156 #ifndef OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_H_ 157 #define OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_H_ 160 #include <functional> 167 #include "absl/container/flat_hash_map.h" 168 #include "absl/container/flat_hash_set.h" 169 #include "absl/hash/hash.h" 170 #include "absl/time/time.h" 171 #include "ortools/base/adjustable_priority_queue-inl.h" 172 #include "ortools/base/adjustable_priority_queue.h" 173 #include "ortools/base/commandlineflags.h" 174 #include "ortools/base/hash.h" 175 #include "ortools/base/int_type_indexed_vector.h" 176 #include "ortools/base/logging.h" 177 #include "ortools/base/macros.h" 183 #include "ortools/glop/lp_solver.h" 184 #include "ortools/glop/parameters.pb.h" 185 #include "ortools/graph/graph.h" 186 #include "ortools/lp_data/lp_data.h" 187 #include "ortools/lp_data/lp_types.h" 188 #include "ortools/sat/theta_tree.h" 189 #include "ortools/util/range_query_function.h" 190 #include "ortools/util/sorted_interval_list.h" 194 class IntVarFilteredDecisionBuilder;
195 class LocalSearchOperator;
198 using util::ReverseArcListGraph;
214 ROUTING_FAIL_TIMEOUT,
220 enum PickupAndDeliveryPolicy {
222 PICKUP_AND_DELIVERY_NO_ORDER,
224 PICKUP_AND_DELIVERY_LIFO,
226 PICKUP_AND_DELIVERY_FIFO
228 typedef RoutingCostClassIndex CostClassIndex;
229 typedef RoutingDimensionIndex DimensionIndex;
230 typedef RoutingDisjunctionIndex DisjunctionIndex;
231 typedef RoutingVehicleClassIndex VehicleClassIndex;
254 struct StateDependentTransit {
255 RangeIntToIntFunction* transit;
256 RangeMinMaxIndexFunction* transit_plus_identity;
258 typedef std::function<StateDependentTransit(int64, int64)>
259 VariableIndexEvaluator2;
265 int evaluator_index = 0;
287 struct DimensionCost {
288 int64 transit_evaluator_class;
289 int64 cost_coefficient;
291 bool operator<(
const DimensionCost& cost)
const {
292 if (transit_evaluator_class != cost.transit_evaluator_class) {
293 return transit_evaluator_class < cost.transit_evaluator_class;
295 return cost_coefficient < cost.cost_coefficient;
298 std::vector<DimensionCost>
299 dimension_transit_evaluator_class_and_cost_coefficient;
301 explicit CostClass(
int evaluator_index)
302 : evaluator_index(evaluator_index) {}
305 static bool LessThan(
const CostClass& a,
const CostClass& b) {
306 if (a.evaluator_index != b.evaluator_index) {
307 return a.evaluator_index < b.evaluator_index;
309 return a.dimension_transit_evaluator_class_and_cost_coefficient <
310 b.dimension_transit_evaluator_class_and_cost_coefficient;
314 struct VehicleClass {
316 CostClassIndex cost_class_index;
325 int start_equivalence_class;
326 int end_equivalence_class;
329 gtl::ITIVector<DimensionIndex, int64> dimension_start_cumuls_min;
330 gtl::ITIVector<DimensionIndex, int64> dimension_start_cumuls_max;
331 gtl::ITIVector<DimensionIndex, int64> dimension_end_cumuls_min;
332 gtl::ITIVector<DimensionIndex, int64> dimension_end_cumuls_max;
333 gtl::ITIVector<DimensionIndex, int64> dimension_capacities;
336 gtl::ITIVector<DimensionIndex, int64> dimension_evaluator_classes;
338 uint64 unvisitable_nodes_fprint;
341 static bool LessThan(
const VehicleClass& a,
const VehicleClass& b);
343 #endif // defined(SWIG) 346 static const int64 kNoPenalty;
350 static const DisjunctionIndex kNoDisjunction;
354 static const DimensionIndex kNoDimension;
359 explicit RoutingModel(
const RoutingIndexManager& index_manager);
360 RoutingModel(
const RoutingIndexManager& index_manager,
361 const RoutingModelParameters& parameters);
365 int RegisterUnaryTransitCallback(TransitCallback1 callback);
366 int RegisterTransitCallback(TransitCallback2 callback);
367 int RegisterPositiveTransitCallback(TransitCallback2 callback);
368 int RegisterStateDependentTransitCallback(VariableIndexEvaluator2 callback);
369 const TransitCallback2& TransitCallback(
int callback_index)
const {
370 CHECK_LT(callback_index, transit_evaluators_.size());
371 return transit_evaluators_[callback_index];
373 const TransitCallback1& UnaryTransitCallbackOrNull(
int callback_index)
const {
374 CHECK_LT(callback_index, unary_transit_evaluators_.size());
375 return unary_transit_evaluators_[callback_index];
377 const VariableIndexEvaluator2& StateDependentTransitCallback(
378 int callback_index)
const {
379 CHECK_LT(callback_index, state_dependent_transit_evaluators_.size());
380 return state_dependent_transit_evaluators_[callback_index];
405 bool AddDimension(
int evaluator_index, int64 slack_max, int64 capacity,
406 bool fix_start_cumul_to_zero,
const std::string& name);
407 bool AddDimensionWithVehicleTransits(
408 const std::vector<int>& evaluator_indices, int64 slack_max,
409 int64 capacity,
bool fix_start_cumul_to_zero,
const std::string& name);
410 bool AddDimensionWithVehicleCapacity(
int evaluator_index, int64 slack_max,
411 std::vector<int64> vehicle_capacities,
412 bool fix_start_cumul_to_zero,
413 const std::string& name);
414 bool AddDimensionWithVehicleTransitAndCapacity(
415 const std::vector<int>& evaluator_indices, int64 slack_max,
416 std::vector<int64> vehicle_capacities,
bool fix_start_cumul_to_zero,
417 const std::string& name);
424 bool AddConstantDimensionWithSlack(int64 value, int64 capacity,
426 bool fix_start_cumul_to_zero,
427 const std::string& name);
428 bool AddConstantDimension(int64 value, int64 capacity,
429 bool fix_start_cumul_to_zero,
430 const std::string& name) {
431 return AddConstantDimensionWithSlack(value, capacity, 0,
432 fix_start_cumul_to_zero, name);
441 bool AddVectorDimension(std::vector<int64> values, int64 capacity,
442 bool fix_start_cumul_to_zero,
443 const std::string& name);
451 bool AddMatrixDimension(std::vector<std::vector<int64>> values,
452 int64 capacity,
bool fix_start_cumul_to_zero,
453 const std::string& name);
460 bool AddDimensionDependentDimensionWithVehicleCapacity(
461 const std::vector<int>& pure_transits,
462 const std::vector<int>& dependent_transits,
464 std::vector<int64> vehicle_capacities,
bool fix_start_cumul_to_zero,
465 const std::string& name) {
466 return AddDimensionDependentDimensionWithVehicleCapacityInternal(
467 pure_transits, dependent_transits, base_dimension, slack_max,
468 std::move(vehicle_capacities), fix_start_cumul_to_zero, name);
471 bool AddDimensionDependentDimensionWithVehicleCapacity(
473 int64 slack_max, std::vector<int64> vehicle_capacities,
474 bool fix_start_cumul_to_zero,
const std::string& name);
476 bool AddDimensionDependentDimensionWithVehicleCapacity(
478 int64 vehicle_capacity,
bool fix_start_cumul_to_zero,
479 const std::string& name);
480 bool AddDimensionDependentDimensionWithVehicleCapacity(
481 int pure_transit,
int dependent_transit,
483 int64 vehicle_capacity,
bool fix_start_cumul_to_zero,
484 const std::string& name);
487 static RoutingModel::StateDependentTransit MakeStateDependentTransit(
488 const std::function<int64(int64)>& f, int64 domain_start,
501 std::vector<IntVar*> spans,
502 std::vector<IntVar*> total_slacks);
506 std::vector<::std::string> GetAllDimensionNames()
const;
508 const std::vector<RoutingDimension*>& GetDimensions()
const {
509 return dimensions_.get();
512 std::vector<RoutingDimension*> GetDimensionsWithSoftOrSpanCosts()
const;
515 const std::vector<RoutingDimension*>& GetDimensionsForGlobalCumulOptimizers()
517 return dimensions_for_global_optimizer_;
519 const std::vector<RoutingDimension*>& GetDimensionsForLocalCumulOptimizers()
521 return dimensions_for_local_optimizer_;
524 bool HasDimension(
const std::string& dimension_name)
const;
527 const std::string& dimension_name)
const;
531 const std::string& dimension_name)
const;
536 void SetPrimaryConstrainedDimension(
const std::string& dimension_name) {
537 DCHECK(dimension_name.empty() || HasDimension(dimension_name));
538 primary_constrained_dimension_ = dimension_name;
542 const std::string& GetPrimaryConstrainedDimension()
const {
543 return primary_constrained_dimension_;
560 DisjunctionIndex AddDisjunction(
const std::vector<int64>& indices,
561 int64 penalty = kNoPenalty,
562 int64 max_cardinality = 1);
564 const std::vector<DisjunctionIndex>& GetDisjunctionIndices(
566 return index_to_disjunctions_[index];
571 template <
typename F>
572 void ForEachNodeInDisjunctionWithMaxCardinalityFromIndex(
573 int64 index, int64 max_cardinality, F f)
const {
574 for (
const DisjunctionIndex disjunction : GetDisjunctionIndices(index)) {
575 if (disjunctions_[disjunction].value.max_cardinality == max_cardinality) {
576 for (
const int64 d_index : disjunctions_[disjunction].indices) {
582 #if !defined(SWIGPYTHON) 585 const std::vector<int64>& GetDisjunctionIndices(
586 DisjunctionIndex index)
const {
587 return disjunctions_[index].indices;
589 #endif // !defined(SWIGPYTHON) 591 int64 GetDisjunctionPenalty(DisjunctionIndex index)
const {
592 return disjunctions_[index].value.penalty;
596 int64 GetDisjunctionMaxCardinality(DisjunctionIndex index)
const {
597 return disjunctions_[index].value.max_cardinality;
600 int GetNumberOfDisjunctions()
const {
return disjunctions_.size(); }
605 std::vector<std::pair<int64, int64>> GetPerfectBinaryDisjunctions()
const;
611 void IgnoreDisjunctionsAlreadyForcedToZero();
616 void AddSoftSameVehicleConstraint(
const std::vector<int64>& indices,
623 void SetAllowedVehiclesForIndex(
const std::vector<int>&
vehicles,
627 bool IsVehicleAllowedForIndex(
int vehicle, int64 index) {
628 return allowed_vehicles_[index].empty() ||
629 allowed_vehicles_[index].find(vehicle) !=
630 allowed_vehicles_[index].end();
648 void AddPickupAndDelivery(int64 pickup, int64 delivery);
652 void AddPickupAndDeliverySets(DisjunctionIndex pickup_disjunction,
653 DisjunctionIndex delivery_disjunction);
658 const std::vector<std::pair<int, int> >&
659 GetPickupIndexPairs(int64 node_index)
const;
661 const std::vector<std::pair<int, int> >&
662 GetDeliveryIndexPairs(int64 node_index)
const;
667 void SetPickupAndDeliveryPolicyOfAllVehicles(PickupAndDeliveryPolicy policy);
668 void SetPickupAndDeliveryPolicyOfVehicle(PickupAndDeliveryPolicy policy,
670 PickupAndDeliveryPolicy GetPickupAndDeliveryPolicyOfVehicle(
675 int GetNumOfSingletonNodes()
const;
679 const IndexPairs& GetPickupAndDeliveryPairs()
const {
680 return pickup_delivery_pairs_;
682 const std::vector<std::pair<DisjunctionIndex, DisjunctionIndex>>&
683 GetPickupAndDeliveryDisjunctions()
const {
684 return pickup_delivery_disjunctions_;
699 void SetVisitType(int64 index,
int type);
721 return has_hard_type_incompatibilities_;
724 return has_temporal_type_incompatibilities_;
737 int dependent_type, absl::flat_hash_set<int> required_type_alternatives);
742 int dependent_type, absl::flat_hash_set<int> required_type_alternatives);
746 const std::vector<absl::flat_hash_set<int> >&
748 const std::vector<absl::flat_hash_set<int> >&
754 return has_same_vehicle_type_requirements_;
757 return has_temporal_type_requirements_;
813 int64 quadratic_cost_factor);
816 int64 quadratic_cost_factor,
820 return linear_cost_factor_of_vehicle_;
823 return quadratic_cost_factor_of_vehicle_;
827 DCHECK_LT(vehicle, vehicles_);
828 consider_empty_route_costs_[vehicle] = consider_costs;
832 DCHECK_LT(vehicle, vehicles_);
833 return consider_empty_route_costs_[vehicle];
841 return first_solution_evaluator_;
846 first_solution_evaluator_ = std::move(evaluator);
875 const RoutingSearchParameters& search_parameters);
882 const Assignment*
Solve(
const Assignment* assignment =
nullptr);
890 const RoutingSearchParameters& search_parameters,
891 std::vector<const Assignment*>* solutions =
nullptr);
893 const Assignment* assignment,
894 const RoutingSearchParameters& search_parameters,
895 std::vector<const Assignment*>* solutions =
nullptr);
902 Assignment* target_assignment,
const RoutingModel* source_model,
903 const Assignment* source_assignment);
912 Status
status()
const {
return status_; }
920 IntVar*
ApplyLocks(
const std::vector<int64>& locks);
954 const std::vector<std::vector<int64>>& routes,
955 bool ignore_inactive_indices);
973 bool ignore_inactive_indices,
bool close_routes,
974 Assignment*
const assignment)
const;
979 std::vector<std::vector<int64>>*
const routes)
const;
1015 const Assignment* original_assignment, absl::Duration duration_limit);
1030 CHECK(filter !=
nullptr);
1032 LOG(WARNING) <<
"Model is closed, filter addition will be ignored.";
1034 extra_filters_.push_back(filter);
1039 int64
Start(
int vehicle)
const {
return starts_[vehicle]; }
1041 int64
End(
int vehicle)
const {
return ends_[vehicle]; }
1043 bool IsStart(int64 index)
const;
1052 int64
Next(
const Assignment& assignment, int64 index)
const;
1054 bool IsVehicleUsed(
const Assignment& assignment,
int vehicle)
const;
1056 #if !defined(SWIGPYTHON) 1059 const std::vector<IntVar*>&
Nexts()
const {
return nexts_; }
1062 const std::vector<IntVar*>&
VehicleVars()
const {
return vehicle_vars_; }
1063 #endif // !defined(SWIGPYTHON) 1066 IntVar*
NextVar(int64 index)
const {
return nexts_[index]; }
1068 IntVar*
ActiveVar(int64 index)
const {
return active_[index]; }
1072 return vehicle_costs_considered_[vehicle];
1076 IntVar*
VehicleVar(int64 index)
const {
return vehicle_vars_[index]; }
1083 int64 vehicle)
const;
1086 return costs_are_homogeneous_across_vehicles_;
1103 int64 cost_class_index)
const;
1107 return cost_class_index_of_vehicle_[vehicle];
1113 if (cost_class_index == kCostClassIndexOfZeroCost) {
1114 return has_vehicle_with_zero_cost_class_;
1116 return cost_class_index < cost_classes_.size();
1126 return vehicle_class_index_of_vehicle_[vehicle];
1133 return same_vehicle_groups_[same_vehicle_group_[node]];
1159 const Assignment& solution_assignment,
1160 const std::string& dimension_to_print)
const;
1164 Solver*
solver()
const {
return solver_.get(); }
1168 DCHECK(limit_ !=
nullptr);
1169 return limit_->Check();
1174 DCHECK(limit_ !=
nullptr);
1175 return limit_->AbsoluteSolverDeadline() - solver_->Now();
1184 int64
Size()
const {
return nodes_ + vehicles_ - start_end_count_; }
1189 const RoutingSearchParameters& search_parameters)
const;
1191 const RoutingSearchParameters& search_parameters)
const;
1200 std::function<std::vector<operations_research::IntVar*>(RoutingModel*)>;
1220 std::function<int64(int64)> initializer);
1228 std::vector<IntVar*> variables);
1247 enum RoutingLocalSearchOperator {
1250 LIGHT_RELOCATE_PAIR,
1258 RELOCATE_EXPENSIVE_CHAIN,
1262 RELOCATE_AND_MAKE_ACTIVE,
1263 MAKE_ACTIVE_AND_RELOCATE,
1265 MAKE_CHAIN_INACTIVE,
1267 EXTENDED_SWAP_ACTIVE,
1273 EXCHANGE_RELOCATE_PAIR,
1276 LOCAL_SEARCH_OPERATOR_COUNTER
1282 template <
typename T>
1283 struct ValuedNodes {
1284 std::vector<int64> indices;
1287 struct DisjunctionValues {
1289 int64 max_cardinality;
1291 typedef ValuedNodes<DisjunctionValues> Disjunction;
1295 struct CostCacheElement {
1301 CostClassIndex cost_class_index;
1307 void AddNoCycleConstraintInternal();
1308 bool AddDimensionWithCapacityInternal(
1309 const std::vector<int>& evaluator_indices, int64 slack_max,
1310 std::vector<int64> vehicle_capacities,
bool fix_start_cumul_to_zero,
1311 const std::string& name);
1312 bool AddDimensionDependentDimensionWithVehicleCapacityInternal(
1313 const std::vector<int>& pure_transits,
1314 const std::vector<int>& dependent_transits,
1316 std::vector<int64> vehicle_capacities,
bool fix_start_cumul_to_zero,
1317 const std::string& name);
1318 bool InitializeDimensionInternal(
1319 const std::vector<int>& evaluator_indices,
1320 const std::vector<int>& state_dependent_evaluator_indices,
1321 int64 slack_max,
bool fix_start_cumul_to_zero,
1323 DimensionIndex GetDimensionIndex(
const std::string& dimension_name)
const;
1352 void StoreDimensionsForDimensionCumulOptimizers();
1354 void ComputeCostClasses(
const RoutingSearchParameters& parameters);
1355 void ComputeVehicleClasses();
1356 int64 GetArcCostForClassInternal(int64 from_index, int64 to_index,
1357 CostClassIndex cost_class_index)
const;
1358 void AppendHomogeneousArcCosts(
const RoutingSearchParameters& parameters,
1360 std::vector<IntVar*>* cost_elements);
1361 void AppendArcCosts(
const RoutingSearchParameters& parameters,
int node_index,
1362 std::vector<IntVar*>* cost_elements);
1363 Assignment* DoRestoreAssignment();
1364 static const CostClassIndex kCostClassIndexOfZeroCost;
1365 int64 SafeGetCostClassInt64OfVehicle(int64 vehicle)
const {
1366 DCHECK_LT(0, vehicles_);
1368 : kCostClassIndexOfZeroCost)
1371 int64 GetDimensionTransitCostSum(int64 i, int64 j,
1372 const CostClass& cost_class)
const;
1374 IntVar* CreateDisjunction(DisjunctionIndex disjunction);
1376 void AddPickupAndDeliverySetsInternal(
const std::vector<int64>& pickups,
1377 const std::vector<int64>& deliveries);
1380 IntVar* CreateSameVehicleCost(
int vehicle_index);
1383 int FindNextActive(
int index,
const std::vector<int64>& indices)
const;
1387 bool RouteCanBeUsedByVehicle(
const Assignment& assignment,
int start_index,
1396 bool ReplaceUnusedVehicle(
int unused_vehicle,
int active_vehicle,
1397 Assignment* compact_assignment)
const;
1399 void QuietCloseModel();
1400 void QuietCloseModelWithParameters(
1401 const RoutingSearchParameters& parameters) {
1408 bool SolveMatchingModel(Assignment* assignment);
1411 bool AppendAssignmentIfFeasible(
1412 const Assignment& assignment,
1413 std::vector<std::unique_ptr<Assignment>>* assignments);
1416 void LogSolution(
const RoutingSearchParameters& parameters,
1417 const std::string& description, int64 solution_cost,
1418 int64 start_time_ms);
1421 Assignment* CompactAssignmentInternal(
const Assignment& assignment,
1422 bool check_compact_assignment)
const;
1426 std::string FindErrorInSearchParametersForModel(
1427 const RoutingSearchParameters& search_parameters)
const;
1429 void SetupSearch(
const RoutingSearchParameters& search_parameters);
1432 Assignment* GetOrCreateAssignment();
1433 Assignment* GetOrCreateTmpAssignment();
1434 RegularLimit* GetOrCreateLimit();
1435 RegularLimit* GetOrCreateLocalSearchLimit();
1436 RegularLimit* GetOrCreateLargeNeighborhoodSearchLimit();
1437 RegularLimit* GetOrCreateFirstSolutionLargeNeighborhoodSearchLimit();
1438 LocalSearchOperator* CreateInsertionOperator();
1439 LocalSearchOperator* CreateMakeInactiveOperator();
1440 void CreateNeighborhoodOperators(
const RoutingSearchParameters& parameters);
1441 LocalSearchOperator* GetNeighborhoodOperators(
1442 const RoutingSearchParameters& search_parameters)
const;
1443 const std::vector<LocalSearchFilter*>& GetOrCreateLocalSearchFilters();
1444 const std::vector<LocalSearchFilter*>& GetOrCreateFeasibilityFilters();
1445 DecisionBuilder* CreateSolutionFinalizer(SearchLimit* lns_limit);
1446 DecisionBuilder* CreateFinalizerForMinimizedAndMaximizedVariables();
1447 void CreateFirstSolutionDecisionBuilders(
1448 const RoutingSearchParameters& search_parameters);
1449 DecisionBuilder* GetFirstSolutionDecisionBuilder(
1450 const RoutingSearchParameters& search_parameters)
const;
1451 IntVarFilteredDecisionBuilder* GetFilteredFirstSolutionDecisionBuilderOrNull(
1452 const RoutingSearchParameters& parameters)
const;
1453 LocalSearchPhaseParameters* CreateLocalSearchParameters(
1454 const RoutingSearchParameters& search_parameters);
1455 DecisionBuilder* CreateLocalSearchDecisionBuilder(
1456 const RoutingSearchParameters& search_parameters);
1457 void SetupDecisionBuilders(
const RoutingSearchParameters& search_parameters);
1458 void SetupMetaheuristics(
const RoutingSearchParameters& search_parameters);
1459 void SetupAssignmentCollector(
1460 const RoutingSearchParameters& search_parameters);
1461 void SetupTrace(
const RoutingSearchParameters& search_parameters);
1462 void SetupSearchMonitors(
const RoutingSearchParameters& search_parameters);
1463 bool UsesLightPropagation(
1464 const RoutingSearchParameters& search_parameters)
const;
1467 int GetVehicleStartClass(int64 start)
const;
1469 void InitSameVehicleGroups(
int number_of_groups) {
1470 same_vehicle_group_.assign(
Size(), 0);
1471 same_vehicle_groups_.assign(number_of_groups, {});
1473 void SetSameVehicleGroup(
int index,
int group) {
1474 same_vehicle_group_[index] = group;
1475 same_vehicle_groups_[group].push_back(index);
1479 std::unique_ptr<Solver> solver_;
1482 Constraint* no_cycle_constraint_ =
nullptr;
1484 std::vector<IntVar*> nexts_;
1485 std::vector<IntVar*> vehicle_vars_;
1486 std::vector<IntVar*> active_;
1487 std::vector<IntVar*> vehicle_costs_considered_;
1492 std::vector<IntVar*> is_bound_to_end_;
1493 mutable RevSwitch is_bound_to_end_ct_added_;
1495 absl::flat_hash_map<std::string, DimensionIndex> dimension_name_to_index_;
1496 gtl::ITIVector<DimensionIndex, RoutingDimension*> dimensions_;
1497 std::vector<RoutingDimension*> dimensions_for_global_optimizer_;
1498 std::vector<RoutingDimension*> dimensions_for_local_optimizer_;
1499 std::string primary_constrained_dimension_;
1501 IntVar* cost_ =
nullptr;
1502 std::vector<int> vehicle_to_transit_cost_;
1503 std::vector<int64> fixed_cost_of_vehicle_;
1504 std::vector<CostClassIndex> cost_class_index_of_vehicle_;
1505 bool has_vehicle_with_zero_cost_class_;
1506 std::vector<int64> linear_cost_factor_of_vehicle_;
1507 std::vector<int64> quadratic_cost_factor_of_vehicle_;
1508 bool vehicle_amortized_cost_factors_set_;
1517 std::vector<bool> consider_empty_route_costs_;
1519 gtl::ITIVector<CostClassIndex, CostClass> cost_classes_;
1521 bool costs_are_homogeneous_across_vehicles_;
1522 bool cache_callbacks_;
1523 mutable std::vector<CostCacheElement> cost_cache_;
1524 std::vector<VehicleClassIndex> vehicle_class_index_of_vehicle_;
1526 gtl::ITIVector<VehicleClassIndex, VehicleClass> vehicle_classes_;
1528 std::function<int(int64)> vehicle_start_class_callback_;
1530 gtl::ITIVector<DisjunctionIndex, Disjunction> disjunctions_;
1531 std::vector<std::vector<DisjunctionIndex>> index_to_disjunctions_;
1533 std::vector<ValuedNodes<int64>> same_vehicle_costs_;
1536 std::vector<std::unordered_set<int>> allowed_vehicles_;
1539 IndexPairs pickup_delivery_pairs_;
1540 std::vector<std::pair<DisjunctionIndex, DisjunctionIndex>>
1541 pickup_delivery_disjunctions_;
1546 std::vector<std::vector<std::pair<int, int> > > index_to_pickup_index_pairs_;
1548 std::vector<std::vector<std::pair<int, int> > >
1549 index_to_delivery_index_pairs_;
1551 std::vector<PickupAndDeliveryPolicy> vehicle_pickup_delivery_policy_;
1553 std::vector<int> same_vehicle_group_;
1555 std::vector<std::vector<int>> same_vehicle_groups_;
1558 std::vector<int> index_to_visit_type_;
1560 std::vector<absl::flat_hash_set<int> >
1561 hard_incompatible_types_per_type_index_;
1562 bool has_hard_type_incompatibilities_;
1563 std::vector<absl::flat_hash_set<int> >
1564 temporal_incompatible_types_per_type_index_;
1565 bool has_temporal_type_incompatibilities_;
1567 std::vector<std::vector<absl::flat_hash_set<int> > >
1568 same_vehicle_required_type_alternatives_per_type_index_;
1569 bool has_same_vehicle_type_requirements_;
1570 std::vector<std::vector<absl::flat_hash_set<int> > >
1571 temporal_required_type_alternatives_per_type_index_;
1572 bool has_temporal_type_requirements_;
1573 absl::flat_hash_set<int> trivially_infeasible_visit_types_;
1575 int num_visit_types_;
1578 std::vector<int> index_to_equivalence_class_;
1579 std::vector<int> index_to_vehicle_;
1580 std::vector<int64> starts_;
1581 std::vector<int64> ends_;
1584 RoutingIndexManager manager_;
1585 int start_end_count_;
1587 bool closed_ =
false;
1588 Status status_ = ROUTING_NOT_SOLVED;
1589 bool enable_deep_serialization_ =
true;
1592 std::vector<DecisionBuilder*> first_solution_decision_builders_;
1593 std::vector<IntVarFilteredDecisionBuilder*>
1594 first_solution_filtered_decision_builders_;
1596 std::vector<LocalSearchOperator*> local_search_operators_;
1597 std::vector<SearchMonitor*> monitors_;
1598 SolutionCollector* collect_assignments_ =
nullptr;
1599 SolutionCollector* collect_one_assignment_ =
nullptr;
1600 SolutionCollector* packed_dimensions_assignment_collector_ =
nullptr;
1601 DecisionBuilder* solve_db_ =
nullptr;
1602 DecisionBuilder* improve_db_ =
nullptr;
1603 DecisionBuilder* restore_assignment_ =
nullptr;
1604 DecisionBuilder* restore_tmp_assignment_ =
nullptr;
1605 Assignment* assignment_ =
nullptr;
1606 Assignment* preassignment_ =
nullptr;
1607 Assignment* tmp_assignment_ =
nullptr;
1608 std::vector<IntVar*> extra_vars_;
1609 std::vector<IntervalVar*> extra_intervals_;
1610 std::vector<LocalSearchOperator*> extra_operators_;
1611 std::vector<LocalSearchFilter*> filters_;
1612 std::vector<LocalSearchFilter*> feasibility_filters_;
1613 std::vector<LocalSearchFilter*> extra_filters_;
1614 std::vector<IntVar*> variables_maximized_by_finalizer_;
1615 std::vector<IntVar*> variables_minimized_by_finalizer_;
1617 std::unique_ptr<SweepArranger> sweep_arranger_;
1620 RegularLimit* limit_ =
nullptr;
1621 RegularLimit* ls_limit_ =
nullptr;
1622 RegularLimit* lns_limit_ =
nullptr;
1623 RegularLimit* first_solution_lns_limit_ =
nullptr;
1625 typedef std::pair<int64, int64> CacheKey;
1626 typedef absl::flat_hash_map<CacheKey, int64> TransitCallbackCache;
1627 typedef absl::flat_hash_map<CacheKey, StateDependentTransit>
1628 StateDependentTransitCallbackCache;
1630 std::vector<TransitCallback1> unary_transit_evaluators_;
1631 std::vector<TransitCallback2> transit_evaluators_;
1642 std::vector<bool> is_transit_evaluator_positive_;
1643 std::vector<VariableIndexEvaluator2> state_dependent_transit_evaluators_;
1644 std::vector<std::unique_ptr<StateDependentTransitCallbackCache>>
1645 state_dependent_transit_evaluators_cache_;
1650 DISALLOW_COPY_AND_ASSIGN(RoutingModel);
1654 class RoutingModelVisitor :
public BaseObject {
1657 static const char kLightElement[];
1658 static const char kLightElement2[];
1659 static const char kRemoveValues[];
1665 class DisjunctivePropagator {
1673 int num_chain_tasks = 0;
1687 duration_min.clear();
1688 duration_max.clear();
1691 is_preemptible.clear();
1692 forbidden_intervals.clear();
1693 distance_duration.clear();
1699 bool Propagate(Tasks* tasks);
1702 bool Precedences(Tasks* tasks);
1705 bool MirrorTasks(Tasks* tasks);
1707 bool EdgeFinding(Tasks* tasks);
1710 bool DetectablePrecedencesWithChain(Tasks* tasks);
1712 bool ForbiddenIntervals(Tasks* tasks);
1713 bool DistanceDuration(Tasks* tasks);
1718 sat::ThetaLambdaTree<int64> theta_lambda_tree_;
1720 std::vector<int> tasks_by_start_min_;
1721 std::vector<int> tasks_by_end_max_;
1722 std::vector<int> event_of_task_;
1723 std::vector<int> nonchain_tasks_by_start_max_;
1726 void AppendTasksFromPath(
const std::vector<int64>& path,
1727 const std::vector<int64>& min_travels,
1728 const std::vector<int64>& max_travels,
1729 const std::vector<int64>& pre_travels,
1730 const std::vector<int64>& post_travels,
1733 void AppendTasksFromIntervals(
const std::vector<IntervalVar*>& intervals,
1735 void FillPathEvaluation(
const std::vector<int64>& path,
1736 const RoutingModel::TransitCallback2& evaluator,
1737 std::vector<int64>* values);
1738 #endif // !defined(SWIG) 1750 class GlobalVehicleBreaksConstraint :
public Constraint {
1754 void Post()
override;
1755 void InitialPropagate()
override;
1758 void PropagateNode(
int node);
1759 void PropagateVehicle(
int vehicle);
1760 void PropagateMaxBreakDistance(
int vehicle);
1762 const RoutingModel* model_;
1764 std::vector<Demon*> vehicle_demons_;
1765 std::vector<int64> path_;
1771 void FillPartialPathOfVehicle(
int vehicle);
1772 void FillPathTravels(
const std::vector<int64>& path);
1785 class TaskTranslator {
1787 TaskTranslator(IntVar* start, int64 before_start, int64 after_start)
1789 before_start_(before_start),
1790 after_start_(after_start) {}
1791 explicit TaskTranslator(IntervalVar* interval) : interval_(interval) {}
1794 void SetStartMin(int64 value) {
1795 if (start_ !=
nullptr) {
1796 start_->SetMin(CapAdd(before_start_, value));
1797 }
else if (interval_ !=
nullptr) {
1798 interval_->SetStartMin(value);
1801 void SetStartMax(int64 value) {
1802 if (start_ !=
nullptr) {
1803 start_->SetMax(CapAdd(before_start_, value));
1804 }
else if (interval_ !=
nullptr) {
1805 interval_->SetStartMax(value);
1808 void SetDurationMin(int64 value) {
1809 if (interval_ !=
nullptr) {
1810 interval_->SetDurationMin(value);
1813 void SetEndMin(int64 value) {
1814 if (start_ !=
nullptr) {
1815 start_->SetMin(CapSub(value, after_start_));
1816 }
else if (interval_ !=
nullptr) {
1817 interval_->SetEndMin(value);
1820 void SetEndMax(int64 value) {
1821 if (start_ !=
nullptr) {
1822 start_->SetMax(CapSub(value, after_start_));
1823 }
else if (interval_ !=
nullptr) {
1824 interval_->SetEndMax(value);
1829 IntVar* start_ =
nullptr;
1830 int64 before_start_;
1832 IntervalVar* interval_ =
nullptr;
1836 std::vector<TaskTranslator> task_translators_;
1839 DisjunctivePropagator disjunctive_propagator_;
1843 std::vector<int64> min_travel_;
1844 std::vector<int64> max_travel_;
1845 std::vector<int64> pre_travel_;
1846 std::vector<int64> post_travel_;
1849 class TypeRegulationsChecker {
1851 explicit TypeRegulationsChecker(
const RoutingModel&
model);
1852 virtual ~TypeRegulationsChecker() {}
1854 bool CheckVehicle(
int vehicle,
1855 const std::function<int64(int64)>& next_accessor);
1858 enum PickupDeliveryStatus { PICKUP, DELIVERY, NONE };
1860 int non_pickup_delivery = 0;
1866 int GetNonDeliveryCount(
int type)
const;
1868 int GetNonDeliveredCount(
int type)
const;
1870 virtual bool HasRegulationsToCheck()
const = 0;
1871 virtual void InitializeCheck() {}
1872 virtual bool CheckTypeRegulations(
int type) = 0;
1873 virtual bool FinalizeCheck()
const {
return true; }
1875 const RoutingModel& model_;
1878 std::vector<PickupDeliveryStatus> pickup_delivery_status_of_node_;
1879 std::vector<NodeCount> counts_of_type_;
1883 class TypeIncompatibilityChecker :
public TypeRegulationsChecker {
1885 TypeIncompatibilityChecker(
const RoutingModel&
model,
1886 bool check_hard_incompatibilities);
1887 ~TypeIncompatibilityChecker()
override {}
1890 bool HasRegulationsToCheck()
const override;
1891 bool CheckTypeRegulations(
int type)
override;
1895 bool check_hard_incompatibilities_;
1899 class TypeRequirementChecker :
public TypeRegulationsChecker {
1901 explicit TypeRequirementChecker(
const RoutingModel&
model)
1902 : TypeRegulationsChecker(
model) {}
1903 ~TypeRequirementChecker()
override {}
1906 bool HasRegulationsToCheck()
const override;
1907 void InitializeCheck()
override {
1908 types_with_same_vehicle_requirements_on_route_.clear();
1910 bool CheckTypeRegulations(
int type)
override;
1911 bool FinalizeCheck()
const override;
1913 absl::flat_hash_set<int> types_with_same_vehicle_requirements_on_route_;
1933 class TypeRegulationsConstraint :
public Constraint {
1935 explicit TypeRegulationsConstraint(
const RoutingModel&
model);
1937 void Post()
override;
1938 void InitialPropagate()
override;
1941 void PropagateNodeRegulations(
int node);
1942 void CheckRegulationsOnVehicle(
int vehicle);
1944 const RoutingModel& model_;
1945 TypeIncompatibilityChecker incompatibility_checker_;
1946 TypeRequirementChecker requirement_checker_;
1947 std::vector<Demon*> vehicle_demons_;
1962 class SimpleBoundCosts {
1968 SimpleBoundCosts(
int num_bounds,
BoundCost default_bound_cost)
1969 : bound_costs_(num_bounds, default_bound_cost) {}
1970 BoundCost& bound_cost(
int element) {
return bound_costs_[element]; }
1971 BoundCost bound_cost(
int element)
const {
return bound_costs_[element]; }
1972 int Size() {
return bound_costs_.size(); }
1973 SimpleBoundCosts(
const SimpleBoundCosts&) =
delete;
1974 SimpleBoundCosts operator=(
const SimpleBoundCosts&) =
delete;
1977 std::vector<BoundCost> bound_costs_;
1979 #endif // !defined SWIG 2004 RoutingModel*
model()
const {
return model_; }
2008 int64 GetTransitValue(int64 from_index, int64 to_index, int64 vehicle)
const;
2011 int64 GetTransitValueFromClass(int64 from_index, int64 to_index,
2012 int64 vehicle_class)
const {
2013 return model_->TransitCallback(class_evaluators_[vehicle_class])(from_index,
2018 IntVar* CumulVar(int64 index)
const {
return cumuls_[index]; }
2019 IntVar* TransitVar(int64 index)
const {
return transits_[index]; }
2020 IntVar* FixedTransitVar(int64 index)
const {
return fixed_transits_[index]; }
2021 IntVar* SlackVar(int64 index)
const {
return slacks_[index]; }
2023 #if !defined(SWIGPYTHON) 2026 const std::vector<IntVar*>& cumuls()
const {
return cumuls_; }
2027 const std::vector<IntVar*>& fixed_transits()
const {
return fixed_transits_; }
2028 const std::vector<IntVar*>& transits()
const {
return transits_; }
2029 const std::vector<IntVar*>& slacks()
const {
return slacks_; }
2030 #if !defined(SWIGCSHARP) && !defined(SWIGJAVA) 2032 const std::vector<SortedDisjointIntervalList>& forbidden_intervals()
const {
2033 return forbidden_intervals_;
2036 const std::vector<int64>& vehicle_capacities()
const {
2037 return vehicle_capacities_;
2041 const RoutingModel::TransitCallback2& transit_evaluator(
int vehicle)
const {
2042 return model_->TransitCallback(
2043 class_evaluators_[vehicle_to_class_[vehicle]]);
2047 bool AreVehicleTransitsPositive(
int vehicle)
const {
2048 return model()->is_transit_evaluator_positive_
2049 [class_evaluators_[vehicle_to_class_[vehicle]]];
2051 int vehicle_to_class(
int vehicle)
const {
return vehicle_to_class_[vehicle]; }
2052 #endif // !defined(SWIGCSHARP) && !defined(SWIGJAVA) 2053 #endif // !defined(SWIGPYTHON) 2057 void SetSpanUpperBoundForVehicle(int64 upper_bound,
int vehicle);
2064 void SetSpanCostCoefficientForVehicle(int64 coefficient,
int vehicle);
2065 void SetSpanCostCoefficientForAllVehicles(int64 coefficient);
2072 void SetGlobalSpanCostCoefficient(int64 coefficient);
2079 void SetCumulVarPiecewiseLinearCost(int64 index,
2080 const PiecewiseLinearFunction& cost);
2083 bool HasCumulVarPiecewiseLinearCost(int64 index)
const;
2086 const PiecewiseLinearFunction* GetCumulVarPiecewiseLinearCost(
2098 void SetCumulVarSoftUpperBound(int64 index, int64 upper_bound,
2101 bool HasCumulVarSoftUpperBound(int64 index)
const;
2105 int64 GetCumulVarSoftUpperBound(int64 index)
const;
2109 int64 GetCumulVarSoftUpperBoundCoefficient(int64 index)
const;
2122 void SetCumulVarSoftLowerBound(int64 index, int64 lower_bound,
2125 bool HasCumulVarSoftLowerBound(int64 index)
const;
2129 int64 GetCumulVarSoftLowerBound(int64 index)
const;
2133 int64 GetCumulVarSoftLowerBoundCoefficient(int64 index)
const;
2149 #if !defined(SWIGPYTHON) 2150 void SetBreakIntervalsOfVehicle(std::vector<IntervalVar*> breaks,
int vehicle,
2151 int pre_travel_evaluator,
2152 int post_travel_evaluator);
2153 #endif // !defined(SWIGPYTHON) 2156 void SetBreakIntervalsOfVehicle(std::vector<IntervalVar*> breaks,
int vehicle,
2157 std::vector<int64> node_visit_transits);
2163 void SetBreakDistanceDurationOfVehicle(int64 distance, int64 duration,
2167 void InitializeBreaks();
2169 bool HasBreakConstraints()
const;
2170 #if !defined(SWIGPYTHON) 2173 void SetBreakIntervalsOfVehicle(
2174 std::vector<IntervalVar*> breaks,
int vehicle,
2175 std::vector<int64> node_visit_transits,
2176 std::function<int64(int64, int64)> group_delays);
2179 const std::vector<IntervalVar*>& GetBreakIntervalsOfVehicle(
2184 const std::vector<std::pair<int64, int64> >&
2185 GetBreakDistanceDurationOfVehicle(
int vehicle)
const;
2187 #endif // !defined(SWIGPYTHON) 2188 int GetPreTravelEvaluatorOfVehicle(
int vehicle)
const;
2189 int GetPostTravelEvaluatorOfVehicle(
int vehicle)
const;
2200 int64 ShortestTransitionSlack(int64 node)
const;
2203 const std::string& name()
const {
return name_; }
2207 const ReverseArcListGraph<int, int>& GetPathPrecedenceGraph()
const {
2208 return path_precedence_graph_;
2221 typedef std::function<int64(
int,
int)> PickupToDeliveryLimitFunction;
2223 void SetPickupToDeliveryLimitFunctionForPair(
2224 PickupToDeliveryLimitFunction limit_function,
int pair_index);
2226 bool HasPickupToDeliveryLimits()
const;
2228 int64 GetPickupToDeliveryLimitForPair(
int pair_index,
int pickup,
2229 int delivery)
const;
2238 node_precedences_.push_back(precedence);
2240 const std::vector<NodePrecedence>& GetNodePrecedences()
const {
2241 return node_precedences_;
2245 void AddNodePrecedence(int64 first_node, int64 second_node, int64 offset) {
2246 AddNodePrecedence({first_node, second_node, offset});
2249 int64 GetSpanUpperBoundForVehicle(
int vehicle)
const {
2250 return vehicle_span_upper_bounds_[vehicle];
2253 const std::vector<int64>& vehicle_span_upper_bounds()
const {
2254 return vehicle_span_upper_bounds_;
2257 int64 GetSpanCostCoefficientForVehicle(
int vehicle)
const {
2258 return vehicle_span_cost_coefficients_[vehicle];
2261 const std::vector<int64>& vehicle_span_cost_coefficients()
const {
2262 return vehicle_span_cost_coefficients_;
2265 int64 global_span_cost_coefficient()
const {
2266 return global_span_cost_coefficient_;
2269 int64 GetGlobalOptimizerOffset()
const {
2270 DCHECK_GE(global_optimizer_offset_, 0);
2271 return global_optimizer_offset_;
2273 int64 GetLocalOptimizerOffsetForVehicle(
int vehicle)
const {
2274 if (vehicle >= local_optimizer_offset_for_vehicle_.size()) {
2277 DCHECK_GE(local_optimizer_offset_for_vehicle_[vehicle], 0);
2278 return local_optimizer_offset_for_vehicle_[vehicle];
2285 if (!HasSoftSpanUpperBounds()) {
2286 vehicle_soft_span_upper_bound_ = absl::make_unique<SimpleBoundCosts>(
2289 vehicle_soft_span_upper_bound_->bound_cost(vehicle) = bound_cost;
2291 bool HasSoftSpanUpperBounds()
const {
2292 return vehicle_soft_span_upper_bound_ !=
nullptr;
2295 int vehicle)
const {
2296 DCHECK(HasSoftSpanUpperBounds());
2297 return vehicle_soft_span_upper_bound_->bound_cost(vehicle);
2299 #endif // !defined SWIG 2308 struct PiecewiseLinearCost {
2309 PiecewiseLinearCost() : var(nullptr), cost(nullptr) {}
2311 std::unique_ptr<PiecewiseLinearFunction> cost;
2316 const std::string& name,
2319 const std::string& name, SelfBased);
2320 void Initialize(
const std::vector<int>& transit_evaluators,
2321 const std::vector<int>& state_dependent_transit_evaluators,
2323 void InitializeCumuls();
2324 void InitializeTransits(
2325 const std::vector<int>& transit_evaluators,
2326 const std::vector<int>& state_dependent_transit_evaluators,
2328 void InitializeTransitVariables(int64 slack_max);
2330 void SetupCumulVarSoftUpperBoundCosts(
2331 std::vector<IntVar*>* cost_elements)
const;
2333 void SetupCumulVarSoftLowerBoundCosts(
2334 std::vector<IntVar*>* cost_elements)
const;
2335 void SetupCumulVarPiecewiseLinearCosts(
2336 std::vector<IntVar*>* cost_elements)
const;
2339 void SetupGlobalSpanCost(std::vector<IntVar*>* cost_elements)
const;
2340 void SetupSlackAndDependentTransitCosts()
const;
2344 void SetOffsetForGlobalOptimizer(int64 offset) {
2345 global_optimizer_offset_ = std::max(
Zero(), offset);
2348 void SetVehicleOffsetsForLocalOptimizer(std::vector<int64> offsets) {
2350 std::transform(offsets.begin(), offsets.end(), offsets.begin(),
2351 [](int64 offset) {
return std::max(
Zero(), offset); });
2352 local_optimizer_offset_for_vehicle_ = std::move(offsets);
2355 std::vector<IntVar*> cumuls_;
2356 std::vector<SortedDisjointIntervalList> forbidden_intervals_;
2357 std::vector<IntVar*> capacity_vars_;
2358 const std::vector<int64> vehicle_capacities_;
2359 std::vector<IntVar*> transits_;
2360 std::vector<IntVar*> fixed_transits_;
2363 std::vector<int> class_evaluators_;
2364 std::vector<int64> vehicle_to_class_;
2366 ReverseArcListGraph<int, int> path_precedence_graph_;
2371 std::vector<NodePrecedence> node_precedences_;
2380 std::vector<int> state_dependent_class_evaluators_;
2381 std::vector<int64> state_dependent_vehicle_to_class_;
2386 std::vector<PickupToDeliveryLimitFunction>
2387 pickup_to_delivery_limits_per_pair_index_;
2390 bool break_constraints_are_initialized_ =
false;
2392 std::vector<std::vector<IntervalVar*> > vehicle_break_intervals_;
2393 std::vector<std::vector<std::pair<int64, int64> > >
2394 vehicle_break_distance_duration_;
2399 std::vector<int> vehicle_pre_travel_evaluators_;
2400 std::vector<int> vehicle_post_travel_evaluators_;
2402 std::vector<IntVar*> slacks_;
2403 std::vector<IntVar*> dependent_transits_;
2404 std::vector<int64> vehicle_span_upper_bounds_;
2405 int64 global_span_cost_coefficient_;
2406 std::vector<int64> vehicle_span_cost_coefficients_;
2407 std::vector<SoftBound> cumul_var_soft_upper_bound_;
2408 std::vector<SoftBound> cumul_var_soft_lower_bound_;
2409 std::vector<PiecewiseLinearCost> cumul_var_piecewise_linear_cost_;
2410 RoutingModel*
const model_;
2411 const std::string name_;
2412 int64 global_optimizer_offset_;
2413 std::vector<int64> local_optimizer_offset_for_vehicle_;
2415 std::unique_ptr<SimpleBoundCosts> vehicle_soft_span_upper_bound_;
2416 friend class RoutingModel;
2425 class SweepArranger {
2427 explicit SweepArranger(
const std::vector<std::pair<int64, int64>>& points);
2428 virtual ~SweepArranger() {}
2429 void ArrangeIndices(std::vector<int64>* indices);
2430 void SetSectors(
int sectors) { sectors_ = sectors; }
2433 std::vector<int> coordinates_;
2436 DISALLOW_COPY_AND_ASSIGN(SweepArranger);
2442 DecisionBuilder* MakeSetValuesFromTargets(Solver*
solver,
2443 std::vector<IntVar*> variables,
2444 std::vector<int64> targets);
2463 class IntVarFilteredDecisionBuilder :
public DecisionBuilder {
2465 IntVarFilteredDecisionBuilder(Solver*
solver,
2466 const std::vector<IntVar*>& vars,
2467 const std::vector<LocalSearchFilter*>& filters);
2468 ~IntVarFilteredDecisionBuilder()
override {}
2471 virtual bool BuildSolution() = 0;
2474 int64 number_of_decisions()
const {
return number_of_decisions_; }
2475 int64 number_of_rejects()
const {
return number_of_rejects_; }
2479 virtual bool InitializeSolution() {
return true; }
2485 virtual bool StopSearch() {
return false; }
2488 void SetValue(int64 index, int64 value) {
2489 if (!is_in_delta_[index]) {
2490 delta_->FastAdd(vars_[index])->SetValue(value);
2491 delta_indices_.push_back(index);
2492 is_in_delta_[index] =
true;
2494 delta_->SetValue(vars_[index], value);
2499 int64 Value(int64 index)
const {
2500 return assignment_->IntVarContainer().Element(index).Value();
2503 bool Contains(int64 index)
const {
2504 return assignment_->IntVarContainer().Element(index).Var() !=
nullptr;
2508 int Size()
const {
return vars_.size(); }
2510 IntVar* Var(int64 index)
const {
return vars_[index]; }
2514 void SynchronizeFilters();
2517 bool FilterAccept();
2519 const std::vector<IntVar*> vars_;
2520 Assignment*
const assignment_;
2521 Assignment*
const delta_;
2522 std::vector<int> delta_indices_;
2523 std::vector<bool> is_in_delta_;
2524 Assignment*
const empty_;
2525 LocalSearchFilterManager filter_manager_;
2527 int64 number_of_decisions_;
2528 int64 number_of_rejects_;
2532 class RoutingFilteredDecisionBuilder :
public IntVarFilteredDecisionBuilder {
2534 RoutingFilteredDecisionBuilder(
2535 RoutingModel*
model,
const std::vector<LocalSearchFilter*>& filters);
2536 ~RoutingFilteredDecisionBuilder()
override {}
2537 RoutingModel*
model()
const {
return model_; }
2539 int GetStartChainEnd(
int vehicle)
const {
return start_chain_ends_[vehicle]; }
2541 int GetEndChainStart(
int vehicle)
const {
return end_chain_starts_[vehicle]; }
2544 void MakeDisjunctionNodesUnperformed(int64 node);
2546 void MakeUnassignedNodesUnperformed();
2549 bool StopSearch()
override {
return model_->CheckLimit(); }
2553 bool InitializeSolution()
override;
2555 RoutingModel*
const model_;
2556 std::vector<int64> start_chain_ends_;
2557 std::vector<int64> end_chain_starts_;
2560 class CheapestInsertionFilteredDecisionBuilder
2561 :
public RoutingFilteredDecisionBuilder {
2564 CheapestInsertionFilteredDecisionBuilder(
2565 RoutingModel*
model, std::function<int64(int64, int64, int64)> evaluator,
2566 std::function<int64(int64)> penalty_evaluator,
2567 const std::vector<LocalSearchFilter*>& filters);
2568 ~CheapestInsertionFilteredDecisionBuilder()
override {}
2571 typedef std::pair<int64, int64> ValuedPosition;
2577 return std::tie(distance, vehicle) <
2581 typedef std::pair<StartEndValue,
int> Seed;
2589 std::vector<std::vector<StartEndValue> >
2590 ComputeStartEndDistanceForVehicles(
const std::vector<int>&
vehicles);
2596 template <
class Queue>
2597 void InitializePriorityQueue(
2598 std::vector<std::vector<StartEndValue> >* start_end_distances_per_node,
2599 Queue* priority_queue);
2606 void InsertBetween(int64 node, int64 predecessor, int64 successor);
2611 void AppendEvaluatedPositionsAfter(
2612 int64 node_to_insert, int64 start, int64 next_after_start, int64 vehicle,
2613 std::vector<ValuedPosition>* valued_positions);
2616 int64 GetUnperformedValue(int64 node_to_insert)
const;
2618 std::function<int64(int64, int64, int64)> evaluator_;
2619 std::function<int64(int64)> penalty_evaluator_;
2628 class GlobalCheapestInsertionFilteredDecisionBuilder
2629 :
public CheapestInsertionFilteredDecisionBuilder {
2632 GlobalCheapestInsertionFilteredDecisionBuilder(
2633 RoutingModel*
model, std::function<int64(int64, int64, int64)> evaluator,
2634 std::function<int64(int64)> penalty_evaluator,
2635 const std::vector<LocalSearchFilter*>& filters,
bool is_sequential,
2636 double farthest_seeds_ratio,
double neighbors_ratio);
2637 ~GlobalCheapestInsertionFilteredDecisionBuilder()
override {}
2638 bool BuildSolution()
override;
2639 std::string DebugString()
const override {
2640 return "GlobalCheapestInsertionFilteredDecisionBuilder";
2646 typedef absl::flat_hash_set<PairEntry*> PairEntries;
2647 typedef absl::flat_hash_set<NodeEntry*> NodeEntries;
2664 void InsertNodesOnRoutes(
const std::vector<int>&
nodes,
2672 void SequentialInsertNodes(
const std::vector<int>&
nodes);
2677 void DetectUsedVehicles(std::vector<bool>* is_vehicle_used,
2678 std::vector<int>* used_vehicles,
2679 std::vector<int>* unused_vehicles);
2684 void InsertFarthestNodesAsSeeds();
2694 template <
class Queue>
2696 std::vector<std::vector<StartEndValue>>* start_end_distances_per_node,
2697 Queue* priority_queue, std::vector<bool>* is_vehicle_used);
2702 void InitializePairPositions(
2703 AdjustablePriorityQueue<PairEntry>* priority_queue,
2704 std::vector<PairEntries>* pickup_to_entries,
2705 std::vector<PairEntries>* delivery_to_entries);
2708 void UpdatePairPositions(
int vehicle, int64 insert_after,
2709 AdjustablePriorityQueue<PairEntry>* priority_queue,
2710 std::vector<PairEntries>* pickup_to_entries,
2711 std::vector<PairEntries>* delivery_to_entries) {
2712 UpdatePickupPositions(vehicle, insert_after, priority_queue,
2713 pickup_to_entries, delivery_to_entries);
2714 UpdateDeliveryPositions(vehicle, insert_after, priority_queue,
2715 pickup_to_entries, delivery_to_entries);
2719 void UpdatePickupPositions(
int vehicle, int64 pickup_insert_after,
2720 AdjustablePriorityQueue<PairEntry>* priority_queue,
2721 std::vector<PairEntries>* pickup_to_entries,
2722 std::vector<PairEntries>* delivery_to_entries);
2725 void UpdateDeliveryPositions(
2726 int vehicle, int64 delivery_insert_after,
2727 AdjustablePriorityQueue<PairEntry>* priority_queue,
2728 std::vector<PairEntries>* pickup_to_entries,
2729 std::vector<PairEntries>* delivery_to_entries);
2732 void DeletePairEntry(PairEntry* entry,
2733 AdjustablePriorityQueue<PairEntry>* priority_queue,
2734 std::vector<PairEntries>* pickup_to_entries,
2735 std::vector<PairEntries>* delivery_to_entries);
2738 void InitializePositions(
const std::vector<int>&
nodes,
2739 AdjustablePriorityQueue<NodeEntry>* priority_queue,
2740 std::vector<NodeEntries>* position_to_node_entries,
2744 void UpdatePositions(
const std::vector<int>&
nodes,
int vehicle,
2746 AdjustablePriorityQueue<NodeEntry>* priority_queue,
2747 std::vector<NodeEntries>* node_entries);
2750 void DeleteNodeEntry(NodeEntry* entry,
2751 AdjustablePriorityQueue<NodeEntry>* priority_queue,
2752 std::vector<NodeEntries>* node_entries);
2758 void AddNeighborForCostClass(
int cost_class, int64 node_index,
2759 int64 neighbor_index,
bool neighbor_is_pickup,
2760 bool neighbor_is_delivery);
2764 bool IsNeighborForCostClass(
int cost_class, int64 node_index,
2765 int64 neighbor_index)
const;
2768 const absl::flat_hash_set<int64>& GetPickupNeighborsOfNodeForCostClass(
2769 int cost_class, int64 node_index) {
2770 if (neighbors_ratio_ == 1) {
2771 return pickup_nodes_;
2773 return node_index_to_pickup_neighbors_by_cost_class_[node_index]
2778 const absl::flat_hash_set<int64>& GetDeliveryNeighborsOfNodeForCostClass(
2779 int cost_class, int64 node_index) {
2780 if (neighbors_ratio_ == 1) {
2781 return delivery_nodes_;
2783 return node_index_to_delivery_neighbors_by_cost_class_[node_index]
2787 const bool is_sequential_;
2788 const double farthest_seeds_ratio_;
2789 const double neighbors_ratio_;
2792 std::vector<std::vector<absl::flat_hash_set<int64> > >
2793 node_index_to_single_neighbors_by_cost_class_;
2794 std::vector<std::vector<absl::flat_hash_set<int64> > >
2795 node_index_to_pickup_neighbors_by_cost_class_;
2796 std::vector<std::vector<absl::flat_hash_set<int64> > >
2797 node_index_to_delivery_neighbors_by_cost_class_;
2803 absl::flat_hash_set<int64> pickup_nodes_;
2804 absl::flat_hash_set<int64> delivery_nodes_;
2812 class LocalCheapestInsertionFilteredDecisionBuilder
2813 :
public CheapestInsertionFilteredDecisionBuilder {
2816 LocalCheapestInsertionFilteredDecisionBuilder(
2817 RoutingModel*
model, std::function<int64(int64, int64, int64)> evaluator,
2818 const std::vector<LocalSearchFilter*>& filters);
2819 ~LocalCheapestInsertionFilteredDecisionBuilder()
override {}
2820 bool BuildSolution()
override;
2821 std::string DebugString()
const override {
2822 return "LocalCheapestInsertionFilteredDecisionBuilder";
2831 void ComputeEvaluatorSortedPositions(int64 node,
2832 std::vector<int64>* sorted_positions);
2837 void ComputeEvaluatorSortedPositionsOnRouteAfter(
2838 int64 node, int64 start, int64 next_after_start,
2839 std::vector<int64>* sorted_positions);
2844 class CheapestAdditionFilteredDecisionBuilder
2845 :
public RoutingFilteredDecisionBuilder {
2847 CheapestAdditionFilteredDecisionBuilder(
2848 RoutingModel*
model,
const std::vector<LocalSearchFilter*>& filters);
2849 ~CheapestAdditionFilteredDecisionBuilder()
override {}
2850 bool BuildSolution()
override;
2853 class PartialRoutesAndLargeVehicleIndicesFirst {
2855 explicit PartialRoutesAndLargeVehicleIndicesFirst(
2856 const CheapestAdditionFilteredDecisionBuilder& builder)
2857 : builder_(builder) {}
2858 bool operator()(
int vehicle1,
int vehicle2)
const;
2861 const CheapestAdditionFilteredDecisionBuilder& builder_;
2864 template <
typename Iterator>
2865 std::vector<int64> GetPossibleNextsFromIterator(int64 node, Iterator start,
2866 Iterator end)
const {
2867 const int size =
model()->Size();
2868 std::vector<int64> nexts;
2869 for (Iterator it = start; it != end; ++it) {
2870 const int64 next = *it;
2871 if (next != node && (next >= size || !Contains(next))) {
2872 nexts.push_back(next);
2878 virtual void SortSuccessors(int64 node, std::vector<int64>* successors) = 0;
2879 virtual int64 FindTopSuccessor(int64 node,
2880 const std::vector<int64>& successors) = 0;
2885 class EvaluatorCheapestAdditionFilteredDecisionBuilder
2886 :
public CheapestAdditionFilteredDecisionBuilder {
2889 EvaluatorCheapestAdditionFilteredDecisionBuilder(
2890 RoutingModel*
model, std::function<int64(int64, int64)> evaluator,
2891 const std::vector<LocalSearchFilter*>& filters);
2892 ~EvaluatorCheapestAdditionFilteredDecisionBuilder()
override {}
2893 std::string DebugString()
const override {
2894 return "EvaluatorCheapestAdditionFilteredDecisionBuilder";
2899 void SortSuccessors(int64 node, std::vector<int64>* successors)
override;
2900 int64 FindTopSuccessor(int64 node,
2901 const std::vector<int64>& successors)
override;
2903 std::function<int64(int64, int64)> evaluator_;
2908 class ComparatorCheapestAdditionFilteredDecisionBuilder
2909 :
public CheapestAdditionFilteredDecisionBuilder {
2912 ComparatorCheapestAdditionFilteredDecisionBuilder(
2914 const std::vector<LocalSearchFilter*>& filters);
2915 ~ComparatorCheapestAdditionFilteredDecisionBuilder()
override {}
2916 std::string DebugString()
const override {
2917 return "ComparatorCheapestAdditionFilteredDecisionBuilder";
2922 void SortSuccessors(int64 node, std::vector<int64>* successors)
override;
2923 int64 FindTopSuccessor(int64 node,
2924 const std::vector<int64>& successors)
override;
2938 class SavingsFilteredDecisionBuilder :
public RoutingFilteredDecisionBuilder {
2943 double neighbors_ratio = 1.0;
2946 double max_memory_usage_bytes = 6e9;
2949 bool add_reverse_arcs =
false;
2952 double arc_coefficient = 1.0;
2955 SavingsFilteredDecisionBuilder(
2956 RoutingModel*
model, RoutingIndexManager* manager,
2958 const std::vector<LocalSearchFilter*>& filters);
2959 ~SavingsFilteredDecisionBuilder()
override;
2960 bool BuildSolution()
override;
2963 typedef std::pair< int64, int64> Saving;
2965 template <
typename S>
2973 return std::tie(fixed_cost, vehicle_class) <
2978 virtual double ExtraSavingsMemoryMultiplicativeFactor()
const = 0;
2980 virtual void BuildRoutesFromSavings() = 0;
2983 int64 GetVehicleTypeFromSaving(
const Saving& saving)
const {
2984 return saving.second / size_squared_;
2987 int64 GetBeforeNodeFromSaving(
const Saving& saving)
const {
2988 return (saving.second % size_squared_) /
Size();
2991 int64 GetAfterNodeFromSaving(
const Saving& saving)
const {
2992 return (saving.second % size_squared_) %
Size();
2995 int64 GetSavingValue(
const Saving& saving)
const {
return saving.first; }
3006 int StartNewRouteWithBestVehicleOfType(
int type, int64 before_node,
3009 std::vector<int> type_index_of_vehicle_;
3011 std::vector<std::set<VehicleClassEntry> > sorted_vehicle_classes_per_type_;
3012 std::vector<std::deque<int> > vehicles_per_vehicle_class_;
3013 std::unique_ptr<SavingsContainer<Saving> > savings_container_;
3022 void AddSymetricArcsToAdjacencyLists(
3023 std::vector<std::vector<int64> >* adjacency_lists);
3032 void ComputeSavings();
3034 Saving BuildSaving(int64 saving,
int vehicle_type,
int before_node,
3035 int after_node)
const {
3036 return std::make_pair(saving, vehicle_type * size_squared_ +
3037 before_node *
Size() + after_node);
3047 void ComputeVehicleTypes();
3052 int64 MaxNumNeighborsPerNode(
int num_vehicle_types)
const;
3054 RoutingIndexManager*
const manager_;
3055 const SavingsParameters savings_params_;
3056 int64 size_squared_;
3058 friend class SavingsFilteredDecisionBuilderTestPeer;
3061 class SequentialSavingsFilteredDecisionBuilder
3062 :
public SavingsFilteredDecisionBuilder {
3064 SequentialSavingsFilteredDecisionBuilder(
3065 RoutingModel*
model, RoutingIndexManager* manager,
3066 SavingsParameters parameters,
3067 const std::vector<LocalSearchFilter*>& filters)
3068 : SavingsFilteredDecisionBuilder(
model, manager, parameters, filters) {}
3069 ~SequentialSavingsFilteredDecisionBuilder()
override{};
3070 std::string DebugString()
const override {
3071 return "SequentialSavingsFilteredDecisionBuilder";
3079 void BuildRoutesFromSavings()
override;
3080 double ExtraSavingsMemoryMultiplicativeFactor()
const override {
return 1.0; }
3083 class ParallelSavingsFilteredDecisionBuilder
3084 :
public SavingsFilteredDecisionBuilder {
3086 ParallelSavingsFilteredDecisionBuilder(
3087 RoutingModel*
model, RoutingIndexManager* manager,
3088 SavingsParameters parameters,
3089 const std::vector<LocalSearchFilter*>& filters)
3090 : SavingsFilteredDecisionBuilder(
model, manager, parameters, filters) {}
3091 ~ParallelSavingsFilteredDecisionBuilder()
override{};
3092 std::string DebugString()
const override {
3093 return "ParallelSavingsFilteredDecisionBuilder";
3107 void BuildRoutesFromSavings()
override;
3109 double ExtraSavingsMemoryMultiplicativeFactor()
const override {
return 2.0; }
3115 void MergeRoutes(
int first_vehicle,
int second_vehicle, int64 before_node,
3119 std::vector<int64> first_node_on_route_;
3120 std::vector<int64> last_node_on_route_;
3124 std::vector<int> vehicle_of_first_or_last_node_;
3131 class ChristofidesFilteredDecisionBuilder
3132 :
public RoutingFilteredDecisionBuilder {
3134 ChristofidesFilteredDecisionBuilder(
3135 RoutingModel*
model,
const std::vector<LocalSearchFilter*>& filters);
3136 ~ChristofidesFilteredDecisionBuilder()
override {}
3137 bool BuildSolution()
override;
3138 std::string DebugString()
const override {
3139 return "ChristofidesFilteredDecisionBuilder";
3147 bool SolveModelWithSat(RoutingModel*
model, Assignment* solution);
3151 class BasePathFilter :
public IntVarLocalSearchFilter {
3153 BasePathFilter(
const std::vector<IntVar*>& nexts,
int next_domain_size,
3154 std::function<
void(int64)> objective_callback);
3155 ~BasePathFilter()
override {}
3156 bool Accept(Assignment* delta, Assignment* deltadelta)
override;
3157 void OnSynchronize(
const Assignment* delta)
override;
3160 static const int64 kUnassigned;
3162 int64 GetNext(int64 node)
const {
3163 return (new_nexts_[node] == kUnassigned)
3164 ? (IsVarSynced(node) ? Value(node) : kUnassigned)
3167 int NumPaths()
const {
return starts_.size(); }
3168 int64
Start(
int i)
const {
return starts_[i]; }
3169 int GetPath(int64 node)
const {
return paths_[node]; }
3170 int Rank(int64 node)
const {
return ranks_[node]; }
3171 bool IsDisabled()
const {
return status_ == DISABLED; }
3172 const std::vector<int64>& GetNewSynchronizedUnperformedNodes()
const {
3173 return new_synchronized_unperformed_nodes_.PositionsSetAtLeastOnce();
3177 enum Status { UNKNOWN, ENABLED, DISABLED };
3179 virtual bool DisableFiltering()
const {
return false; }
3180 virtual void OnBeforeSynchronizePaths() {}
3181 virtual void OnAfterSynchronizePaths() {}
3182 virtual void OnSynchronizePathFromStart(int64 start) {}
3183 virtual void InitializeAcceptPath() {}
3184 virtual bool AcceptPath(int64 path_start, int64 chain_start,
3185 int64 chain_end) = 0;
3186 virtual bool FinalizeAcceptPath(Assignment* delta) {
return true; }
3188 void ComputePathStarts(std::vector<int64>* path_starts,
3189 std::vector<int>* index_to_path);
3190 bool HavePathsChanged();
3191 void SynchronizeFullAssignment();
3192 void UpdateAllRanks();
3193 void UpdatePathRanksFromStart(
int start);
3195 std::vector<int64> node_path_starts_;
3196 std::vector<int64> starts_;
3197 std::vector<int> paths_;
3198 SparseBitset<int64> new_synchronized_unperformed_nodes_;
3199 std::vector<int64> new_nexts_;
3200 std::vector<int> delta_touched_;
3201 SparseBitset<> touched_paths_;
3202 SparseBitset<> touched_path_nodes_;
3203 std::vector<int> ranks_;
3219 class CPFeasibilityFilter :
public IntVarLocalSearchFilter {
3221 explicit CPFeasibilityFilter(
const RoutingModel* routing_model);
3222 ~CPFeasibilityFilter()
override {}
3223 std::string DebugString()
const override {
return "CPFeasibilityFilter"; }
3224 bool Accept(Assignment* delta, Assignment* deltadelta)
override;
3225 void OnSynchronize(
const Assignment* delta)
override;
3228 void AddDeltaToAssignment(
const Assignment* delta, Assignment* assignment);
3230 static const int64 kUnassigned;
3231 const RoutingModel*
const model_;
3232 Solver*
const solver_;
3233 Assignment*
const assignment_;
3234 Assignment*
const temp_assignment_;
3235 DecisionBuilder*
const restore_;
3239 IntVarLocalSearchFilter* MakeNodeDisjunctionFilter(
3240 const RoutingModel& routing_model,
3241 std::function<
void(int64)> objective_callback);
3242 IntVarLocalSearchFilter* MakeVehicleAmortizedCostFilter(
3243 const RoutingModel& routing_model,
3245 IntVarLocalSearchFilter* MakeTypeRegulationsFilter(
3246 const RoutingModel& routing_model);
3247 std::vector<IntVarLocalSearchFilter*> MakeCumulFilters(
3250 IntVarLocalSearchFilter* MakePathCumulFilter(
3253 bool propagate_own_objective_value,
bool filter_objective_cost);
3254 IntVarLocalSearchFilter* MakeGlobalLPCumulFilter(
3257 IntVarLocalSearchFilter* MakePickupDeliveryFilter(
3258 const RoutingModel& routing_model,
const RoutingModel::IndexPairs& pairs,
3259 const std::vector<RoutingModel::PickupAndDeliveryPolicy>& vehicle_policies);
3260 IntVarLocalSearchFilter* MakeVehicleVarFilter(
3261 const RoutingModel& routing_model);
3262 IntVarLocalSearchFilter* MakeVehicleBreaksFilter(
3264 IntVarLocalSearchFilter* MakeCPFeasibilityFilter(
3265 const RoutingModel* routing_model);
3269 #endif // OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_H_
bool HasTypeRegulations() const
Returns true iff the model has any incompatibilities or requirements set on node types.
void AddSearchMonitor(SearchMonitor *const monitor)
Adds a search monitor to the search used to solve the routing model.
absl::Duration RemainingTime() const
Returns the time left in the search limit.
void SetAmortizedCostFactorsOfVehicle(int64 linear_cost_factor, int64 quadratic_cost_factor, int vehicle)
Sets the linear and quadratic cost factor of the given vehicle.
bool WriteAssignment(const std::string &file_name) const
Writes the current solution to a file containing an AssignmentProto.
bool ApplyLocksToAllVehicles(const std::vector< std::vector< int64 >> &locks, bool close_routes)
Applies lock chains to all vehicles to the next search, such that locks[p] is the lock chain for rout...
void AddTemporalRequiredTypeAlternatives(int dependent_type, absl::flat_hash_set< int > required_type_alternatives)
If type_D temporally depends on type_R, any non-delivery node_D of type_D requires at least one non-d...
int GetCostClassesCount() const
Returns the number of different cost classes in the model.
void SetFirstSolutionEvaluator(Solver::IndexEvaluator2 evaluator)
Takes ownership of evaluator.
IntVar * NextVar(int64 index) const
Returns the next variable of the node corresponding to index.
const Solver::IndexEvaluator2 & first_solution_evaluator() const
Search Gets/sets the evaluator used during the search.
std::vector< const SortedDisjointIntervalList * > forbidden_intervals
bool HasTemporalTypeRequirements() const
int vehicles() const
Returns the number of vehicle routes in the model.
bool IsMatchingModel() const
Returns true if a vehicle/node matching problem is detected.
int GetNonZeroCostClassesCount() const
Ditto, minus the 'always zero', built-in cost class.
bool HasTemporalTypeIncompatibilities() const
Assignment * RestoreAssignment(const Assignment &solution)
Restores an assignment as a solution in the routing model and returns the new solution.
std::vector< std::pair< int64, int64 > > distance_duration
const std::vector< int64 > & GetAmortizedLinearCostFactorOfVehicles() const
void ConsiderEmptyRouteCostsForVehicle(bool consider_costs, int vehicle)
static std::unique_ptr< LocalSearchOperator > MakeGreedyDescentLSOperator(std::vector< IntVar * > variables)
void AssignmentToRoutes(const Assignment &assignment, std::vector< std::vector< int64 >> *const routes) const
Converts the solution in the given assignment to routes for all vehicles.
Assignment * CompactAndCheckAssignment(const Assignment &assignment) const
Same as CompactAssignment() but also checks the validity of the final compact solution; if it is not ...
std::vector< int64 > duration_min
void AddSameVehicleRequiredTypeAlternatives(int dependent_type, absl::flat_hash_set< int > required_type_alternatives)
Requirements:
const Assignment * Solve(const Assignment *assignment=nullptr)
Solves the current routing model; closes the current model.
bool HasSameVehicleTypeRequirements() const
clang-format on Returns true iff any same-route (resp.
IntVar * VehicleVar(int64 index) const
Returns the vehicle variable of the node corresponding to index.
int64 Zero()
-------— Misc -------—
bool HasHardTypeIncompatibilities() const
Returns true iff any hard (resp.
int64 GetHomogeneousCost(int64 from_index, int64 to_index) const
Returns the cost of the segment between two nodes supposing all vehicle costs are the same (returns t...
IntVar * VehicleCostsConsideredVar(int vehicle) const
Returns the variable specifying whether or not costs are considered for vehicle.
IntVar * ActiveVar(int64 index) const
Returns the active variable of the node corresponding to index.
const Assignment * SolveWithParameters(const RoutingSearchParameters &search_parameters, std::vector< const Assignment * > *solutions=nullptr)
Solves the current routing model with the given parameters.
std::function< int64(int64, int64)> RoutingTransitCallback2
bool IsEnd(int64 index) const
Returns true if 'index' represents the last node of a route.
CostClassIndex GetCostClassIndexOfVehicle(int64 vehicle) const
Get the cost class index of the given vehicle.
IntVar * CostVar() const
Returns the global cost variable which is being minimized.
bool IsStart(int64 index) const
Returns true if 'index' represents the first node of a route.
int64 Next(const Assignment &assignment, int64 index) const
Assignment inspection Returns the variable index of the node directly after the node corresponding to...
const Assignment *const PreAssignment() const
Returns an assignment used to fix some of the variables of the problem.
void AddHardTypeIncompatibility(int type1, int type2)
Incompatibilities: Two nodes with "hard" incompatible types cannot share the same route at all,...
const absl::flat_hash_set< int > & GetTemporalTypeIncompatibilitiesOfType(int type) const
std::function< bool(int64, int64, int64)> VariableValueComparator
bool IsVehicleUsed(const Assignment &assignment, int vehicle) const
Returns true if the route of 'vehicle' is non empty in 'assignment'.
int64 ComputeLowerBound()
Computes a lower bound to the routing problem solving a linear assignment problem.
Assignment * ReadAssignmentFromRoutes(const std::vector< std::vector< int64 >> &routes, bool ignore_inactive_indices)
Restores the routes as the current solution.
const std::vector< IntVar * > & VehicleVars() const
Returns all vehicle variables of the model, such that VehicleVars(i) is the vehicle variable of the n...
void CloseModelWithParameters(const RoutingSearchParameters &search_parameters)
Same as above taking search parameters (as of 10/2015 some the parameters have to be set when closing...
bool CheckLimit()
Returns true if the search limit has been crossed.
int64 UnperformedPenaltyOrValue(int64 default_value, int64 var_index) const
Same as above except that it returns default_value instead of 0 when penalty is not well defined (def...
int64 GetArcCostForVehicle(int64 from_index, int64 to_index, int64 vehicle) const
Returns the cost of the transit arc between two nodes for a given vehicle.
std::string DebugOutputAssignment(const Assignment &solution_assignment, const std::string &dimension_to_print) const
Print some debugging information about an assignment, including the feasible intervals of the CumulVa...
void CloseModel()
Closes the current routing model; after this method is called, no modification to the model can be do...
int64 End(int vehicle) const
Returns the variable index of the ending node of a vehicle route.
void AddVariableMinimizedByFinalizer(IntVar *var)
Adds a variable to minimize in the solution finalizer.
std::function< std::vector< operations_research::IntVar * >(RoutingModel *)> GetTabuVarsCallback
Sets the callback returning the variable to use for the Tabu Search metaheuristic.
int64 GetArcCostForClass(int64 from_index, int64 to_index, int64 cost_class_index) const
Returns the cost of the segment between two nodes for a given cost class.
void AddIntervalToAssignment(IntervalVar *const interval)
DecisionBuilder * MakeGuidedSlackFinalizer(const RoutingDimension *dimension, std::function< int64(int64)> initializer)
The next few members are in the public section only for testing purposes.
void SetArcCostEvaluatorOfAllVehicles(int evaluator_index)
Sets the cost function of the model such that the cost of a segment of a route between node 'from' an...
std::vector< int64 > duration_max
void SetFixedCostOfAllVehicles(int64 cost)
Sets the fixed cost of all vehicle routes.
void CloseVisitTypes()
This function should be called once all node visit types have been set and prior to adding any incomp...
int64 GetDepot() const
Returns the variable index of the first starting or ending node of all routes.
std::function< int64(int64)> RoutingTransitCallback1
int VehicleIndex(int index) const
Returns the vehicle of the given start/end index, and -1 if the given index is not a vehicle start/en...
friend class RoutingModelInspector
int GetVehicleClassesCount() const
Returns the number of different vehicle classes in the model.
void SetSweepArranger(SweepArranger *sweep_arranger)
int64 UnperformedPenalty(int64 var_index) const
Get the "unperformed" penalty of a node.
bool CostsAreHomogeneousAcrossVehicles() const
Whether costs are homogeneous across all vehicles.
routing_no_lns(default:false) int GetVisitType(int64 index) const
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in c...
int64 Start(int vehicle) const
Model inspection.
const Assignment * PackCumulsOfOptimizerDimensionsFromAssignment(const Assignment *original_assignment, absl::Duration duration_limit)
For every dimension in the model's dimensions_for_local/global_optimizer_, this method tries to pack ...
const absl::flat_hash_set< int > & GetHardTypeIncompatibilitiesOfType(int type) const
Returns visit types incompatible with a given type.
Status status() const
Returns the current status of the routing model.
bool HasVehicleWithCostClassIndex(CostClassIndex cost_class_index) const
Returns true iff the model contains a vehicle with the given cost_class_index.
void AddLocalSearchFilter(LocalSearchFilter *filter)
Adds a custom local search filter to the list of filters used to speed up local search by pruning unf...
void AddTemporalTypeIncompatibility(int type1, int type2)
int64 GetNumberOfDecisionsInFirstSolution(const RoutingSearchParameters &search_parameters) const
Returns statistics on first solution search, number of decisions sent to filters, number of decisions...
bool AreEmptyRouteCostsConsideredForVehicle(int vehicle) const
bool operator<(const StartEndValue &other) const
A structure to hold tasks described by their features.
std::vector< int64 > end_min
void AddLocalSearchOperator(LocalSearchOperator *ls_operator)
Adds a local search operator to the set of operators used to solve the vehicle routing problem.
Assignment * MutablePreAssignment()
void AddVariableMaximizedByFinalizer(IntVar *var)
Adds a variable to maximize in the solution finalizer (see above for information on the solution fina...
void SetAssignmentFromOtherModelAssignment(Assignment *target_assignment, const RoutingModel *source_model, const Assignment *source_assignment)
Given a "source_model" and its "source_assignment", resets "target_assignment" with the IntVar variab...
int nodes() const
Sizes and indices Returns the number of nodes in the model.
void SetTabuVarsCallback(GetTabuVarsCallback tabu_var_callback)
const std::vector< int64 > & GetAmortizedQuadraticCostFactorOfVehicles() const
bool operator<(const VehicleClassEntry &other) const
std::vector< int64 > start_min
const std::vector< IntVar * > & Nexts() const
Variables.
IntVar * ApplyLocks(const std::vector< int64 > &locks)
Applies a lock chain to the next search.
int64 GetFixedCostOfVehicle(int vehicle) const
Returns the route fixed cost taken into account if the route of the vehicle is not empty,...
bool ArcIsMoreConstrainedThanArc(int64 from, int64 to1, int64 to2)
Returns whether the arc from->to1 is more constrained than from->to2, taking into account,...
Assignment * CompactAssignment(const Assignment &assignment) const
Returns a compacted version of the given assignment, in which all vehicles with id lower or equal to ...
void SetFixedCostOfVehicle(int64 cost, int vehicle)
Sets the fixed cost of one vehicle route.
std::function< void(int64)> ObjectiveWatcher
void SetArcCostEvaluatorOfVehicle(int evaluator_index, int vehicle)
Sets the cost function for a given vehicle route.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in c...
bool RoutesToAssignment(const std::vector< std::vector< int64 >> &routes, bool ignore_inactive_indices, bool close_routes, Assignment *const assignment) const
Fills an assignment from a specification of the routes of the vehicles.
SweepArranger * sweep_arranger() const
Returns the sweep arranger to be used by routing heuristics.
int64 GetNumberOfRejectsInFirstSolution(const RoutingSearchParameters &search_parameters) const
Solver * solver() const
Returns the underlying constraint solver.
quadratic_cost_factor_of_vehicle_ *[v] square of length of route v void SetAmortizedCostFactorsOfAllVehicles(int64 linear_cost_factor, int64 quadratic_cost_factor)
The following methods set the linear and quadratic cost factors of vehicles (must be positive values)...
std::vector< bool > is_preemptible
VehicleClassIndex GetVehicleClassIndexOfVehicle(int64 vehicle) const
int GetNumberOfVisitTypes() const
std::vector< RoutingIndexPair > RoutingIndexPairs
void AddAtSolutionCallback(std::function< void()> callback)
Adds a callback called each time a solution is found during the search.
*RoutingModel model(manager)
std::function< int64(int64, int64)> IndexEvaluator2
const std::vector< absl::flat_hash_set< int > > & GetTemporalRequiredTypeAlternativesOfType(int type) const
std::vector< int64 > end_max
std::pair< std::vector< int64 >, std::vector< int64 > > RoutingIndexPair
NOTE(user): keep the "> >" for SWIG.
const Assignment * SolveFromAssignmentWithParameters(const Assignment *assignment, const RoutingSearchParameters &search_parameters, std::vector< const Assignment * > *solutions=nullptr)
DecisionBuilder * MakeSelfDependentDimensionFinalizer(const RoutingDimension *dimension)
MakeSelfDependentDimensionFinalizer is a finalizer for the slacks of a self-dependent dimension.
Assignment * ReadAssignment(const std::string &file_name)
Reads an assignment from a file and returns the current solution.
const std::vector< absl::flat_hash_set< int > > & GetSameVehicleRequiredTypeAlternativesOfType(int type) const
clang-format off Returns the sets of same-vehicle/temporal requirement alternatives for the given typ...
int64 Size() const
Returns the number of next variables in the model.
int64 GetArcCostForFirstSolution(int64 from_index, int64 to_index) const
Returns the cost of the arc in the context of the first solution strategy.
void AddToAssignment(IntVar *const var)
Adds an extra variable to the vehicle routing assignment.
friend class RoutingDimension
const std::vector< int > & GetSameVehicleIndicesOfIndex(int node) const
Returns variable indices of nodes constrained to be on the same route.
std::vector< int64 > start_max