Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1473,6 +1473,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
}
```

### Solution Tracing

```ruby
Expand Down
26 changes: 26 additions & 0 deletions ext/or-tools/routing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,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<double>(Symbol("improvement_rate_coefficient"));
const int distance =
value.get<int>(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<RoutingIndexManager>(m, "RoutingIndexManager")
Expand Down
25 changes: 24 additions & 1 deletion test/routing_solution_trace_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,28 @@ def test_keeps_aggregates_after_samples_are_truncated
assert_operator values[:improvement_count], :>, 1
end

def test_native_improvement_limit_stops_search
baseline_routing = build_routing
baseline_trace = baseline_routing.enable_solution_trace
baseline_routing.solve_with_parameters(search_parameters(solution_limit: 500))

routing = build_routing
trace = routing.enable_solution_trace
solution = routing.solve_with_parameters(
search_parameters(
solution_limit: 500,
improvement_limit_parameters: {
improvement_rate_coefficient: 0.01,
improvement_rate_solutions_distance: 1
}
)
)

assert_equal 500, baseline_trace.to_h[:solution_count]
assert_operator trace.to_h[:solution_count], :<, 500
assert_equal solution.objective_value, trace.to_h[:best_solution_objective]
end

def test_resets_for_warm_solves
routing = build_routing
trace = routing.enable_solution_trace(
Expand Down Expand Up @@ -239,12 +261,13 @@ def build_routing
routing
end

def search_parameters(solution_limit: nil, time_limit: nil)
def search_parameters(solution_limit: nil, time_limit: nil, improvement_limit_parameters: nil)
parameters = ORTools.default_routing_search_parameters
parameters.first_solution_strategy = :path_cheapest_arc
parameters.local_search_metaheuristic = :guided_local_search
parameters.solution_limit = solution_limit if solution_limit
parameters.time_limit = time_limit if time_limit
parameters.improvement_limit_parameters = improvement_limit_parameters if improvement_limit_parameters
parameters
end

Expand Down
14 changes: 14 additions & 0 deletions test/routing_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down