19 #include "absl/status/status.h"
20 #include "absl/time/time.h"
32 "Routing: forbids use of Large Neighborhood Search.");
34 "Routing: forbids use of Full-path Large Neighborhood Search.");
36 "Routing: forbids use of Relocate neighborhood.");
37 ABSL_FLAG(
bool, routing_no_relocate_neighbors,
true,
38 "Routing: forbids use of RelocateNeighbors neighborhood.");
40 "Routing: forbids use of RelocateSubtrips neighborhood.");
42 "Routing: forbids use of Exchange neighborhood.");
44 "Routing: forbids use of ExchangeSubtrips neighborhood.");
46 "Routing: forbids use of Cross neighborhood.");
48 "Routing: forbids use of 2Opt neighborhood.");
50 "Routing: forbids use of OrOpt neighborhood.");
52 "Routing: forbids use of MakeActive/SwapActive/MakeInactive "
55 "Routing: forbids use of LKH neighborhood.");
56 ABSL_FLAG(
bool, routing_no_relocate_expensive_chain,
false,
57 "Routing: forbids use of RelocateExpensiveChain operator.");
59 "Routing: forbids use of TSPOpt neighborhood.");
61 "Routing: forbids use of TSPLNS neighborhood.");
62 ABSL_FLAG(
bool, routing_use_chain_make_inactive,
false,
63 "Routing: use chain version of MakeInactive neighborhood.");
64 ABSL_FLAG(
bool, routing_use_extended_swap_active,
false,
65 "Routing: use extended version of SwapActive neighborhood.");
68 ABSL_FLAG(
bool, routing_guided_local_search,
false,
"Routing: use GLS.");
69 ABSL_FLAG(
double, routing_guided_local_search_lambda_coefficient, 0.1,
70 "Lambda coefficient in GLS.");
72 "Routing: use simulated annealing.");
73 ABSL_FLAG(
bool, routing_tabu_search,
false,
"Routing: use tabu search.");
75 "Routing: use tabu search based on a list of values.");
79 "Routing: number of solutions limit.");
82 "Routing: time limit in ms for LNS sub-decisionbuilder.");
86 "Routing first solution heuristic. See SetupParametersFromFlags "
87 "in the code to get a full list.");
88 ABSL_FLAG(
bool, routing_use_filtered_first_solutions,
true,
89 "Use filtered version of first solution heuristics if available.");
91 "Ratio of neighbors to consider for each node when "
92 "constructing the savings.");
94 "Add savings related to reverse arcs when finding the nearest "
95 "neighbors of the nodes.");
97 "Coefficient of the cost of the arc for which the saving value "
98 "is being computed.");
99 ABSL_FLAG(
double, cheapest_insertion_farthest_seeds_ratio, 0,
100 "Ratio of available vehicles in the model on which farthest "
101 "nodes of the model are inserted as seeds.");
102 ABSL_FLAG(
double, cheapest_insertion_first_solution_neighbors_ratio, 1.0,
103 "Ratio of nodes considered as neighbors in the "
104 "GlobalCheapestInsertion first solution heuristic.");
106 "Routing: use a complete depth-first search.");
107 ABSL_FLAG(
double, routing_optimization_step, 0.0,
"Optimization step.");
108 ABSL_FLAG(
int, routing_number_of_solutions_to_collect, 1,
109 "Number of solutions to collect.");
110 ABSL_FLAG(
int, routing_relocate_expensive_chain_num_arcs_to_consider, 4,
111 "Number of arcs to consider in the RelocateExpensiveChain "
112 "neighborhood operator.");
116 "Use constraints with light propagation in routing model.");
119 ABSL_FLAG(
bool, routing_cache_callbacks,
false,
"Cache callback calls.");
121 "Maximum cache size when callback caching is on.");
124 ABSL_FLAG(
bool, routing_trace,
false,
"Routing: trace search.");
125 ABSL_FLAG(
bool, routing_profile,
false,
"Routing: profile search.");
129 "Routing: use homogeneous cost model when possible.");
131 "Use gzip to compress the trail, zippy otherwise.");
137 const std::map<std::string, FirstSolutionStrategy::Value>
138 first_solution_string_to_parameters = {
139 {
"PathCheapestArc", FirstSolutionStrategy::PATH_CHEAPEST_ARC},
140 {
"PathMostConstrainedArc",
141 FirstSolutionStrategy::PATH_MOST_CONSTRAINED_ARC},
142 {
"EvaluatorStrategy", FirstSolutionStrategy::EVALUATOR_STRATEGY},
143 {
"Savings", FirstSolutionStrategy::SAVINGS},
144 {
"Sweep", FirstSolutionStrategy::SWEEP},
145 {
"Christofides", FirstSolutionStrategy::CHRISTOFIDES},
146 {
"AllUnperformed", FirstSolutionStrategy::ALL_UNPERFORMED},
147 {
"BestInsertion", FirstSolutionStrategy::BEST_INSERTION},
148 {
"GlobalCheapestInsertion",
149 FirstSolutionStrategy::PARALLEL_CHEAPEST_INSERTION},
150 {
"SequentialGlobalCheapestInsertion",
151 FirstSolutionStrategy::SEQUENTIAL_CHEAPEST_INSERTION},
152 {
"LocalCheapestInsertion",
153 FirstSolutionStrategy::LOCAL_CHEAPEST_INSERTION},
154 {
"GlobalCheapestArc", FirstSolutionStrategy::GLOBAL_CHEAPEST_ARC},
155 {
"LocalCheapestArc", FirstSolutionStrategy::LOCAL_CHEAPEST_ARC},
156 {
"DefaultStrategy", FirstSolutionStrategy::FIRST_UNBOUND_MIN_VALUE},
157 {
"", FirstSolutionStrategy::FIRST_UNBOUND_MIN_VALUE}};
160 absl::GetFlag(FLAGS_routing_first_solution), &strategy)) {
161 parameters->set_first_solution_strategy(strategy);
163 parameters->set_use_unfiltered_first_solution_strategy(
164 !absl::GetFlag(FLAGS_routing_use_filtered_first_solutions));
166 absl::GetFlag(FLAGS_savings_neighbors_ratio));
167 parameters->set_savings_max_memory_usage_bytes(6e9);
169 absl::GetFlag(FLAGS_savings_add_reverse_arcs));
171 absl::GetFlag(FLAGS_savings_arc_coefficient));
172 parameters->set_cheapest_insertion_farthest_seeds_ratio(
173 absl::GetFlag(FLAGS_cheapest_insertion_farthest_seeds_ratio));
174 parameters->set_cheapest_insertion_first_solution_neighbors_ratio(
175 absl::GetFlag(FLAGS_cheapest_insertion_first_solution_neighbors_ratio));
180 if (absl::GetFlag(FLAGS_routing_tabu_search)) {
182 LocalSearchMetaheuristic::TABU_SEARCH);
183 }
else if (absl::GetFlag(FLAGS_routing_generic_tabu_search)) {
185 LocalSearchMetaheuristic::GENERIC_TABU_SEARCH);
186 }
else if (absl::GetFlag(FLAGS_routing_simulated_annealing)) {
188 LocalSearchMetaheuristic::SIMULATED_ANNEALING);
189 }
else if (absl::GetFlag(FLAGS_routing_guided_local_search)) {
191 LocalSearchMetaheuristic::GUIDED_LOCAL_SEARCH);
193 parameters->set_guided_local_search_lambda_coefficient(
194 absl::GetFlag(FLAGS_routing_guided_local_search_lambda_coefficient));
204 parameters->set_cheapest_insertion_ls_operator_neighbors_ratio(1.0);
205 RoutingSearchParameters::LocalSearchNeighborhoodOperators*
const
206 local_search_operators =
parameters->mutable_local_search_operators();
210 local_search_operators->set_use_relocate_pair(
BOOL_TRUE);
211 local_search_operators->set_use_light_relocate_pair(
BOOL_TRUE);
212 local_search_operators->set_use_exchange_pair(
BOOL_TRUE);
213 local_search_operators->set_use_relocate_and_make_active(
BOOL_FALSE);
214 local_search_operators->set_use_node_pair_swap_active(
BOOL_FALSE);
215 local_search_operators->set_use_cross_exchange(
BOOL_FALSE);
216 local_search_operators->set_use_global_cheapest_insertion_path_lns(
BOOL_TRUE);
217 local_search_operators->set_use_local_cheapest_insertion_path_lns(
BOOL_TRUE);
218 local_search_operators
219 ->set_use_relocate_path_global_cheapest_insertion_insert_unperformed(
221 local_search_operators->set_use_global_cheapest_insertion_expensive_chain_lns(
223 local_search_operators->set_use_local_cheapest_insertion_expensive_chain_lns(
225 local_search_operators->set_use_global_cheapest_insertion_close_nodes_lns(
227 local_search_operators->set_use_local_cheapest_insertion_close_nodes_lns(
230 local_search_operators->set_use_relocate(
231 ToOptionalBoolean(!absl::GetFlag(FLAGS_routing_no_relocate)));
232 local_search_operators->set_use_relocate_neighbors(
233 ToOptionalBoolean(!absl::GetFlag(FLAGS_routing_no_relocate_neighbors)));
234 local_search_operators->set_use_relocate_subtrip(
235 ToOptionalBoolean(!absl::GetFlag(FLAGS_routing_no_relocate_subtrip)));
236 local_search_operators->set_use_exchange_subtrip(
237 ToOptionalBoolean(!absl::GetFlag(FLAGS_routing_no_exchange_subtrip)));
238 local_search_operators->set_use_exchange(
239 ToOptionalBoolean(!absl::GetFlag(FLAGS_routing_no_exchange)));
240 local_search_operators->set_use_cross(
241 ToOptionalBoolean(!absl::GetFlag(FLAGS_routing_no_cross)));
242 local_search_operators->set_use_two_opt(
243 ToOptionalBoolean(!absl::GetFlag(FLAGS_routing_no_2opt)));
244 local_search_operators->set_use_or_opt(
245 ToOptionalBoolean(!absl::GetFlag(FLAGS_routing_no_oropt)));
246 local_search_operators->set_use_lin_kernighan(
247 ToOptionalBoolean(!absl::GetFlag(FLAGS_routing_no_lkh)));
248 local_search_operators->set_use_relocate_expensive_chain(ToOptionalBoolean(
249 !absl::GetFlag(FLAGS_routing_no_relocate_expensive_chain)));
250 local_search_operators->set_use_tsp_opt(
251 ToOptionalBoolean(!absl::GetFlag(FLAGS_routing_no_tsp)));
252 local_search_operators->set_use_make_active(
253 ToOptionalBoolean(!absl::GetFlag(FLAGS_routing_no_make_active)));
254 local_search_operators->set_use_make_inactive(
255 ToOptionalBoolean(!absl::GetFlag(FLAGS_routing_use_chain_make_inactive) &&
256 !absl::GetFlag(FLAGS_routing_no_make_active)));
257 local_search_operators->set_use_make_chain_inactive(
258 ToOptionalBoolean(absl::GetFlag(FLAGS_routing_use_chain_make_inactive) &&
259 !absl::GetFlag(FLAGS_routing_no_make_active)));
260 local_search_operators->set_use_swap_active(ToOptionalBoolean(
261 !absl::GetFlag(FLAGS_routing_use_extended_swap_active) &&
262 !absl::GetFlag(FLAGS_routing_no_make_active)));
263 local_search_operators->set_use_extended_swap_active(
264 ToOptionalBoolean(absl::GetFlag(FLAGS_routing_use_extended_swap_active) &&
265 !absl::GetFlag(FLAGS_routing_no_make_active)));
266 local_search_operators->set_use_path_lns(
267 ToOptionalBoolean(!absl::GetFlag(FLAGS_routing_no_lns)));
268 local_search_operators->set_use_inactive_lns(
269 ToOptionalBoolean(!absl::GetFlag(FLAGS_routing_no_lns)));
270 local_search_operators->set_use_full_path_lns(
271 ToOptionalBoolean(!absl::GetFlag(FLAGS_routing_no_fullpathlns)));
272 local_search_operators->set_use_tsp_lns(
273 ToOptionalBoolean(!absl::GetFlag(FLAGS_routing_no_tsplns)));
278 parameters->set_use_depth_first_search(absl::GetFlag(FLAGS_routing_dfs));
282 absl::GetFlag(FLAGS_routing_optimization_step));
283 parameters->set_number_of_solutions_to_collect(
284 absl::GetFlag(FLAGS_routing_number_of_solutions_to_collect));
285 parameters->set_solution_limit(absl::GetFlag(FLAGS_routing_solution_limit));
286 if (absl::GetFlag(FLAGS_routing_time_limit) !=
kint64max) {
288 absl::Milliseconds(absl::GetFlag(FLAGS_routing_time_limit)),
291 if (absl::GetFlag(FLAGS_routing_lns_time_limit) !=
kint64max) {
293 absl::Milliseconds(absl::GetFlag(FLAGS_routing_lns_time_limit)),
301 !absl::GetFlag(FLAGS_routing_use_light_propagation));
302 parameters->set_log_search(absl::GetFlag(FLAGS_routing_trace));
304 parameters->set_relocate_expensive_chain_num_arcs_to_consider(absl::GetFlag(
305 FLAGS_routing_relocate_expensive_chain_num_arcs_to_consider));
306 parameters->set_heuristic_expensive_chain_lns_num_arcs_to_consider(4);
307 parameters->set_heuristic_close_nodes_lns_num_nodes(5);
308 parameters->set_continuous_scheduling_solver(RoutingSearchParameters::GLOP);
309 parameters->set_mixed_integer_scheduling_solver(
310 RoutingSearchParameters::CP_SAT);
321 LOG_IF(DFATAL, !error.empty())
322 <<
"Error in the routing search parameters built from flags: " << error;
328 ConstraintSolverParameters*
const solver_parameters =
332 absl::GetFlag(FLAGS_routing_use_homogeneous_costs));
333 if (absl::GetFlag(FLAGS_routing_cache_callbacks)) {
335 absl::GetFlag(FLAGS_routing_max_cache_size));
337 solver_parameters->set_profile_local_search(
338 absl::GetFlag(FLAGS_routing_profile));