23#include "absl/functional/bind_front.h"
24#include "absl/log/check.h"
28#include "ortools/constraint_solver/routing_ils.pb.h"
29#include "ortools/constraint_solver/routing_parameters.pb.h"
36GlobalCheapestInsertionFilteredHeuristic::GlobalCheapestInsertionParameters
37MakeGlobalCheapestInsertionParameters(
38 const RoutingSearchParameters& search_parameters,
bool is_sequential) {
39 GlobalCheapestInsertionFilteredHeuristic::GlobalCheapestInsertionParameters
41 gci_parameters.is_sequential = is_sequential;
42 gci_parameters.farthest_seeds_ratio =
43 search_parameters.cheapest_insertion_farthest_seeds_ratio();
44 gci_parameters.neighbors_ratio =
45 search_parameters.cheapest_insertion_first_solution_neighbors_ratio();
46 gci_parameters.min_neighbors =
47 search_parameters.cheapest_insertion_first_solution_min_neighbors();
48 gci_parameters.use_neighbors_ratio_for_initialization =
50 .cheapest_insertion_first_solution_use_neighbors_ratio_for_initialization();
51 gci_parameters.add_unperformed_entries =
52 search_parameters.cheapest_insertion_add_unperformed_entries();
53 return gci_parameters;
57std::unique_ptr<RuinProcedure> MakeRuinProcedure(
60 case RuinStrategy::UNSET:
61 LOG(ERROR) <<
"Unset ruin procedure, using "
62 "RuinStrategy::SPATIALLY_CLOSE_ROUTES_REMOVAL.";
64 case RuinStrategy::SPATIALLY_CLOSE_ROUTES_REMOVAL:
65 return std::make_unique<CloseRoutesRemovalRuinProcedure>(
69 LOG(ERROR) <<
"Unsupported ruin procedure.";
75std::unique_ptr<RoutingFilteredHeuristic> MakeRecreateProcedure(
77 std::function<
bool()> stop_search,
78 LocalSearchFilterManager* filter_manager) {
79 switch (
parameters.iterated_local_search_parameters()
80 .ruin_recreate_parameters()
81 .recreate_strategy()) {
82 case FirstSolutionStrategy::UNSET:
83 LOG(ERROR) <<
"Unset recreate procedure, using "
84 "FirstSolutionStrategy::LOCAL_CHEAPEST_INSERTION";
86 case FirstSolutionStrategy::LOCAL_CHEAPEST_INSERTION:
87 return std::make_unique<LocalCheapestInsertionFilteredHeuristic>(
88 model, std::move(stop_search),
89 absl::bind_front(&RoutingModel::GetArcCostForVehicle,
model),
90 parameters.local_cheapest_cost_insertion_pickup_delivery_strategy(),
91 filter_manager,
model->GetBinCapacities());
92 case FirstSolutionStrategy::LOCAL_CHEAPEST_COST_INSERTION:
93 return std::make_unique<LocalCheapestInsertionFilteredHeuristic>(
94 model, std::move(stop_search),
96 parameters.local_cheapest_cost_insertion_pickup_delivery_strategy(),
97 filter_manager,
model->GetBinCapacities());
98 case FirstSolutionStrategy::SEQUENTIAL_CHEAPEST_INSERTION: {
99 GlobalCheapestInsertionFilteredHeuristic::
100 GlobalCheapestInsertionParameters gci_parameters =
101 MakeGlobalCheapestInsertionParameters(
parameters,
103 return std::make_unique<GlobalCheapestInsertionFilteredHeuristic>(
104 model, std::move(stop_search),
105 absl::bind_front(&RoutingModel::GetArcCostForVehicle,
model),
106 [
model](int64_t i) {
return model->UnperformedPenaltyOrValue(0, i); },
107 filter_manager, gci_parameters);
109 case FirstSolutionStrategy::PARALLEL_CHEAPEST_INSERTION: {
110 GlobalCheapestInsertionFilteredHeuristic::
111 GlobalCheapestInsertionParameters gci_parameters =
112 MakeGlobalCheapestInsertionParameters(
parameters,
114 return std::make_unique<GlobalCheapestInsertionFilteredHeuristic>(
115 model, std::move(stop_search),
116 absl::bind_front(&RoutingModel::GetArcCostForVehicle,
model),
117 [
model](int64_t i) {
return model->UnperformedPenaltyOrValue(0, i); },
118 filter_manager, gci_parameters);
121 LOG(ERROR) <<
"Unsupported recreate procedure.";
130class GreedyDescentAcceptanceCriterion :
public NeighborAcceptanceCriterion {
132 bool Accept(
const Assignment* candidate,
133 const Assignment* reference)
const override {
134 return candidate->ObjectiveValue() < reference->ObjectiveValue();
141 RoutingModel*
model,
size_t num_routes)
143 neighbors_manager_(
model->GetOrCreateNodeNeighborsByCostClass(
146 num_routes_(num_routes),
148 customer_dist_(0,
model->Size() - 1),
149 removed_routes_(
model->vehicles()) {}
155 if (num_routes_ > 0 && HasPerformedNodes(assignment)) {
159 seed_node = customer_dist_(rnd_);
160 seed_route = assignment->
Value(model_.VehicleVar(seed_node));
161 }
while (model_.IsStart(seed_node) || seed_route == -1);
162 DCHECK(!model_.IsEnd(seed_node));
165 model_.GetCostClassIndexOfVehicle(seed_route);
167 const std::vector<int>& neighbors =
168 neighbors_manager_->GetNeighborsOfNodeForCostClass(
171 for (
int neighbor : neighbors) {
172 const int64_t route = assignment->
Value(model_.VehicleVar(neighbor));
173 if (route < 0 || removed_routes_[route]) {
176 removed_routes_.
Set(route);
184 return [
this, assignment](int64_t node) {
186 if (model_.IsStart(node)) {
187 const int route = assignment->
Value(model_.VehicleVar(node));
188 if (removed_routes_[route]) {
189 return model_.End(route);
192 return assignment->
Value(model_.NextVar(node));
196bool CloseRoutesRemovalRuinProcedure::HasPerformedNodes(
198 for (
int v = 0; v < model_.vehicles(); ++v) {
199 if (model_.Next(*assignment, model_.Start(v)) != model_.End(v)) {
209 const Assignment* assignment, std::unique_ptr<RuinProcedure> ruin,
210 std::unique_ptr<RoutingFilteredHeuristic> recreate)
211 : assignment_(*assignment),
212 ruin_(
std::move(ruin)),
213 recreate_(
std::move(recreate)) {}
216 Assignment*
const new_assignment = Recreate(ruin_->Ruin(&assignment_));
217 if (new_assignment) {
226 Assignment* Recreate(
const std::function<int64_t(int64_t)>& next_accessor) {
227 return recreate_->BuildSolutionFromRoutes(next_accessor);
230 const Assignment& assignment_;
231 std::unique_ptr<RuinProcedure> ruin_;
232 std::unique_ptr<RoutingFilteredHeuristic> recreate_;
237 const Assignment* assignment, std::function<
bool()> stop_search,
239 std::unique_ptr<RuinProcedure> ruin = MakeRuinProcedure(
240 parameters.iterated_local_search_parameters().ruin_recreate_parameters(),
243 std::unique_ptr<RoutingFilteredHeuristic> recreate = MakeRecreateProcedure(
247 assignment, std::move(ruin), std::move(recreate)));
252 const Assignment* assignment, std::function<
bool()> stop_search,
255 parameters.iterated_local_search_parameters().perturbation_strategy()) {
256 case PerturbationStrategy::UNSET:
257 LOG(ERROR) <<
"Unset perturbation strategy, using "
258 "PerturbationStrategy::RUIN_AND_RECREATE.";
260 case PerturbationStrategy::RUIN_AND_RECREATE:
262 std::move(stop_search),
265 LOG(ERROR) <<
"Unsupported perturbation strategy.";
272 CHECK(
parameters.has_iterated_local_search_parameters());
273 switch (
parameters.iterated_local_search_parameters().acceptance_strategy()) {
274 case AcceptanceStrategy::UNSET:
275 LOG(ERROR) <<
"Unset acceptance strategy, using "
276 "AcceptanceStrategy::GREEDY_DESCENT.";
278 case AcceptanceStrategy::GREEDY_DESCENT:
279 return std::make_unique<GreedyDescentAcceptanceCriterion>();
281 LOG(ERROR) <<
"Unsupported acceptance strategy.";
int64_t Value(const IntVar *var) const
CloseRoutesRemovalRuinProcedure(RoutingModel *model, size_t num_routes)
std::function< int64_t(int64_t)> Ruin(const Assignment *assignment) override
Decision * Next(Solver *const solver) override
RuinAndRecreateDecisionBuilder(const Assignment *assignment, std::unique_ptr< RuinProcedure > ruin, std::unique_ptr< RoutingFilteredHeuristic > recreate)
For the time being, Solver is neither MT_SAFE nor MT_HOT.
void Fail()
Abandon the current branch in the search tree. A backtrack will follow.
void Set(IntegerType index)
int NumberOfSetCallsWithDifferentArguments() const
In SWIG mode, we don't want anything besides these top-level includes.
std::unique_ptr< NeighborAcceptanceCriterion > MakeNeighborAcceptanceCriterion(const RoutingSearchParameters ¶meters)
Returns a neighbor acceptance criterion based on the given parameters.
DecisionBuilder * MakeRuinAndRecreateDecisionBuilder(const RoutingSearchParameters ¶meters, RoutingModel *model, const Assignment *assignment, std::function< bool()> stop_search, LocalSearchFilterManager *filter_manager)
DecisionBuilder * MakePerturbationDecisionBuilder(const RoutingSearchParameters ¶meters, RoutingModel *model, const Assignment *assignment, std::function< bool()> stop_search, LocalSearchFilterManager *filter_manager)
RoutingModel::CostClassIndex cost_class_index
The cost class of the vehicle.