diff --git a/README.md b/README.md index 14c92a3..ad72c04 100644 --- a/README.md +++ b/README.md @@ -1472,6 +1472,15 @@ routing.solve( ) ``` +Native improvement-rate stopping is available through search parameters: + +```ruby +search_parameters.improvement_limit_parameters = { + improvement_rate_coefficient: 0.01, + improvement_rate_solutions_distance: 5 +} +``` + ## Bin Packing ### The Knapsack Problem diff --git a/ext/or-tools/routing.cpp b/ext/or-tools/routing.cpp index 88ff5bc..0364e3b 100644 --- a/ext/or-tools/routing.cpp +++ b/ext/or-tools/routing.cpp @@ -22,6 +22,7 @@ using operations_research::RoutingSearchStatus; using Rice::Array; using Rice::Class; +using Rice::Hash; using Rice::Module; using Rice::Object; using Rice::String; @@ -182,6 +183,32 @@ void init_routing(Rice::Module& m) { "lns_time_limit=", [](RoutingSearchParameters& self, int64_t value) { self.mutable_lns_time_limit()->set_seconds(value); + }) + .define_method( + "improvement_limit_parameters", + [](RoutingSearchParameters& self) -> Object { + if (!self.has_improvement_limit_parameters()) { + return Object(Qnil); + } + + const auto& parameters = self.improvement_limit_parameters(); + Hash result; + result[Symbol("improvement_rate_coefficient")] = + parameters.improvement_rate_coefficient(); + result[Symbol("improvement_rate_solutions_distance")] = + parameters.improvement_rate_solutions_distance(); + return result; + }) + .define_method( + "improvement_limit_parameters=", + [](RoutingSearchParameters& self, Hash value) { + const double coefficient = + value.get(Symbol("improvement_rate_coefficient")); + const int distance = + value.get(Symbol("improvement_rate_solutions_distance")); + auto* parameters = self.mutable_improvement_limit_parameters(); + parameters->set_improvement_rate_coefficient(coefficient); + parameters->set_improvement_rate_solutions_distance(distance); }); Rice::define_class_under(m, "RoutingIndexManager") diff --git a/test/routing_test.rb b/test/routing_test.rb index 9f9fe7c..9a7074e 100644 --- a/test/routing_test.rb +++ b/test/routing_test.rb @@ -907,6 +907,20 @@ def test_search_parameters search_parameters.first_solution_strategy = :path_cheapest_arc search_parameters.local_search_metaheuristic = :guided_local_search search_parameters.log_search = true + assert_nil search_parameters.improvement_limit_parameters + + search_parameters.improvement_limit_parameters = { + improvement_rate_coefficient: 0.01, + improvement_rate_solutions_distance: 5 + } + + assert_equal( + { + improvement_rate_coefficient: 0.01, + improvement_rate_solutions_distance: 5 + }, + search_parameters.improvement_limit_parameters + ) end def test_set_allowed_vehicles_for_index