From 1f844fb0d9840b79f0ac61dd42cd4dee60a72a21 Mon Sep 17 00:00:00 2001 From: Eric Kreutzer Date: Fri, 2 Oct 2026 05:25:32 -0600 Subject: [PATCH] feat(routing): Expose native search limit check --- README.md | 3 +++ ext/or-tools/routing.cpp | 1 + test/routing_time_limit_test.rb | 13 +++++++++++++ 3 files changed, 17 insertions(+) diff --git a/README.md b/README.md index 35bf1c4..0178080 100644 --- a/README.md +++ b/README.md @@ -1485,6 +1485,9 @@ assignment = routing.read_assignment_from_routes(routes, true) The limit is checked cooperatively, so the call can exceed it. Restoration can return a valid assignment found before the limit. A `nil` result does not distinguish an invalid route from a limit reached before finding a solution. +Call `routing.check_limit` immediately after restoration to check whether the +native search limit was reached. It returns a boolean, like Python's +`routing.CheckLimit()`. A subsequent solve uses the time limit in its own search parameters. Native improvement-rate stopping is available through search parameters: diff --git a/ext/or-tools/routing.cpp b/ext/or-tools/routing.cpp index 73ec71d..dbe7951 100644 --- a/ext/or-tools/routing.cpp +++ b/ext/or-tools/routing.cpp @@ -865,6 +865,7 @@ void init_routing(Rice::Module& m) { self.CloseModel(); } }) + .define_method("check_limit", [](RoutingModel& self) { return self.CheckLimit(); }) .define_method( "update_time_limit", [](RoutingModel& self, double seconds) { diff --git a/test/routing_time_limit_test.rb b/test/routing_time_limit_test.rb index 0f71d94..f20d70c 100644 --- a/test/routing_time_limit_test.rb +++ b/test/routing_time_limit_test.rb @@ -8,6 +8,7 @@ def test_restoration_limit_can_be_reset_after_timeout assert_nil routing.read_assignment_from_routes([[1, 2]], true) assert_equal :fail, routing.status + assert_equal true, routing.check_limit routing.update_time_limit(0.5) assignment = routing.read_assignment_from_routes([[1, 2]], true) @@ -15,6 +16,18 @@ def test_restoration_limit_can_be_reset_after_timeout refute_nil assignment assert_equal 4, assignment.objective_value assert_equal :success, routing.status + assert_equal false, routing.check_limit + end + + def test_infeasible_restoration_does_not_cross_limit + routing = build_routing + transit = routing.register_transit_matrix([[0, 1, 2], [1, 0, 1], [2, 1, 0]]) + routing.add_dimension(transit, 0, 3, true, "Distance") + routing.close_model + routing.update_time_limit(1) + + assert_nil routing.read_assignment_from_routes([[1, 2]], true) + assert_equal false, routing.check_limit end def test_solve_replaces_restoration_time_limit