@@ -261,189 +261,6 @@ const Assignment* SolveFromAssignmentWithAlternativeSolversAndParameters(
261261 return best_assignment;
262262}
263263
264- namespace {
265- void ConvertAssignment (const RoutingModel* src_model, const Assignment* src,
266- const RoutingModel* dst_model, Assignment* dst) {
267- DCHECK_EQ (src_model->Nexts ().size (), dst_model->Nexts ().size ());
268- DCHECK_NE (src, nullptr );
269- DCHECK_EQ (src_model->solver (), src->solver ());
270- DCHECK_EQ (dst_model->solver (), dst->solver ());
271- for (int i = 0 ; i < src_model->Nexts ().size (); i++) {
272- IntVar* const dst_next_var = dst_model->NextVar (i);
273- if (!dst->Contains (dst_next_var)) {
274- dst->Add (dst_next_var);
275- }
276- dst->SetValue (dst_next_var, src->Value (src_model->NextVar (i)));
277- }
278- }
279-
280- bool AreAssignmentsEquivalent (const RoutingModel& model,
281- const Assignment& assignment1,
282- const Assignment& assignment2) {
283- for (IntVar* next_var : model.Nexts ()) {
284- if (assignment1.Value (next_var) != assignment2.Value (next_var)) {
285- return false ;
286- }
287- }
288- return true ;
289- }
290-
291- absl::Duration GetTimeLimit (const RoutingSearchParameters& search_parameters) {
292- return search_parameters.has_time_limit ()
293- ? util_time::DecodeGoogleApiProto (search_parameters.time_limit ())
294- .value ()
295- : absl::InfiniteDuration ();
296- }
297-
298- // TODO(user): Refactor this function with other versions living in
299- // routing.cc.
300- // TODO(user): Should we update solution limits as well?
301- bool UpdateTimeLimits (Solver* solver, int64_t start_time_ms,
302- absl::Duration time_limit,
303- RoutingSearchParameters& search_parameters) {
304- if (!search_parameters.has_time_limit ()) return true ;
305- const absl::Duration elapsed_time =
306- absl::Milliseconds (solver->wall_time () - start_time_ms);
307- const absl::Duration time_left =
308- std::min (time_limit - elapsed_time, GetTimeLimit (search_parameters));
309- if (time_left <= absl::ZeroDuration ()) return false ;
310- const absl::Status status = util_time::EncodeGoogleApiProto (
311- time_left, search_parameters.mutable_time_limit ());
312- DCHECK_OK (status);
313- return true ;
314- }
315- } // namespace
316-
317- const Assignment* SolveWithAlternativeSolvers (
318- RoutingModel* primary_model,
319- const std::vector<RoutingModel*>& alternative_models,
320- const RoutingSearchParameters& parameters,
321- int max_non_improving_iterations) {
322- return SolveFromAssignmentWithAlternativeSolvers (
323- /* assignment=*/ nullptr , primary_model, alternative_models, parameters,
324- max_non_improving_iterations);
325- }
326-
327- const Assignment* SolveFromAssignmentWithAlternativeSolvers (
328- const Assignment* assignment, RoutingModel* primary_model,
329- const std::vector<RoutingModel*>& alternative_models,
330- const RoutingSearchParameters& parameters,
331- int max_non_improving_iterations) {
332- return SolveFromAssignmentWithAlternativeSolversAndParameters (
333- assignment, primary_model, parameters, alternative_models, {},
334- max_non_improving_iterations);
335- }
336-
337- const Assignment* SolveFromAssignmentWithAlternativeSolversAndParameters (
338- const Assignment* assignment, RoutingModel* primary_model,
339- const RoutingSearchParameters& primary_parameters,
340- const std::vector<RoutingModel*>& alternative_models,
341- const std::vector<RoutingSearchParameters>& alternative_parameters,
342- int max_non_improving_iterations) {
343- const int64_t start_time_ms = primary_model->solver ()->wall_time ();
344- if (max_non_improving_iterations < 0 ) return nullptr ;
345- // Shortcut if no alternative models will be explored.
346- if (max_non_improving_iterations == 0 || alternative_models.empty ()) {
347- return primary_model->SolveFromAssignmentWithParameters (assignment,
348- primary_parameters);
349- }
350- RoutingSearchParameters mutable_search_parameters = primary_parameters;
351- // The first alternating phases are limited to greedy descent. The final pass
352- // at the end of this function will actually use the metaheuristic if needed.
353- // TODO(user): Add support for multiple metaheuristics.
354- const LocalSearchMetaheuristic_Value metaheuristic =
355- mutable_search_parameters.local_search_metaheuristic ();
356- const bool run_metaheuristic_phase =
357- metaheuristic != LocalSearchMetaheuristic::GREEDY_DESCENT &&
358- metaheuristic != LocalSearchMetaheuristic::AUTOMATIC;
359- if (run_metaheuristic_phase) {
360- mutable_search_parameters.set_local_search_metaheuristic (
361- LocalSearchMetaheuristic::GREEDY_DESCENT);
362- }
363- std::vector<RoutingSearchParameters> mutable_alternative_parameters =
364- alternative_parameters;
365- DCHECK (mutable_alternative_parameters.empty () ||
366- mutable_alternative_parameters.size () == alternative_models.size ());
367- for (RoutingSearchParameters& mutable_alternative_parameter :
368- mutable_alternative_parameters) {
369- if (!mutable_alternative_parameter.has_time_limit () &&
370- mutable_search_parameters.has_time_limit ()) {
371- *mutable_alternative_parameter.mutable_time_limit () =
372- mutable_search_parameters.time_limit ();
373- }
374- }
375- const absl::Duration time_limit = GetTimeLimit (mutable_search_parameters);
376- Assignment* best_assignment = primary_model->solver ()->MakeAssignment ();
377- std::vector<Assignment*> first_solutions;
378- first_solutions.reserve (alternative_models.size ());
379- for (RoutingModel* model : alternative_models) {
380- first_solutions.push_back (model->solver ()->MakeAssignment ());
381- }
382- Assignment* primary_first_solution =
383- primary_model->solver ()->MakeAssignment ();
384- Assignment* current_solution = primary_model->solver ()->MakeAssignment ();
385- DCHECK (assignment == nullptr ||
386- assignment->solver () == primary_model->solver ());
387- const Assignment* solution = primary_model->SolveFromAssignmentWithParameters (
388- assignment, mutable_search_parameters);
389- if (solution == nullptr ) return nullptr ;
390- best_assignment->Copy (solution);
391- int iteration = 0 ;
392- while (iteration < max_non_improving_iterations) {
393- if (best_assignment->ObjectiveValue () > solution->ObjectiveValue ()) {
394- best_assignment->Copy (solution);
395- }
396- current_solution->Copy (solution);
397- for (int i = 0 ; i < alternative_models.size (); ++i) {
398- RoutingSearchParameters& mutable_alternative_parameter =
399- mutable_alternative_parameters.empty ()
400- ? mutable_search_parameters
401- : mutable_alternative_parameters[i];
402- if (!UpdateTimeLimits (primary_model->solver (), start_time_ms, time_limit,
403- mutable_alternative_parameter)) {
404- return best_assignment;
405- }
406- ConvertAssignment (primary_model, solution, alternative_models[i],
407- first_solutions[i]);
408- solution = alternative_models[i]->SolveFromAssignmentWithParameters (
409- first_solutions[i], mutable_alternative_parameter);
410- if (solution == nullptr ) {
411- solution = first_solutions[i];
412- }
413- if (!UpdateTimeLimits (primary_model->solver (), start_time_ms, time_limit,
414- mutable_search_parameters)) {
415- return best_assignment;
416- }
417- ConvertAssignment (alternative_models[i], solution, primary_model,
418- primary_first_solution);
419- solution = primary_model->SolveFromAssignmentWithParameters (
420- primary_first_solution, mutable_search_parameters);
421- if (solution == nullptr ) return best_assignment;
422- }
423- // No modifications done in this iteration, no need to continue.
424- if (AreAssignmentsEquivalent (*primary_model, *solution,
425- *current_solution)) {
426- break ;
427- }
428- // We're back to the best assignment which means we will cycle if we
429- // continue the search.
430- if (AreAssignmentsEquivalent (*primary_model, *solution, *best_assignment)) {
431- break ;
432- }
433- if (solution->ObjectiveValue () >= best_assignment->ObjectiveValue ()) {
434- ++iteration;
435- }
436- }
437- if (run_metaheuristic_phase &&
438- UpdateTimeLimits (primary_model->solver (), start_time_ms, time_limit,
439- mutable_search_parameters)) {
440- mutable_search_parameters.set_local_search_metaheuristic (metaheuristic);
441- return primary_model->SolveFromAssignmentWithParameters (
442- best_assignment, mutable_search_parameters);
443- }
444- return best_assignment;
445- }
446-
447264// --- VehicleTypeCurator ---
448265
449266void VehicleTypeCurator::Reset (const std::function<bool (int )>& store_vehicle) {
0 commit comments