OR-Tools  9.6
routing.h
Go to the documentation of this file.
1 // Copyright 2010-2022 Google LLC
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 // http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 
68 // TODO(user): Add a section on costs (vehicle arc costs, span costs,
69 // disjunctions costs).
70 //
156 
157 #ifndef OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_H_
158 #define OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_H_
159 
160 #include <algorithm>
161 #include <cstdint>
162 #include <deque>
163 #include <functional>
164 #include <memory>
165 #include <set>
166 #include <string>
167 #include <tuple>
168 #include <utility>
169 #include <vector>
170 
171 #include "absl/container/flat_hash_map.h"
172 #include "absl/container/flat_hash_set.h"
173 #include "absl/container/inlined_vector.h"
174 #include "absl/time/time.h"
175 #include "ortools/base/int_type.h"
177 #include "ortools/base/logging.h"
178 #include "ortools/base/macros.h"
182 #include "ortools/constraint_solver/routing_enums.pb.h"
184 #include "ortools/constraint_solver/routing_parameters.pb.h"
186 #include "ortools/graph/graph.h"
187 #include "ortools/sat/theta_tree.h"
192 
193 namespace operations_research {
194 
195 class GlobalDimensionCumulOptimizer;
196 class LocalDimensionCumulOptimizer;
197 class LocalSearchPhaseParameters;
198 #ifndef SWIG
199 class IndexNeighborFinder;
200 class IntVarFilteredDecisionBuilder;
201 #endif
202 class RoutingDimension;
203 #ifndef SWIG
205 class SweepArranger;
206 #endif
207 
209  public:
210  explicit PathsMetadata(const RoutingIndexManager& manager) {
211  const int num_indices = manager.num_indices();
212  const int num_paths = manager.num_vehicles();
213  path_of_node_.resize(num_indices, -1);
214  is_start_.resize(num_indices, false);
215  is_end_.resize(num_indices, false);
216  start_of_path_.resize(num_paths);
217  end_of_path_.resize(num_paths);
218  for (int v = 0; v < num_paths; ++v) {
219  const int64_t start = manager.GetStartIndex(v);
220  start_of_path_[v] = start;
221  path_of_node_[start] = v;
222  is_start_[start] = true;
223  const int64_t end = manager.GetEndIndex(v);
224  end_of_path_[v] = end;
225  path_of_node_[end] = v;
226  is_end_[end] = true;
227  }
228  }
229 
230  bool IsStart(int64_t node) const { return is_start_[node]; }
231  bool IsEnd(int64_t node) const { return is_end_[node]; }
232  int GetPath(int64_t start_or_end_node) const {
233  return path_of_node_[start_or_end_node];
234  }
235  const std::vector<int64_t>& Starts() const { return start_of_path_; }
236  const std::vector<int64_t>& Ends() const { return end_of_path_; }
237 
238  private:
239  std::vector<bool> is_start_;
240  std::vector<bool> is_end_;
241  std::vector<int64_t> start_of_path_;
242  std::vector<int64_t> end_of_path_;
243  std::vector<int64_t> path_of_node_;
244 };
245 
247  public:
249  enum Status {
266  };
267 
276  };
277  typedef RoutingCostClassIndex CostClassIndex;
278  typedef RoutingDimensionIndex DimensionIndex;
279  typedef RoutingDisjunctionIndex DisjunctionIndex;
280  typedef RoutingVehicleClassIndex VehicleClassIndex;
283 
284 // TODO(user): Remove all SWIG guards by adding the @ignore in .i.
285 #if !defined(SWIG)
288 #endif // SWIG
289 
290 #if !defined(SWIG)
306  };
307  typedef std::function<StateDependentTransit(int64_t, int64_t)>
309 #endif // SWIG
310 
311 #if !defined(SWIG)
312  struct CostClass {
315 
330 
336  struct DimensionCost {
340  bool operator<(const DimensionCost& cost) const {
341  if (transit_evaluator_class != cost.transit_evaluator_class) {
342  return transit_evaluator_class < cost.transit_evaluator_class;
343  }
344  return cost_coefficient < cost.cost_coefficient;
345  }
346  };
347  std::vector<DimensionCost>
349 
352 
354  static bool LessThan(const CostClass& a, const CostClass& b) {
355  if (a.evaluator_index != b.evaluator_index) {
356  return a.evaluator_index < b.evaluator_index;
357  }
358  return a.dimension_transit_evaluator_class_and_cost_coefficient <
359  b.dimension_transit_evaluator_class_and_cost_coefficient;
360  }
361  };
362 
363  struct VehicleClass {
367  int64_t fixed_cost;
374  // TODO(user): Find equivalent start/end nodes wrt dimensions and
375  // callbacks.
392 
394  static bool LessThan(const VehicleClass& a, const VehicleClass& b);
395  };
396 #endif // defined(SWIG)
397 
404  int64_t fixed_cost;
405 
406  bool operator<(const VehicleClassEntry& other) const {
407  return std::tie(fixed_cost, vehicle_class) <
408  std::tie(other.fixed_cost, other.vehicle_class);
409  }
410  };
411 
412  int NumTypes() const { return sorted_vehicle_classes_per_type.size(); }
413 
414  int Type(int vehicle) const {
415  DCHECK_LT(vehicle, type_index_of_vehicle.size());
416  return type_index_of_vehicle[vehicle];
417  }
418 
419  std::vector<int> type_index_of_vehicle;
420  // clang-format off
421  std::vector<std::set<VehicleClassEntry> > sorted_vehicle_classes_per_type;
422  std::vector<std::deque<int> > vehicles_per_vehicle_class;
423  // clang-format on
424  };
425 
438  public:
440  class Attributes {
441  public:
442  Attributes();
444 
445  const Domain& start_domain() const { return start_domain_; }
446  const Domain& end_domain() const { return end_domain_; }
447 
448  private:
452  Domain start_domain_;
454  Domain end_domain_;
455  };
456 
458  class Resource {
459  public:
461  const RoutingDimension* dimension) const;
462 
463  private:
464  explicit Resource(const RoutingModel* model) : model_(model) {}
465 
466  void SetDimensionAttributes(ResourceGroup::Attributes attributes,
467  const RoutingDimension* dimension);
468  const ResourceGroup::Attributes& GetDefaultAttributes() const;
469 
470  const RoutingModel* const model_;
471  absl::flat_hash_map<DimensionIndex, ResourceGroup::Attributes>
472  dimension_attributes_;
473 
474  friend class ResourceGroup;
475  };
476 
478  : model_(model), vehicle_requires_resource_(model->vehicles(), false) {}
479 
482  int AddResource(Attributes attributes, const RoutingDimension* dimension);
483 
487  void NotifyVehicleRequiresAResource(int vehicle);
488 
489  const std::vector<int>& GetVehiclesRequiringAResource() const {
490  return vehicles_requiring_resource_;
491  }
492 
493  bool VehicleRequiresAResource(int vehicle) const {
494  return vehicle_requires_resource_[vehicle];
495  }
496 
497  const std::vector<Resource>& GetResources() const { return resources_; }
498  const Resource& GetResource(int resource_index) const {
499  DCHECK_LT(resource_index, resources_.size());
500  return resources_[resource_index];
501  }
502  const absl::flat_hash_set<DimensionIndex>& GetAffectedDimensionIndices()
503  const {
504  return affected_dimension_indices_;
505  }
506  int Size() const { return resources_.size(); }
507 
508  private:
509  const RoutingModel* const model_;
510  std::vector<Resource> resources_;
511  std::vector<bool> vehicle_requires_resource_;
512  std::vector<int> vehicles_requiring_resource_;
514  absl::flat_hash_set<DimensionIndex> affected_dimension_indices_;
515  };
516 
518  static const int64_t kNoPenalty;
519 
523 
527 
531  explicit RoutingModel(const RoutingIndexManager& index_manager);
532  RoutingModel(const RoutingIndexManager& index_manager,
533  const RoutingModelParameters& parameters);
534  ~RoutingModel();
535 
537  int RegisterUnaryTransitVector(std::vector<int64_t> values);
540 
542  std::vector<std::vector<int64_t> /*needed_for_swig*/> values);
545 
547  const TransitCallback2& TransitCallback(int callback_index) const {
548  CHECK_LT(callback_index, transit_evaluators_.size());
549  return transit_evaluators_[callback_index];
550  }
551  const TransitCallback1& UnaryTransitCallbackOrNull(int callback_index) const {
552  CHECK_LT(callback_index, unary_transit_evaluators_.size());
553  return unary_transit_evaluators_[callback_index];
554  }
556  int callback_index) const {
557  CHECK_LT(callback_index, state_dependent_transit_evaluators_.size());
558  return state_dependent_transit_evaluators_[callback_index];
559  }
560 
562 
574 
583  bool AddDimension(int evaluator_index, int64_t slack_max, int64_t capacity,
584  bool fix_start_cumul_to_zero, const std::string& name);
586  const std::vector<int>& evaluator_indices, int64_t slack_max,
587  int64_t capacity, bool fix_start_cumul_to_zero, const std::string& name);
588  bool AddDimensionWithVehicleCapacity(int evaluator_index, int64_t slack_max,
589  std::vector<int64_t> vehicle_capacities,
590  bool fix_start_cumul_to_zero,
591  const std::string& name);
593  const std::vector<int>& evaluator_indices, int64_t slack_max,
594  std::vector<int64_t> vehicle_capacities, bool fix_start_cumul_to_zero,
595  const std::string& name);
604  std::pair<int, bool> AddConstantDimensionWithSlack(
605  int64_t value, int64_t capacity, int64_t slack_max,
606  bool fix_start_cumul_to_zero, const std::string& name);
607  std::pair<int, bool> AddConstantDimension(int64_t value, int64_t capacity,
608  bool fix_start_cumul_to_zero,
609  const std::string& name) {
611  fix_start_cumul_to_zero, name);
612  }
622  std::pair<int, bool> AddVectorDimension(std::vector<int64_t> values,
623  int64_t capacity,
624  bool fix_start_cumul_to_zero,
625  const std::string& name);
635  std::pair<int, bool> AddMatrixDimension(
636  std::vector<std::vector<int64_t> /*needed_for_swig*/> values,
637  int64_t capacity, bool fix_start_cumul_to_zero, const std::string& name);
645  const std::vector<int>& pure_transits,
646  const std::vector<int>& dependent_transits,
647  const RoutingDimension* base_dimension, int64_t slack_max,
648  std::vector<int64_t> vehicle_capacities, bool fix_start_cumul_to_zero,
649  const std::string& name) {
650  return AddDimensionDependentDimensionWithVehicleCapacityInternal(
651  pure_transits, dependent_transits, base_dimension, slack_max,
652  std::move(vehicle_capacities), fix_start_cumul_to_zero, name);
653  }
654 
657  const std::vector<int>& transits, const RoutingDimension* base_dimension,
658  int64_t slack_max, std::vector<int64_t> vehicle_capacities,
659  bool fix_start_cumul_to_zero, const std::string& name);
662  int transit, const RoutingDimension* base_dimension, int64_t slack_max,
663  int64_t vehicle_capacity, bool fix_start_cumul_to_zero,
664  const std::string& name);
666  int pure_transit, int dependent_transit,
667  const RoutingDimension* base_dimension, int64_t slack_max,
668  int64_t vehicle_capacity, bool fix_start_cumul_to_zero,
669  const std::string& name);
670 
673  const std::function<int64_t(int64_t)>& f, int64_t domain_start,
674  int64_t domain_end);
675 
686  std::vector<IntVar*> spans,
687  std::vector<IntVar*> total_slacks);
688 
690  // TODO(user): rename.
691  std::vector<std::string> GetAllDimensionNames() const;
693  const std::vector<RoutingDimension*>& GetDimensions() const {
694  return dimensions_.get();
695  }
697  std::vector<RoutingDimension*> GetDimensionsWithSoftOrSpanCosts() const;
698 
700  std::vector<const RoutingDimension*> GetDimensionsWithGlobalCumulOptimizers()
701  const;
702  std::vector<const RoutingDimension*> GetDimensionsWithLocalCumulOptimizers()
703  const;
704 
706  bool HasGlobalCumulOptimizer(const RoutingDimension& dimension) const {
707  return GetGlobalCumulOptimizerIndex(dimension) >= 0;
708  }
709  bool HasLocalCumulOptimizer(const RoutingDimension& dimension) const {
710  return GetLocalCumulOptimizerIndex(dimension) >= 0;
711  }
715  const RoutingDimension& dimension) const;
717  const RoutingDimension& dimension) const;
719  const RoutingDimension& dimension) const;
721  const RoutingDimension& dimension) const;
722 
724  bool HasDimension(const std::string& dimension_name) const;
727  const std::string& dimension_name) const;
731  const std::string& dimension_name) const;
736  void SetPrimaryConstrainedDimension(const std::string& dimension_name) {
737  DCHECK(dimension_name.empty() || HasDimension(dimension_name));
738  primary_constrained_dimension_ = dimension_name;
739  }
741  const std::string& GetPrimaryConstrainedDimension() const {
742  return primary_constrained_dimension_;
743  }
744 
747  int AddResourceGroup();
748  // clang-format off
749  const std::vector<std::unique_ptr<ResourceGroup> >& GetResourceGroups()
750  const {
751  return resource_groups_;
752  }
753  // clang-format on
754  ResourceGroup* GetResourceGroup(int rg_index) const {
755  DCHECK_LT(rg_index, resource_groups_.size());
756  return resource_groups_[rg_index].get();
757  }
758 
761  const std::vector<int>& GetDimensionResourceGroupIndices(
762  const RoutingDimension* dimension) const;
763 
766  int GetDimensionResourceGroupIndex(const RoutingDimension* dimension) const {
767  DCHECK_EQ(GetDimensionResourceGroupIndices(dimension).size(), 1);
768  return GetDimensionResourceGroupIndices(dimension)[0];
769  }
770 
787  DisjunctionIndex AddDisjunction(const std::vector<int64_t>& indices,
788  int64_t penalty = kNoPenalty,
789  int64_t max_cardinality = 1);
791  const std::vector<DisjunctionIndex>& GetDisjunctionIndices(
792  int64_t index) const {
793  return index_to_disjunctions_[index];
794  }
798  template <typename F>
800  int64_t index, int64_t max_cardinality, F f) const {
801  for (const DisjunctionIndex disjunction : GetDisjunctionIndices(index)) {
802  if (disjunctions_[disjunction].value.max_cardinality == max_cardinality) {
803  for (const int64_t d_index : disjunctions_[disjunction].indices) {
804  f(d_index);
805  }
806  }
807  }
808  }
809 #if !defined(SWIGPYTHON)
812  const std::vector<int64_t>& GetDisjunctionNodeIndices(
813  DisjunctionIndex index) const {
814  return disjunctions_[index].indices;
815  }
816 #endif // !defined(SWIGPYTHON)
818  int64_t GetDisjunctionPenalty(DisjunctionIndex index) const {
819  return disjunctions_[index].value.penalty;
820  }
824  return disjunctions_[index].value.max_cardinality;
825  }
827  int GetNumberOfDisjunctions() const { return disjunctions_.size(); }
830  bool HasMandatoryDisjunctions() const;
833  bool HasMaxCardinalityConstrainedDisjunctions() const;
838  std::vector<std::pair<int64_t, int64_t>> GetPerfectBinaryDisjunctions() const;
844  void IgnoreDisjunctionsAlreadyForcedToZero();
845 
849  void AddSoftSameVehicleConstraint(const std::vector<int64_t>& indices,
850  int64_t cost);
851 
856  void SetAllowedVehiclesForIndex(const std::vector<int>& vehicles,
857  int64_t index);
858 
860  bool IsVehicleAllowedForIndex(int vehicle, int64_t index) {
861  return allowed_vehicles_[index].empty() ||
862  allowed_vehicles_[index].find(vehicle) !=
863  allowed_vehicles_[index].end();
864  }
865 
880  // TODO(user): Remove this when model introspection detects linked nodes.
881  void AddPickupAndDelivery(int64_t pickup, int64_t delivery);
885  void AddPickupAndDeliverySets(DisjunctionIndex pickup_disjunction,
886  DisjunctionIndex delivery_disjunction);
887  // clang-format off
891  const std::vector<std::pair<int, int> >&
892  GetPickupIndexPairs(int64_t node_index) const;
894  const std::vector<std::pair<int, int> >&
895  GetDeliveryIndexPairs(int64_t node_index) const;
896  // clang-format on
897 
900  void SetPickupAndDeliveryPolicyOfAllVehicles(PickupAndDeliveryPolicy policy);
901  void SetPickupAndDeliveryPolicyOfVehicle(PickupAndDeliveryPolicy policy,
902  int vehicle);
903  PickupAndDeliveryPolicy GetPickupAndDeliveryPolicyOfVehicle(
904  int vehicle) const;
907 
908  int GetNumOfSingletonNodes() const;
909 
910 #ifndef SWIG
913  return pickup_delivery_pairs_;
914  }
915  const std::vector<std::pair<DisjunctionIndex, DisjunctionIndex>>&
917  return pickup_delivery_disjunctions_;
918  }
924  DCHECK(closed_);
925  return implicit_pickup_delivery_pairs_without_alternatives_;
926  }
927 #endif // SWIG
939  enum VisitTypePolicy {
954  TYPE_SIMULTANEOUSLY_ADDED_AND_REMOVED
955  };
956  // TODO(user): Support multiple visit types per node?
957  void SetVisitType(int64_t index, int type, VisitTypePolicy type_policy);
958  int GetVisitType(int64_t index) const;
959  const std::vector<int>& GetSingleNodesOfType(int type) const;
960  const std::vector<int>& GetPairIndicesOfType(int type) const;
961  VisitTypePolicy GetVisitTypePolicy(int64_t index) const;
964  // TODO(user): Reconsider the logic and potentially remove the need to
966  void CloseVisitTypes();
967  int GetNumberOfVisitTypes() const { return num_visit_types_; }
968 #ifndef SWIG
969  const std::vector<std::vector<int>>& GetTopologicallySortedVisitTypes()
970  const {
971  DCHECK(closed_);
972  return topologically_sorted_visit_types_;
973  }
974 #endif // SWIG
979  void AddHardTypeIncompatibility(int type1, int type2);
980  void AddTemporalTypeIncompatibility(int type1, int type2);
982  const absl::flat_hash_set<int>& GetHardTypeIncompatibilitiesOfType(
983  int type) const;
984  const absl::flat_hash_set<int>& GetTemporalTypeIncompatibilitiesOfType(
985  int type) const;
989  return has_hard_type_incompatibilities_;
990  }
992  return has_temporal_type_incompatibilities_;
993  }
1004  void AddSameVehicleRequiredTypeAlternatives(
1005  int dependent_type, absl::flat_hash_set<int> required_type_alternatives);
1010  void AddRequiredTypeAlternativesWhenAddingType(
1011  int dependent_type, absl::flat_hash_set<int> required_type_alternatives);
1017  void AddRequiredTypeAlternativesWhenRemovingType(
1018  int dependent_type, absl::flat_hash_set<int> required_type_alternatives);
1019  // clang-format off
1022  const std::vector<absl::flat_hash_set<int> >&
1023  GetSameVehicleRequiredTypeAlternativesOfType(int type) const;
1025  const std::vector<absl::flat_hash_set<int> >&
1026  GetRequiredTypeAlternativesWhenAddingType(int type) const;
1028  const std::vector<absl::flat_hash_set<int> >&
1029  GetRequiredTypeAlternativesWhenRemovingType(int type) const;
1030  // clang-format on
1034  return has_same_vehicle_type_requirements_;
1035  }
1037  return has_temporal_type_requirements_;
1038  }
1039 
1042  bool HasTypeRegulations() const {
1043  return HasTemporalTypeIncompatibilities() ||
1044  HasHardTypeIncompatibilities() || HasSameVehicleTypeRequirements() ||
1045  HasTemporalTypeRequirements();
1046  }
1047 
1052  int64_t UnperformedPenalty(int64_t var_index) const;
1056  int64_t UnperformedPenaltyOrValue(int64_t default_value,
1057  int64_t var_index) const;
1061  int64_t GetDepot() const;
1062 
1067  void SetMaximumNumberOfActiveVehicles(int max_active_vehicles) {
1068  max_active_vehicles_ = max_active_vehicles;
1069  }
1071  int GetMaximumNumberOfActiveVehicles() const { return max_active_vehicles_; }
1075  void SetArcCostEvaluatorOfAllVehicles(int evaluator_index);
1077  void SetArcCostEvaluatorOfVehicle(int evaluator_index, int vehicle);
1080  void SetFixedCostOfAllVehicles(int64_t cost);
1082  void SetFixedCostOfVehicle(int64_t cost, int vehicle);
1086  int64_t GetFixedCostOfVehicle(int vehicle) const;
1087 
1103  void SetAmortizedCostFactorsOfAllVehicles(int64_t linear_cost_factor,
1104  int64_t quadratic_cost_factor);
1106  void SetAmortizedCostFactorsOfVehicle(int64_t linear_cost_factor,
1107  int64_t quadratic_cost_factor,
1108  int vehicle);
1109 
1110  const std::vector<int64_t>& GetAmortizedLinearCostFactorOfVehicles() const {
1111  return linear_cost_factor_of_vehicle_;
1112  }
1113  const std::vector<int64_t>& GetAmortizedQuadraticCostFactorOfVehicles()
1114  const {
1115  return quadratic_cost_factor_of_vehicle_;
1116  }
1117 
1118  void SetVehicleUsedWhenEmpty(bool is_used, int vehicle) {
1119  DCHECK_LT(vehicle, vehicles_);
1120  vehicle_used_when_empty_[vehicle] = is_used;
1121  }
1122 
1123  bool IsVehicleUsedWhenEmpty(int vehicle) const {
1124  DCHECK_LT(vehicle, vehicles_);
1125  return vehicle_used_when_empty_[vehicle];
1126  }
1127 
1130 #ifndef SWIG
1132  return first_solution_evaluator_;
1133  }
1134 #endif
1137  first_solution_evaluator_ = std::move(evaluator);
1138  }
1141  void AddLocalSearchOperator(LocalSearchOperator* ls_operator);
1143  void AddSearchMonitor(SearchMonitor* const monitor);
1147  void AddAtSolutionCallback(std::function<void()> callback);
1152  void AddVariableMinimizedByFinalizer(IntVar* var);
1155  void AddVariableMaximizedByFinalizer(IntVar* var);
1158  void AddWeightedVariableMinimizedByFinalizer(IntVar* var, int64_t cost);
1161  void AddWeightedVariableMaximizedByFinalizer(IntVar* var, int64_t cost);
1164  void AddVariableTargetToFinalizer(IntVar* var, int64_t target);
1167  void AddWeightedVariableTargetToFinalizer(IntVar* var, int64_t target,
1168  int64_t cost);
1175  void CloseModel();
1178  void CloseModelWithParameters(
1179  const RoutingSearchParameters& search_parameters);
1186  const Assignment* Solve(const Assignment* assignment = nullptr);
1195  const RoutingSearchParameters& search_parameters,
1196  std::vector<const Assignment*>* solutions = nullptr);
1199  const Assignment* SolveFromAssignmentWithParameters(
1200  const Assignment* assignment,
1201  const RoutingSearchParameters& search_parameters,
1202  std::vector<const Assignment*>* solutions = nullptr);
1205  const Assignment* SolveFromAssignmentsWithParameters(
1206  const std::vector<const Assignment*>& assignments,
1207  const RoutingSearchParameters& search_parameters,
1208  std::vector<const Assignment*>* solutions = nullptr);
1214  void SetAssignmentFromOtherModelAssignment(
1215  Assignment* target_assignment, const RoutingModel* source_model,
1216  const Assignment* source_assignment);
1222  // TODO(user): Add support for non-homogeneous costs and disjunctions.
1223  int64_t ComputeLowerBound();
1225  Status status() const { return status_; }
1227  bool enable_deep_serialization() const { return enable_deep_serialization_; }
1236  IntVar* ApplyLocks(const std::vector<int64_t>& locks);
1245  bool ApplyLocksToAllVehicles(const std::vector<std::vector<int64_t>>& locks,
1246  bool close_routes);
1251  const Assignment* PreAssignment() const { return preassignment_; }
1252  Assignment* MutablePreAssignment() { return preassignment_; }
1256  bool WriteAssignment(const std::string& file_name) const;
1260  Assignment* ReadAssignment(const std::string& file_name);
1263  Assignment* RestoreAssignment(const Assignment& solution);
1269  Assignment* ReadAssignmentFromRoutes(
1270  const std::vector<std::vector<int64_t>>& routes,
1271  bool ignore_inactive_indices);
1288  bool RoutesToAssignment(const std::vector<std::vector<int64_t>>& routes,
1289  bool ignore_inactive_indices, bool close_routes,
1290  Assignment* const assignment) const;
1294  void AssignmentToRoutes(
1295  const Assignment& assignment,
1296  std::vector<std::vector<int64_t>>* const routes) const;
1301 #ifndef SWIG
1302  std::vector<std::vector<int64_t>> GetRoutesFromAssignment(
1303  const Assignment& assignment);
1304 #endif
1322  Assignment* CompactAssignment(const Assignment& assignment) const;
1326  Assignment* CompactAndCheckAssignment(const Assignment& assignment) const;
1328  void AddToAssignment(IntVar* const var);
1329  void AddIntervalToAssignment(IntervalVar* const interval);
1340  const Assignment* PackCumulsOfOptimizerDimensionsFromAssignment(
1341  const Assignment* original_assignment, absl::Duration duration_limit,
1342  bool* time_limit_was_reached = nullptr);
1351  // TODO(user): Adjust the inlined vector sizes based on experiments.
1354  absl::InlinedVector<int64_t, 8> x_anchors;
1360  absl::InlinedVector<int64_t, 8> y_anchors;
1361 
1362  std::string DebugString(std::string line_prefix = "") const;
1363  };
1364 
1368 
1373 
1379 
1383 
1389 
1390  std::string DebugString(std::string line_prefix = "") const;
1391  };
1392 
1395  std::vector<TransitionInfo> transition_info;
1398 
1399  std::string DebugString(std::string line_prefix = "") const;
1400  };
1401 
1402 #ifndef SWIG
1403  // TODO(user): Revisit if coordinates are added to the RoutingModel class.
1404  void SetSweepArranger(SweepArranger* sweep_arranger);
1406  SweepArranger* sweep_arranger() const;
1407 #endif
1409  public:
1411 
1414  void ComputeNeighbors(const RoutingModel& routing_model, int num_neighbors);
1416  const std::vector<int>& GetNeighborsOfNodeForCostClass(
1417  int cost_class, int node_index) const {
1418  return all_nodes_.empty() ? node_index_to_neighbors_by_cost_class_
1419  [node_index][cost_class]
1420  ->PositionsSetAtLeastOnce()
1421  : all_nodes_;
1422  }
1423 
1424  private:
1425  std::vector<std::vector<std::unique_ptr<SparseBitset<int>>>>
1426  node_index_to_neighbors_by_cost_class_;
1427  std::vector<int> all_nodes_;
1428  };
1429 
1432  const NodeNeighborsByCostClass* GetOrCreateNodeNeighborsByCostClass(
1433  int num_neighbors);
1440  CHECK(filter != nullptr);
1441  if (closed_) {
1442  LOG(WARNING) << "Model is closed, filter addition will be ignored.";
1443  }
1444  extra_filters_.push_back({filter, LocalSearchFilterManager::kRelax});
1445  extra_filters_.push_back({filter, LocalSearchFilterManager::kAccept});
1446  }
1447 
1450  int64_t Start(int vehicle) const { return paths_metadata_.Starts()[vehicle]; }
1452  int64_t End(int vehicle) const { return paths_metadata_.Ends()[vehicle]; }
1454  bool IsStart(int64_t index) const { return paths_metadata_.IsStart(index); }
1456  bool IsEnd(int64_t index) const { return paths_metadata_.IsEnd(index); }
1459  int VehicleIndex(int64_t index) const {
1460  return paths_metadata_.GetPath(index);
1461  }
1465  int64_t Next(const Assignment& assignment, int64_t index) const;
1467  bool IsVehicleUsed(const Assignment& assignment, int vehicle) const;
1468 
1469 #if !defined(SWIGPYTHON)
1472  const std::vector<IntVar*>& Nexts() const { return nexts_; }
1475  const std::vector<IntVar*>& VehicleVars() const { return vehicle_vars_; }
1479  const std::vector<IntVar*>& ResourceVars(int resource_group) const {
1480  return resource_vars_[resource_group];
1481  }
1482 #endif
1485  IntVar* NextVar(int64_t index) const { return nexts_[index]; }
1487  IntVar* ActiveVar(int64_t index) const { return active_[index]; }
1490  IntVar* ActiveVehicleVar(int vehicle) const {
1491  return vehicle_active_[vehicle];
1492  }
1496  IntVar* VehicleRouteConsideredVar(int vehicle) const {
1497  return vehicle_route_considered_[vehicle];
1498  }
1501  IntVar* VehicleVar(int64_t index) const { return vehicle_vars_[index]; }
1505  IntVar* ResourceVar(int vehicle, int resource_group) const {
1506  DCHECK_LT(resource_group, resource_vars_.size());
1507  DCHECK_LT(vehicle, resource_vars_[resource_group].size());
1508  return resource_vars_[resource_group][vehicle];
1509  }
1511  IntVar* CostVar() const { return cost_; }
1512 
1515  int64_t GetArcCostForVehicle(int64_t from_index, int64_t to_index,
1516  int64_t vehicle) const;
1519  return costs_are_homogeneous_across_vehicles_;
1520  }
1523  int64_t GetHomogeneousCost(int64_t from_index, int64_t to_index) const {
1524  return GetArcCostForVehicle(from_index, to_index, /*vehicle=*/0);
1525  }
1528  int64_t GetArcCostForFirstSolution(int64_t from_index,
1529  int64_t to_index) const;
1536  int64_t GetArcCostForClass(int64_t from_index, int64_t to_index,
1537  int64_t /*CostClassIndex*/ cost_class_index) const;
1540  DCHECK(closed_);
1541  DCHECK_GE(vehicle, 0);
1542  DCHECK_LT(vehicle, cost_class_index_of_vehicle_.size());
1543  DCHECK_GE(cost_class_index_of_vehicle_[vehicle], 0);
1544  return cost_class_index_of_vehicle_[vehicle];
1545  }
1548  bool HasVehicleWithCostClassIndex(CostClassIndex cost_class_index) const {
1549  DCHECK(closed_);
1550  if (cost_class_index == kCostClassIndexOfZeroCost) {
1551  return has_vehicle_with_zero_cost_class_;
1552  }
1553  return cost_class_index < cost_classes_.size();
1554  }
1556  int GetCostClassesCount() const { return cost_classes_.size(); }
1559  return std::max(0, GetCostClassesCount() - 1);
1560  }
1562  DCHECK(closed_);
1563  return vehicle_class_index_of_vehicle_[vehicle];
1564  }
1568  DCHECK(closed_);
1569  const RoutingModel::VehicleTypeContainer& vehicle_type_container =
1570  GetVehicleTypeContainer();
1571  if (vehicle_class.value() >= GetVehicleClassesCount() ||
1572  vehicle_type_container.vehicles_per_vehicle_class[vehicle_class.value()]
1573  .empty()) {
1574  return -1;
1575  }
1576  return vehicle_type_container
1578  .front();
1579  }
1581  int GetVehicleClassesCount() const { return vehicle_classes_.size(); }
1583  const std::vector<int>& GetSameVehicleIndicesOfIndex(int node) const {
1584  DCHECK(closed_);
1585  return same_vehicle_groups_[same_vehicle_group_[node]];
1586  }
1587 
1589  DCHECK(closed_);
1590  return vehicle_type_container_;
1591  }
1592 
1611  bool ArcIsMoreConstrainedThanArc(int64_t from, int64_t to1, int64_t to2);
1616  std::string DebugOutputAssignment(
1617  const Assignment& solution_assignment,
1618  const std::string& dimension_to_print) const;
1624 #ifndef SWIG
1625  std::vector<std::vector<std::pair<int64_t, int64_t>>> GetCumulBounds(
1626  const Assignment& solution_assignment, const RoutingDimension& dimension);
1627 #endif
1630  Solver* solver() const { return solver_.get(); }
1631 
1634  bool CheckLimit(absl::Duration offset = absl::ZeroDuration()) {
1635  DCHECK(limit_ != nullptr);
1636  return limit_->CheckWithOffset(offset);
1637  }
1638 
1640  absl::Duration RemainingTime() const {
1641  DCHECK(limit_ != nullptr);
1642  return limit_->AbsoluteSolverDeadline() - solver_->Now();
1643  }
1644 
1646  absl::Duration TimeBuffer() const { return time_buffer_; }
1647 
1650  int nodes() const { return nodes_; }
1652  int vehicles() const { return vehicles_; }
1654  int64_t Size() const { return nodes_ + vehicles_ - start_end_count_; }
1655 
1658  int64_t GetNumberOfDecisionsInFirstSolution(
1659  const RoutingSearchParameters& search_parameters) const;
1660  int64_t GetNumberOfRejectsInFirstSolution(
1661  const RoutingSearchParameters& search_parameters) const;
1665  return automatic_first_solution_strategy_;
1666  }
1667 
1669  bool IsMatchingModel() const;
1670 
1673  bool AreRoutesInterdependent(const RoutingSearchParameters& parameters) const;
1674 
1675 #ifndef SWIG
1679  std::function<std::vector<operations_research::IntVar*>(RoutingModel*)>;
1680 
1681  void SetTabuVarsCallback(GetTabuVarsCallback tabu_var_callback);
1682 #endif // SWIG
1683 
1685  // TODO(user): Find a way to test and restrict the access at the same time.
1697  DecisionBuilder* MakeGuidedSlackFinalizer(
1698  const RoutingDimension* dimension,
1699  std::function<int64_t(int64_t)> initializer);
1700 #ifndef SWIG
1701  // TODO(user): MakeGreedyDescentLSOperator is too general for routing.h.
1706  static std::unique_ptr<LocalSearchOperator> MakeGreedyDescentLSOperator(
1707  std::vector<IntVar*> variables);
1708  // Read access to currently registered search monitors.
1709  const std::vector<SearchMonitor*>& GetSearchMonitors() const {
1710  return monitors_;
1711  }
1712 #endif
1726  DecisionBuilder* MakeSelfDependentDimensionFinalizer(
1727  const RoutingDimension* dimension);
1728 
1729  private:
1731  enum RoutingLocalSearchOperator {
1732  RELOCATE = 0,
1733  RELOCATE_PAIR,
1734  LIGHT_RELOCATE_PAIR,
1735  RELOCATE_NEIGHBORS,
1736  EXCHANGE,
1737  EXCHANGE_PAIR,
1738  CROSS,
1739  CROSS_EXCHANGE,
1740  TWO_OPT,
1741  OR_OPT,
1742  GLOBAL_CHEAPEST_INSERTION_CLOSE_NODES_LNS,
1743  LOCAL_CHEAPEST_INSERTION_CLOSE_NODES_LNS,
1744  GLOBAL_CHEAPEST_INSERTION_PATH_LNS,
1745  LOCAL_CHEAPEST_INSERTION_PATH_LNS,
1746  RELOCATE_PATH_GLOBAL_CHEAPEST_INSERTION_INSERT_UNPERFORMED,
1747  GLOBAL_CHEAPEST_INSERTION_EXPENSIVE_CHAIN_LNS,
1748  LOCAL_CHEAPEST_INSERTION_EXPENSIVE_CHAIN_LNS,
1749  RELOCATE_EXPENSIVE_CHAIN,
1750  LIN_KERNIGHAN,
1751  TSP_OPT,
1752  MAKE_ACTIVE,
1753  RELOCATE_AND_MAKE_ACTIVE,
1754  MAKE_ACTIVE_AND_RELOCATE,
1755  MAKE_INACTIVE,
1756  MAKE_CHAIN_INACTIVE,
1757  SWAP_ACTIVE,
1758  EXTENDED_SWAP_ACTIVE,
1759  SHORTEST_PATH_SWAP_ACTIVE,
1760  NODE_PAIR_SWAP,
1761  PATH_LNS,
1762  FULL_PATH_LNS,
1763  TSP_LNS,
1764  INACTIVE_LNS,
1765  EXCHANGE_RELOCATE_PAIR,
1766  RELOCATE_SUBTRIP,
1767  EXCHANGE_SUBTRIP,
1768  LOCAL_SEARCH_OPERATOR_COUNTER
1769  };
1770 
1774  template <typename T>
1775  struct ValuedNodes {
1776  std::vector<int64_t> indices;
1777  T value;
1778  };
1779  struct DisjunctionValues {
1780  int64_t penalty;
1781  int64_t max_cardinality;
1782  };
1783  typedef ValuedNodes<DisjunctionValues> Disjunction;
1784 
1787  struct CostCacheElement {
1793  int index;
1794  CostClassIndex cost_class_index;
1795  int64_t cost;
1796  };
1797 
1800  template <class DimensionCumulOptimizer>
1801  struct DimensionCumulOptimizers {
1802  std::unique_ptr<DimensionCumulOptimizer> lp_optimizer;
1803  std::unique_ptr<DimensionCumulOptimizer> mp_optimizer;
1804  };
1805 
1807  void Initialize();
1808  void AddNoCycleConstraintInternal();
1809  bool AddDimensionWithCapacityInternal(
1810  const std::vector<int>& evaluator_indices, int64_t slack_max,
1811  std::vector<int64_t> vehicle_capacities, bool fix_start_cumul_to_zero,
1812  const std::string& name);
1813  bool AddDimensionDependentDimensionWithVehicleCapacityInternal(
1814  const std::vector<int>& pure_transits,
1815  const std::vector<int>& dependent_transits,
1816  const RoutingDimension* base_dimension, int64_t slack_max,
1817  std::vector<int64_t> vehicle_capacities, bool fix_start_cumul_to_zero,
1818  const std::string& name);
1819  bool InitializeDimensionInternal(
1820  const std::vector<int>& evaluator_indices,
1821  const std::vector<int>& state_dependent_evaluator_indices,
1822  int64_t slack_max, bool fix_start_cumul_to_zero,
1823  RoutingDimension* dimension);
1824  DimensionIndex GetDimensionIndex(const std::string& dimension_name) const;
1825 
1853  void StoreDimensionCumulOptimizers(const RoutingSearchParameters& parameters);
1854 
1855  void ComputeCostClasses(const RoutingSearchParameters& parameters);
1856  void ComputeVehicleClasses();
1864  void ComputeVehicleTypes();
1874  void FinalizeVisitTypes();
1875  // Called by FinalizeVisitTypes() to setup topologically_sorted_visit_types_.
1876  void TopologicallySortVisitTypes();
1877  int64_t GetArcCostForClassInternal(int64_t from_index, int64_t to_index,
1878  CostClassIndex cost_class_index) const;
1879  void AppendHomogeneousArcCosts(const RoutingSearchParameters& parameters,
1880  int node_index,
1881  std::vector<IntVar*>* cost_elements);
1882  void AppendArcCosts(const RoutingSearchParameters& parameters, int node_index,
1883  std::vector<IntVar*>* cost_elements);
1884  Assignment* DoRestoreAssignment();
1885  static const CostClassIndex kCostClassIndexOfZeroCost;
1886  int64_t SafeGetCostClassInt64OfVehicle(int64_t vehicle) const {
1887  DCHECK_LT(0, vehicles_);
1888  return (vehicle >= 0 ? GetCostClassIndexOfVehicle(vehicle)
1889  : kCostClassIndexOfZeroCost)
1890  .value();
1891  }
1892  int64_t GetDimensionTransitCostSum(int64_t i, int64_t j,
1893  const CostClass& cost_class) const;
1895  IntVar* CreateDisjunction(DisjunctionIndex disjunction);
1897  void AddPickupAndDeliverySetsInternal(const std::vector<int64_t>& pickups,
1898  const std::vector<int64_t>& deliveries);
1901  IntVar* CreateSameVehicleCost(int vehicle_index);
1904  int FindNextActive(int index, const std::vector<int64_t>& indices) const;
1905 
1908  bool RouteCanBeUsedByVehicle(const Assignment& assignment, int start_index,
1909  int vehicle) const;
1917  bool ReplaceUnusedVehicle(int unused_vehicle, int active_vehicle,
1918  Assignment* compact_assignment) const;
1919 
1920  void QuietCloseModel();
1921  void QuietCloseModelWithParameters(
1922  const RoutingSearchParameters& parameters) {
1923  if (!closed_) {
1924  CloseModelWithParameters(parameters);
1925  }
1926  }
1927 
1929  bool SolveMatchingModel(Assignment* assignment,
1930  const RoutingSearchParameters& parameters);
1931 #ifndef SWIG
1933  bool AppendAssignmentIfFeasible(
1934  const Assignment& assignment,
1935  std::vector<std::unique_ptr<Assignment>>* assignments);
1936 #endif
1938  void LogSolution(const RoutingSearchParameters& parameters,
1939  const std::string& description, int64_t solution_cost,
1940  int64_t start_time_ms);
1943  Assignment* CompactAssignmentInternal(const Assignment& assignment,
1944  bool check_compact_assignment) const;
1949  std::string FindErrorInSearchParametersForModel(
1950  const RoutingSearchParameters& search_parameters) const;
1952  void SetupSearch(const RoutingSearchParameters& search_parameters);
1954  // TODO(user): Document each auxiliary method.
1955  Assignment* GetOrCreateAssignment();
1956  Assignment* GetOrCreateTmpAssignment();
1957  RegularLimit* GetOrCreateLimit();
1958  RegularLimit* GetOrCreateLocalSearchLimit();
1959  RegularLimit* GetOrCreateLargeNeighborhoodSearchLimit();
1960  RegularLimit* GetOrCreateFirstSolutionLargeNeighborhoodSearchLimit();
1961  LocalSearchOperator* CreateInsertionOperator();
1962  LocalSearchOperator* CreateMakeInactiveOperator();
1963  template <class T>
1964  LocalSearchOperator* CreateCPOperator(const T& operator_factory) {
1965  return operator_factory(solver_.get(), nexts_,
1966  CostsAreHomogeneousAcrossVehicles()
1967  ? std::vector<IntVar*>()
1968  : vehicle_vars_,
1969  vehicle_start_class_callback_);
1970  }
1971  template <class T>
1972  LocalSearchOperator* CreateCPOperator() {
1973  return CreateCPOperator(MakeLocalSearchOperator<T>);
1974  }
1975  template <class T, class Arg>
1976  LocalSearchOperator* CreateOperator(const Arg& arg) {
1977  return solver_->RevAlloc(new T(nexts_,
1978  CostsAreHomogeneousAcrossVehicles()
1979  ? std::vector<IntVar*>()
1980  : vehicle_vars_,
1981  vehicle_start_class_callback_, arg));
1982  }
1983  template <class T, class Arg1, class MoveableArg2>
1984  LocalSearchOperator* CreateOperator(const Arg1& arg1, MoveableArg2 arg2) {
1985  return solver_->RevAlloc(
1986  new T(nexts_,
1987  CostsAreHomogeneousAcrossVehicles() ? std::vector<IntVar*>()
1988  : vehicle_vars_,
1989  vehicle_start_class_callback_, arg1, std::move(arg2)));
1990  }
1991  template <class T>
1992  LocalSearchOperator* CreatePairOperator() {
1993  return CreateOperator<T>(pickup_delivery_pairs_);
1994  }
1995  void CreateNeighborhoodOperators(const RoutingSearchParameters& parameters);
1996  LocalSearchOperator* ConcatenateOperators(
1997  const RoutingSearchParameters& search_parameters,
1998  const std::vector<LocalSearchOperator*>& operators) const;
1999  LocalSearchOperator* GetNeighborhoodOperators(
2000  const RoutingSearchParameters& search_parameters) const;
2001 
2002  struct FilterOptions {
2003  bool filter_objective;
2004  bool filter_with_cp_solver;
2005 
2006  bool operator==(const FilterOptions& other) const {
2007  return other.filter_objective == filter_objective &&
2008  other.filter_with_cp_solver == filter_with_cp_solver;
2009  }
2010  template <typename H>
2011  friend H AbslHashValue(H h, const FilterOptions& options) {
2012  return H::combine(std::move(h), options.filter_objective,
2013  options.filter_with_cp_solver);
2014  }
2015  };
2016  std::vector<LocalSearchFilterManager::FilterEvent> CreateLocalSearchFilters(
2017  const RoutingSearchParameters& parameters, const FilterOptions& options);
2018  LocalSearchFilterManager* GetOrCreateLocalSearchFilterManager(
2019  const RoutingSearchParameters& parameters, const FilterOptions& options);
2020  DecisionBuilder* CreateSolutionFinalizer(
2021  const RoutingSearchParameters& parameters, SearchLimit* lns_limit);
2022  DecisionBuilder* CreateFinalizerForMinimizedAndMaximizedVariables();
2023  void CreateFirstSolutionDecisionBuilders(
2024  const RoutingSearchParameters& search_parameters);
2025  DecisionBuilder* GetFirstSolutionDecisionBuilder(
2026  const RoutingSearchParameters& search_parameters) const;
2027  IntVarFilteredDecisionBuilder* GetFilteredFirstSolutionDecisionBuilderOrNull(
2028  const RoutingSearchParameters& parameters) const;
2029 #ifndef SWIG
2030  template <typename Heuristic, typename... Args>
2031  IntVarFilteredDecisionBuilder* CreateIntVarFilteredDecisionBuilder(
2032  const Args&... args);
2033 #endif
2034  LocalSearchPhaseParameters* CreateLocalSearchParameters(
2035  const RoutingSearchParameters& search_parameters);
2036  DecisionBuilder* CreateLocalSearchDecisionBuilder(
2037  const RoutingSearchParameters& search_parameters);
2038  void SetupDecisionBuilders(const RoutingSearchParameters& search_parameters);
2039  void SetupMetaheuristics(const RoutingSearchParameters& search_parameters);
2040  void SetupAssignmentCollector(
2041  const RoutingSearchParameters& search_parameters);
2042  void SetupTrace(const RoutingSearchParameters& search_parameters);
2043  void SetupImprovementLimit(const RoutingSearchParameters& search_parameters);
2044  void SetupSearchMonitors(const RoutingSearchParameters& search_parameters);
2045  bool UsesLightPropagation(
2046  const RoutingSearchParameters& search_parameters) const;
2047  GetTabuVarsCallback tabu_var_callback_;
2048 
2049  // Detects implicit pickup delivery pairs. These pairs are
2050  // non-pickup/delivery pairs for which there exists a unary dimension such
2051  // that the demand d of the implicit pickup is positive and the demand of the
2052  // implicit delivery is equal to -d.
2053  void DetectImplicitPickupAndDeliveries();
2054 
2055  int GetVehicleStartClass(int64_t start) const;
2056 
2057  void InitSameVehicleGroups(int number_of_groups) {
2058  same_vehicle_group_.assign(Size(), 0);
2059  same_vehicle_groups_.assign(number_of_groups, {});
2060  }
2061  void SetSameVehicleGroup(int index, int group) {
2062  same_vehicle_group_[index] = group;
2063  same_vehicle_groups_[group].push_back(index);
2064  }
2065 
2068  int GetGlobalCumulOptimizerIndex(const RoutingDimension& dimension) const;
2069  int GetLocalCumulOptimizerIndex(const RoutingDimension& dimension) const;
2070 
2072  std::unique_ptr<Solver> solver_;
2073  int nodes_;
2074  int vehicles_;
2075  int max_active_vehicles_;
2076  Constraint* no_cycle_constraint_ = nullptr;
2078  std::vector<IntVar*> nexts_;
2079  std::vector<IntVar*> vehicle_vars_;
2080  std::vector<IntVar*> active_;
2086  // clang-format off
2087  std::vector<std::vector<IntVar*> > resource_vars_;
2088  // clang-format on
2089  // The following vectors are indexed by vehicle index.
2090  std::vector<IntVar*> vehicle_active_;
2091  std::vector<IntVar*> vehicle_route_considered_;
2096  std::vector<IntVar*> is_bound_to_end_;
2097  mutable RevSwitch is_bound_to_end_ct_added_;
2099  absl::flat_hash_map<std::string, DimensionIndex> dimension_name_to_index_;
2105  // clang-format off
2106  std::vector<std::unique_ptr<ResourceGroup> > resource_groups_;
2109  dimension_resource_group_indices_;
2110 
2114  std::vector<DimensionCumulOptimizers<GlobalDimensionCumulOptimizer> >
2115  global_dimension_optimizers_;
2116  absl::StrongVector<DimensionIndex, int> global_optimizer_index_;
2117  std::vector<DimensionCumulOptimizers<LocalDimensionCumulOptimizer> >
2118  local_dimension_optimizers_;
2119  absl::StrongVector<DimensionIndex, int> local_optimizer_index_;
2120  // clang-format on
2121  std::string primary_constrained_dimension_;
2123  IntVar* cost_ = nullptr;
2124  std::vector<int> vehicle_to_transit_cost_;
2125  std::vector<int64_t> fixed_cost_of_vehicle_;
2126  std::vector<CostClassIndex> cost_class_index_of_vehicle_;
2127  bool has_vehicle_with_zero_cost_class_;
2128  std::vector<int64_t> linear_cost_factor_of_vehicle_;
2129  std::vector<int64_t> quadratic_cost_factor_of_vehicle_;
2130  bool vehicle_amortized_cost_factors_set_;
2142  std::vector<bool> vehicle_used_when_empty_;
2143 #ifndef SWIG
2145 #endif // SWIG
2146  bool costs_are_homogeneous_across_vehicles_;
2147  bool cache_callbacks_;
2148  mutable std::vector<CostCacheElement> cost_cache_;
2149  std::vector<VehicleClassIndex> vehicle_class_index_of_vehicle_;
2150 #ifndef SWIG
2152 #endif // SWIG
2153  VehicleTypeContainer vehicle_type_container_;
2154  std::function<int(int64_t)> vehicle_start_class_callback_;
2157  // clang-format off
2158  std::vector<std::vector<DisjunctionIndex> > index_to_disjunctions_;
2160  std::vector<ValuedNodes<int64_t> > same_vehicle_costs_;
2162 #ifndef SWIG
2163  std::vector<absl::flat_hash_set<int>> allowed_vehicles_;
2164 #endif // SWIG
2166  IndexPairs pickup_delivery_pairs_;
2167  IndexPairs implicit_pickup_delivery_pairs_without_alternatives_;
2168  std::vector<std::pair<DisjunctionIndex, DisjunctionIndex> >
2169  pickup_delivery_disjunctions_;
2170  // If node_index is a pickup, index_to_pickup_index_pairs_[node_index] is the
2171  // vector of pairs {pair_index, pickup_index} such that
2172  // (pickup_delivery_pairs_[pair_index].first)[pickup_index] == node_index
2173  std::vector<std::vector<std::pair<int, int> > > index_to_pickup_index_pairs_;
2174  // Same as above for deliveries.
2175  std::vector<std::vector<std::pair<int, int> > >
2176  index_to_delivery_index_pairs_;
2177  // clang-format on
2178  std::vector<PickupAndDeliveryPolicy> vehicle_pickup_delivery_policy_;
2179  // Same vehicle group to which a node belongs.
2180  std::vector<int> same_vehicle_group_;
2181  // Same vehicle node groups.
2182  std::vector<std::vector<int>> same_vehicle_groups_;
2183  // Node visit types
2184  // Variable index to visit type index.
2185  std::vector<int> index_to_visit_type_;
2186  // Variable index to VisitTypePolicy.
2187  std::vector<VisitTypePolicy> index_to_type_policy_;
2188  // clang-format off
2189  std::vector<std::vector<int> > single_nodes_of_type_;
2190  std::vector<std::vector<int> > pair_indices_of_type_;
2191 
2192  std::vector<absl::flat_hash_set<int> >
2193  hard_incompatible_types_per_type_index_;
2194  bool has_hard_type_incompatibilities_;
2195  std::vector<absl::flat_hash_set<int> >
2196  temporal_incompatible_types_per_type_index_;
2197  bool has_temporal_type_incompatibilities_;
2198 
2199  std::vector<std::vector<absl::flat_hash_set<int> > >
2200  same_vehicle_required_type_alternatives_per_type_index_;
2201  bool has_same_vehicle_type_requirements_;
2202  std::vector<std::vector<absl::flat_hash_set<int> > >
2203  required_type_alternatives_when_adding_type_index_;
2204  std::vector<std::vector<absl::flat_hash_set<int> > >
2205  required_type_alternatives_when_removing_type_index_;
2206  bool has_temporal_type_requirements_;
2207  absl::flat_hash_map</*type*/int, absl::flat_hash_set<VisitTypePolicy> >
2208  trivially_infeasible_visit_types_to_policies_;
2209 
2210  // Visit types sorted topologically based on required-->dependent requirement
2211  // arcs between the types (if the requirement/dependency graph is acyclic).
2212  // Visit types of the same topological level are sorted in each sub-vector
2213  // by decreasing requirement "tightness", computed as the pair of the two
2214  // following criteria:
2215  //
2216  // 1) How highly *dependent* this type is, determined by
2217  // (total number of required alternative sets for that type)
2218  // / (average number of types in the required alternative sets)
2219  // 2) How highly *required* this type t is, computed as
2220  // SUM_{S required set containing t} ( 1 / |S| ),
2221  // i.e. the sum of reverse number of elements of all required sets
2222  // containing the type t.
2223  //
2224  // The higher these two numbers, the tighter the type is wrt requirements.
2225  std::vector<std::vector<int> > topologically_sorted_visit_types_;
2226  // clang-format on
2227  int num_visit_types_;
2228  // Two indices are equivalent if they correspond to the same node (as given
2229  // to the constructors taking a RoutingIndexManager).
2230  std::vector<int> index_to_equivalence_class_;
2231  const PathsMetadata paths_metadata_;
2232  // TODO(user): b/62478706 Once the port is done, this shouldn't be needed
2233  // anymore.
2234  RoutingIndexManager manager_;
2235  int start_end_count_;
2236  // Model status
2237  bool closed_ = false;
2238  Status status_ = ROUTING_NOT_SOLVED;
2239  bool enable_deep_serialization_ = true;
2240 
2241  // Search data
2242  std::vector<DecisionBuilder*> first_solution_decision_builders_;
2243  std::vector<IntVarFilteredDecisionBuilder*>
2244  first_solution_filtered_decision_builders_;
2245  Solver::IndexEvaluator2 first_solution_evaluator_;
2246  FirstSolutionStrategy::Value automatic_first_solution_strategy_ =
2247  FirstSolutionStrategy::UNSET;
2248  std::vector<LocalSearchOperator*> local_search_operators_;
2249  std::vector<SearchMonitor*> monitors_;
2250  bool local_optimum_reached_ = false;
2251  // Best lower bound found during the search.
2252  int64_t objective_lower_bound_ = kint64min;
2253  SolutionCollector* collect_assignments_ = nullptr;
2254  SolutionCollector* collect_one_assignment_ = nullptr;
2255  SolutionCollector* optimized_dimensions_assignment_collector_ = nullptr;
2256  DecisionBuilder* solve_db_ = nullptr;
2257  DecisionBuilder* improve_db_ = nullptr;
2258  DecisionBuilder* restore_assignment_ = nullptr;
2259  DecisionBuilder* restore_tmp_assignment_ = nullptr;
2260  Assignment* assignment_ = nullptr;
2261  Assignment* preassignment_ = nullptr;
2262  Assignment* tmp_assignment_ = nullptr;
2263  std::vector<IntVar*> extra_vars_;
2264  std::vector<IntervalVar*> extra_intervals_;
2265  std::vector<LocalSearchOperator*> extra_operators_;
2266  absl::flat_hash_map<FilterOptions, LocalSearchFilterManager*>
2267  local_search_filter_managers_;
2268  std::vector<LocalSearchFilterManager::FilterEvent> extra_filters_;
2269  absl::flat_hash_map<int, std::unique_ptr<NodeNeighborsByCostClass>>
2270  node_neighbors_by_cost_class_per_size_;
2271 #ifndef SWIG
2272  struct VarTarget {
2273  VarTarget(IntVar* v, int64_t t) : var(v), target(t) {}
2274 
2275  IntVar* var;
2276  int64_t target;
2277  };
2278  std::vector<std::pair<VarTarget, int64_t>>
2279  weighted_finalizer_variable_targets_;
2280  std::vector<VarTarget> finalizer_variable_targets_;
2281  absl::flat_hash_map<IntVar*, int> weighted_finalizer_variable_index_;
2282  absl::flat_hash_set<IntVar*> finalizer_variable_target_set_;
2283  std::unique_ptr<SweepArranger> sweep_arranger_;
2284 #endif
2285 
2286  RegularLimit* limit_ = nullptr;
2287  RegularLimit* ls_limit_ = nullptr;
2288  RegularLimit* lns_limit_ = nullptr;
2289  RegularLimit* first_solution_lns_limit_ = nullptr;
2290  absl::Duration time_buffer_;
2291 
2292  typedef std::pair<int64_t, int64_t> CacheKey;
2293  typedef absl::flat_hash_map<CacheKey, int64_t> TransitCallbackCache;
2294  typedef absl::flat_hash_map<CacheKey, StateDependentTransit>
2295  StateDependentTransitCallbackCache;
2296 
2297  std::vector<TransitCallback1> unary_transit_evaluators_;
2298  std::vector<TransitCallback2> transit_evaluators_;
2299  // The following vector stores a boolean per transit_evaluator_, indicating
2300  // whether the transits are all positive.
2301  // is_transit_evaluator_positive_ will be set to true only when registering a
2302  // callback via RegisterPositiveTransitCallback(), and to false otherwise.
2303  // The actual positivity of the transit values will only be checked in debug
2304  // mode, when calling RegisterPositiveTransitCallback().
2305  // Therefore, RegisterPositiveTransitCallback() should only be called when the
2306  // transits are known to be positive, as the positivity of a callback will
2307  // allow some improvements in the solver, but will entail in errors if the
2308  // transits are falsely assumed positive.
2309  std::vector<bool> is_transit_evaluator_positive_;
2310  std::vector<VariableIndexEvaluator2> state_dependent_transit_evaluators_;
2311  std::vector<std::unique_ptr<StateDependentTransitCallbackCache>>
2312  state_dependent_transit_evaluators_cache_;
2313 
2314  friend class RoutingDimension;
2317 
2319 };
2320 
2323  public:
2325  static const char kLightElement[];
2326  static const char kLightElement2[];
2327  static const char kRemoveValues[];
2328 };
2329 
2330 #if !defined(SWIG)
2334  public:
2340  struct Tasks {
2341  int num_chain_tasks = 0;
2342  std::vector<int64_t> start_min;
2343  std::vector<int64_t> start_max;
2344  std::vector<int64_t> duration_min;
2345  std::vector<int64_t> duration_max;
2346  std::vector<int64_t> end_min;
2347  std::vector<int64_t> end_max;
2348  std::vector<bool> is_preemptible;
2349  std::vector<const SortedDisjointIntervalList*> forbidden_intervals;
2350  std::vector<std::pair<int64_t, int64_t>> distance_duration;
2351  int64_t span_min = 0;
2352  int64_t span_max = kint64max;
2353 
2354  void Clear() {
2355  start_min.clear();
2356  start_max.clear();
2357  duration_min.clear();
2358  duration_max.clear();
2359  end_min.clear();
2360  end_max.clear();
2361  is_preemptible.clear();
2362  forbidden_intervals.clear();
2363  distance_duration.clear();
2364  span_min = 0;
2365  span_max = kint64max;
2366  num_chain_tasks = 0;
2367  }
2368  };
2369 
2372  bool Propagate(Tasks* tasks);
2373 
2375  bool Precedences(Tasks* tasks);
2378  bool MirrorTasks(Tasks* tasks);
2380  bool EdgeFinding(Tasks* tasks);
2383  bool DetectablePrecedencesWithChain(Tasks* tasks);
2385  bool ForbiddenIntervals(Tasks* tasks);
2387  bool DistanceDuration(Tasks* tasks);
2390  bool ChainSpanMin(Tasks* tasks);
2395  bool ChainSpanMinDynamic(Tasks* tasks);
2396 
2397  private:
2400  sat::ThetaLambdaTree<int64_t> theta_lambda_tree_;
2402  std::vector<int> tasks_by_start_min_;
2403  std::vector<int> tasks_by_end_max_;
2404  std::vector<int> event_of_task_;
2405  std::vector<int> nonchain_tasks_by_start_max_;
2407  std::vector<int64_t> total_duration_before_;
2408 };
2409 
2411  std::vector<int64_t> min_travels;
2412  std::vector<int64_t> max_travels;
2413  std::vector<int64_t> pre_travels;
2414  std::vector<int64_t> post_travels;
2415 };
2416 
2417 void AppendTasksFromPath(const std::vector<int64_t>& path,
2418  const TravelBounds& travel_bounds,
2419  const RoutingDimension& dimension,
2421 void AppendTasksFromIntervals(const std::vector<IntervalVar*>& intervals,
2423 void FillPathEvaluation(const std::vector<int64_t>& path,
2424  const RoutingModel::TransitCallback2& evaluator,
2425  std::vector<int64_t>* values);
2426 void FillTravelBoundsOfVehicle(int vehicle, const std::vector<int64_t>& path,
2427  const RoutingDimension& dimension,
2428  TravelBounds* travel_bounds);
2429 #endif // !defined(SWIG)
2430 
2442  public:
2443  explicit GlobalVehicleBreaksConstraint(const RoutingDimension* dimension);
2444  std::string DebugString() const override {
2445  return "GlobalVehicleBreaksConstraint";
2446  }
2447 
2448  void Post() override;
2449  void InitialPropagate() override;
2450 
2451  private:
2452  void PropagateNode(int node);
2453  void PropagateVehicle(int vehicle);
2454 
2455  const RoutingModel* model_;
2456  const RoutingDimension* const dimension_;
2457  std::vector<Demon*> vehicle_demons_;
2458  std::vector<int64_t> path_;
2459 
2464  void FillPartialPathOfVehicle(int vehicle);
2465  void FillPathTravels(const std::vector<int64_t>& path);
2466 
2477  class TaskTranslator {
2478  public:
2479  TaskTranslator(IntVar* start, int64_t before_start, int64_t after_start)
2480  : start_(start),
2481  before_start_(before_start),
2482  after_start_(after_start) {}
2483  explicit TaskTranslator(IntervalVar* interval) : interval_(interval) {}
2484  TaskTranslator() = default;
2485 
2486  void SetStartMin(int64_t value) {
2487  if (start_ != nullptr) {
2488  start_->SetMin(CapAdd(before_start_, value));
2489  } else if (interval_ != nullptr) {
2490  interval_->SetStartMin(value);
2491  }
2492  }
2493  void SetStartMax(int64_t value) {
2494  if (start_ != nullptr) {
2495  start_->SetMax(CapAdd(before_start_, value));
2496  } else if (interval_ != nullptr) {
2497  interval_->SetStartMax(value);
2498  }
2499  }
2500  void SetDurationMin(int64_t value) {
2501  if (interval_ != nullptr) {
2502  interval_->SetDurationMin(value);
2503  }
2504  }
2505  void SetEndMin(int64_t value) {
2506  if (start_ != nullptr) {
2507  start_->SetMin(CapSub(value, after_start_));
2508  } else if (interval_ != nullptr) {
2509  interval_->SetEndMin(value);
2510  }
2511  }
2512  void SetEndMax(int64_t value) {
2513  if (start_ != nullptr) {
2514  start_->SetMax(CapSub(value, after_start_));
2515  } else if (interval_ != nullptr) {
2516  interval_->SetEndMax(value);
2517  }
2518  }
2519 
2520  private:
2521  IntVar* start_ = nullptr;
2522  int64_t before_start_;
2523  int64_t after_start_;
2524  IntervalVar* interval_ = nullptr;
2525  };
2526 
2528  std::vector<TaskTranslator> task_translators_;
2529 
2531  DisjunctivePropagator disjunctive_propagator_;
2532  DisjunctivePropagator::Tasks tasks_;
2533 
2535  TravelBounds travel_bounds_;
2536 };
2537 
2539  public:
2540  explicit TypeRegulationsChecker(const RoutingModel& model);
2541  virtual ~TypeRegulationsChecker() = default;
2542 
2543  bool CheckVehicle(int vehicle,
2544  const std::function<int64_t(int64_t)>& next_accessor);
2545 
2546  protected:
2547 #ifndef SWIG
2549 #endif // SWIG
2550 
2555  int num_type_added_to_vehicle = 0;
2561  int num_type_removed_from_vehicle = 0;
2566  int position_of_last_type_on_vehicle_up_to_visit = -1;
2567  };
2568 
2573  bool TypeOccursOnRoute(int type) const;
2580  bool TypeCurrentlyOnRoute(int type, int pos) const;
2581 
2582  void InitializeCheck(int vehicle,
2583  const std::function<int64_t(int64_t)>& next_accessor);
2584  virtual void OnInitializeCheck() {}
2585  virtual bool HasRegulationsToCheck() const = 0;
2586  virtual bool CheckTypeRegulations(int type, VisitTypePolicy policy,
2587  int pos) = 0;
2588  virtual bool FinalizeCheck() const { return true; }
2589 
2591 
2592  private:
2593  std::vector<TypePolicyOccurrence> occurrences_of_type_;
2594  std::vector<int64_t> current_route_visits_;
2595 };
2596 
2599  public:
2601  bool check_hard_incompatibilities);
2602  ~TypeIncompatibilityChecker() override = default;
2603 
2604  private:
2605  bool HasRegulationsToCheck() const override;
2606  bool CheckTypeRegulations(int type, VisitTypePolicy policy, int pos) override;
2610  bool check_hard_incompatibilities_;
2611 };
2612 
2615  public:
2618  ~TypeRequirementChecker() override = default;
2619 
2620  private:
2621  bool HasRegulationsToCheck() const override;
2622  void OnInitializeCheck() override {
2623  types_with_same_vehicle_requirements_on_route_.clear();
2624  }
2625  // clang-format off
2628  bool CheckRequiredTypesCurrentlyOnRoute(
2629  const std::vector<absl::flat_hash_set<int> >& required_type_alternatives,
2630  int pos);
2631  // clang-format on
2632  bool CheckTypeRegulations(int type, VisitTypePolicy policy, int pos) override;
2633  bool FinalizeCheck() const override;
2634 
2635  absl::flat_hash_set<int> types_with_same_vehicle_requirements_on_route_;
2636 };
2637 
2679  public:
2680  explicit TypeRegulationsConstraint(const RoutingModel& model);
2681 
2682  void Post() override;
2683  void InitialPropagate() override;
2684 
2685  private:
2686  void PropagateNodeRegulations(int node);
2687  void CheckRegulationsOnVehicle(int vehicle);
2688 
2689  const RoutingModel& model_;
2690  TypeIncompatibilityChecker incompatibility_checker_;
2691  TypeRequirementChecker requirement_checker_;
2692  std::vector<Demon*> vehicle_demons_;
2693 };
2694 
2707 struct BoundCost {
2708  int64_t bound;
2709  int64_t cost;
2710  BoundCost() : bound(0), cost(0) {}
2711  BoundCost(int64_t bound, int64_t cost) : bound(bound), cost(cost) {}
2712 };
2713 
2715  public:
2716  SimpleBoundCosts(int num_bounds, BoundCost default_bound_cost)
2717  : bound_costs_(num_bounds, default_bound_cost) {}
2718 #ifndef SWIG
2719  BoundCost& bound_cost(int element) { return bound_costs_[element]; }
2720 #endif
2721  BoundCost bound_cost(int element) const { return bound_costs_[element]; }
2722  int Size() { return bound_costs_.size(); }
2725 
2726  private:
2727  std::vector<BoundCost> bound_costs_;
2728 };
2729 
2747 // TODO(user): Break constraints need to know the service time of nodes
2751  public:
2752  ~RoutingDimension();
2754  RoutingModel* model() const { return model_; }
2758  int64_t GetTransitValue(int64_t from_index, int64_t to_index,
2759  int64_t vehicle) const;
2762  int64_t GetTransitValueFromClass(int64_t from_index, int64_t to_index,
2763  int64_t vehicle_class) const {
2764  return model_->TransitCallback(class_evaluators_[vehicle_class])(from_index,
2765  to_index);
2766  }
2769  IntVar* CumulVar(int64_t index) const { return cumuls_[index]; }
2770  IntVar* TransitVar(int64_t index) const { return transits_[index]; }
2771  IntVar* FixedTransitVar(int64_t index) const {
2772  return fixed_transits_[index];
2773  }
2774  IntVar* SlackVar(int64_t index) const { return slacks_[index]; }
2775 
2776 #if !defined(SWIGPYTHON)
2779  const std::vector<IntVar*>& cumuls() const { return cumuls_; }
2780  const std::vector<IntVar*>& fixed_transits() const { return fixed_transits_; }
2781  const std::vector<IntVar*>& transits() const { return transits_; }
2782  const std::vector<IntVar*>& slacks() const { return slacks_; }
2783 #if !defined(SWIGCSHARP) && !defined(SWIGJAVA)
2785  const std::vector<SortedDisjointIntervalList>& forbidden_intervals() const {
2786  return forbidden_intervals_;
2787  }
2789  SortedDisjointIntervalList GetAllowedIntervalsInRange(
2790  int64_t index, int64_t min_value, int64_t max_value) const;
2794  int64_t min_value) const {
2795  DCHECK_LT(index, forbidden_intervals_.size());
2796  const SortedDisjointIntervalList& forbidden_intervals =
2797  forbidden_intervals_[index];
2798  const auto first_forbidden_interval_it =
2799  forbidden_intervals.FirstIntervalGreaterOrEqual(min_value);
2800  if (first_forbidden_interval_it != forbidden_intervals.end() &&
2801  min_value >= first_forbidden_interval_it->start) {
2803  return CapAdd(first_forbidden_interval_it->end, 1);
2804  }
2806  return min_value;
2807  }
2813  int64_t max_value) const {
2814  DCHECK_LT(index, forbidden_intervals_.size());
2815  const SortedDisjointIntervalList& forbidden_intervals =
2816  forbidden_intervals_[index];
2817  const auto last_forbidden_interval_it =
2818  forbidden_intervals.LastIntervalLessOrEqual(max_value);
2819  if (last_forbidden_interval_it != forbidden_intervals.end() &&
2820  max_value <= last_forbidden_interval_it->end) {
2822  return CapSub(last_forbidden_interval_it->start, 1);
2823  }
2825  return max_value;
2826  }
2828  const std::vector<int64_t>& vehicle_capacities() const {
2829  return vehicle_capacities_;
2830  }
2834  return model_->TransitCallback(
2835  class_evaluators_[vehicle_to_class_[vehicle]]);
2836  }
2837 
2841  RoutingVehicleClassIndex vehicle_class) const {
2842  const int vehicle = model_->GetVehicleOfClass(vehicle_class);
2843  DCHECK_NE(vehicle, -1);
2844  return transit_evaluator(vehicle);
2845  }
2846 
2851  int vehicle) const {
2852  return model_->UnaryTransitCallbackOrNull(
2853  class_evaluators_[vehicle_to_class_[vehicle]]);
2854  }
2856  int vehicle) const {
2857  return model_->TransitCallback(
2858  class_evaluators_[vehicle_to_class_[vehicle]]);
2859  }
2862  bool AreVehicleTransitsPositive(int vehicle) const {
2863  return model()->is_transit_evaluator_positive_
2864  [class_evaluators_[vehicle_to_class_[vehicle]]];
2865  }
2866  int vehicle_to_class(int vehicle) const { return vehicle_to_class_[vehicle]; }
2867 #endif
2868 #endif
2872  void SetSpanUpperBoundForVehicle(int64_t upper_bound, int vehicle);
2879  void SetSpanCostCoefficientForVehicle(int64_t coefficient, int vehicle);
2880  void SetSpanCostCoefficientForAllVehicles(int64_t coefficient);
2887  void SetGlobalSpanCostCoefficient(int64_t coefficient);
2888 
2889 #ifndef SWIG
2894  void SetCumulVarPiecewiseLinearCost(int64_t index,
2895  const PiecewiseLinearFunction& cost);
2898  bool HasCumulVarPiecewiseLinearCost(int64_t index) const;
2901  const PiecewiseLinearFunction* GetCumulVarPiecewiseLinearCost(
2902  int64_t index) const;
2903 #endif
2904 
2913  void SetCumulVarSoftUpperBound(int64_t index, int64_t upper_bound,
2914  int64_t coefficient);
2917  bool HasCumulVarSoftUpperBound(int64_t index) const;
2921  int64_t GetCumulVarSoftUpperBound(int64_t index) const;
2925  int64_t GetCumulVarSoftUpperBoundCoefficient(int64_t index) const;
2926 
2936  void SetCumulVarSoftLowerBound(int64_t index, int64_t lower_bound,
2937  int64_t coefficient);
2940  bool HasCumulVarSoftLowerBound(int64_t index) const;
2944  int64_t GetCumulVarSoftLowerBound(int64_t index) const;
2948  int64_t GetCumulVarSoftLowerBoundCoefficient(int64_t index) const;
2964  // TODO(user): Remove if !defined when routing.i is repaired.
2965 #if !defined(SWIGPYTHON)
2966  void SetBreakIntervalsOfVehicle(std::vector<IntervalVar*> breaks, int vehicle,
2967  int pre_travel_evaluator,
2968  int post_travel_evaluator);
2969 #endif // !defined(SWIGPYTHON)
2970 
2972  void SetBreakIntervalsOfVehicle(std::vector<IntervalVar*> breaks, int vehicle,
2973  std::vector<int64_t> node_visit_transits);
2974 
2979  void SetBreakDistanceDurationOfVehicle(int64_t distance, int64_t duration,
2980  int vehicle);
2983  void InitializeBreaks();
2985  bool HasBreakConstraints() const;
2986 #if !defined(SWIGPYTHON)
2989  void SetBreakIntervalsOfVehicle(
2990  std::vector<IntervalVar*> breaks, int vehicle,
2991  std::vector<int64_t> node_visit_transits,
2992  std::function<int64_t(int64_t, int64_t)> delays);
2993 
2995  const std::vector<IntervalVar*>& GetBreakIntervalsOfVehicle(
2996  int vehicle) const;
2999  // clang-format off
3000  const std::vector<std::pair<int64_t, int64_t> >&
3001  GetBreakDistanceDurationOfVehicle(int vehicle) const;
3002  // clang-format on
3003 #endif
3004  int GetPreTravelEvaluatorOfVehicle(int vehicle) const;
3005  int GetPostTravelEvaluatorOfVehicle(int vehicle) const;
3006 
3008  const RoutingDimension* base_dimension() const { return base_dimension_; }
3016  int64_t ShortestTransitionSlack(int64_t node) const;
3017 
3019  const std::string& name() const { return name_; }
3020 
3022 #ifndef SWIG
3024  return path_precedence_graph_;
3025  }
3026 #endif // SWIG
3027 
3037  typedef std::function<int64_t(int, int)> PickupToDeliveryLimitFunction;
3038 
3039  void SetPickupToDeliveryLimitFunctionForPair(
3040  PickupToDeliveryLimitFunction limit_function, int pair_index);
3041 
3042  bool HasPickupToDeliveryLimits() const;
3043 #ifndef SWIG
3044  int64_t GetPickupToDeliveryLimitForPair(int pair_index, int pickup,
3045  int delivery) const;
3046 
3048  int64_t first_node;
3049  int64_t second_node;
3050  int64_t offset;
3051  };
3052 
3054  node_precedences_.push_back(precedence);
3055  }
3056  const std::vector<NodePrecedence>& GetNodePrecedences() const {
3057  return node_precedences_;
3058  }
3059 #endif // SWIG
3060 
3061  void AddNodePrecedence(int64_t first_node, int64_t second_node,
3062  int64_t offset) {
3063  AddNodePrecedence({first_node, second_node, offset});
3064  }
3065 
3066  int64_t GetSpanUpperBoundForVehicle(int vehicle) const {
3067  return vehicle_span_upper_bounds_[vehicle];
3068  }
3069 #ifndef SWIG
3070  const std::vector<int64_t>& vehicle_span_upper_bounds() const {
3071  return vehicle_span_upper_bounds_;
3072  }
3073 #endif // SWIG
3074  int64_t GetSpanCostCoefficientForVehicle(int vehicle) const {
3075  return vehicle_span_cost_coefficients_[vehicle];
3076  }
3077 #ifndef SWIG
3079  RoutingVehicleClassIndex vehicle_class) const {
3080  const int vehicle = model_->GetVehicleOfClass(vehicle_class);
3081  DCHECK_NE(vehicle, -1);
3082  return GetSpanCostCoefficientForVehicle(vehicle);
3083  }
3084 #endif // SWIG
3085 #ifndef SWIG
3086  const std::vector<int64_t>& vehicle_span_cost_coefficients() const {
3087  return vehicle_span_cost_coefficients_;
3088  }
3089 #endif // SWIG
3091  return global_span_cost_coefficient_;
3092  }
3093 
3094  int64_t GetGlobalOptimizerOffset() const {
3095  DCHECK_GE(global_optimizer_offset_, 0);
3096  return global_optimizer_offset_;
3097  }
3098  int64_t GetLocalOptimizerOffsetForVehicle(int vehicle) const {
3099  if (vehicle >= local_optimizer_offset_for_vehicle_.size()) {
3100  return 0;
3101  }
3102  DCHECK_GE(local_optimizer_offset_for_vehicle_[vehicle], 0);
3103  return local_optimizer_offset_for_vehicle_[vehicle];
3104  }
3105 
3108  void SetSoftSpanUpperBoundForVehicle(BoundCost bound_cost, int vehicle) {
3109  if (!HasSoftSpanUpperBounds()) {
3110  vehicle_soft_span_upper_bound_ = std::make_unique<SimpleBoundCosts>(
3111  model_->vehicles(), BoundCost{kint64max, 0});
3112  }
3113  vehicle_soft_span_upper_bound_->bound_cost(vehicle) = bound_cost;
3114  }
3115  bool HasSoftSpanUpperBounds() const {
3116  return vehicle_soft_span_upper_bound_ != nullptr;
3117  }
3119  DCHECK(HasSoftSpanUpperBounds());
3120  return vehicle_soft_span_upper_bound_->bound_cost(vehicle);
3121  }
3125  int vehicle) {
3126  if (!HasQuadraticCostSoftSpanUpperBounds()) {
3127  vehicle_quadratic_cost_soft_span_upper_bound_ =
3128  std::make_unique<SimpleBoundCosts>(model_->vehicles(),
3129  BoundCost{kint64max, 0});
3130  }
3131  vehicle_quadratic_cost_soft_span_upper_bound_->bound_cost(vehicle) =
3132  bound_cost;
3133  }
3135  return vehicle_quadratic_cost_soft_span_upper_bound_ != nullptr;
3136  }
3138  DCHECK(HasQuadraticCostSoftSpanUpperBounds());
3139  return vehicle_quadratic_cost_soft_span_upper_bound_->bound_cost(vehicle);
3140  }
3141 
3142  private:
3143  struct SoftBound {
3144  IntVar* var;
3145  int64_t bound;
3146  int64_t coefficient;
3147  };
3148 
3149  struct PiecewiseLinearCost {
3150  PiecewiseLinearCost() : var(nullptr), cost(nullptr) {}
3151  IntVar* var;
3152  std::unique_ptr<PiecewiseLinearFunction> cost;
3153  };
3154 
3155  class SelfBased {};
3156  RoutingDimension(RoutingModel* model, std::vector<int64_t> vehicle_capacities,
3157  const std::string& name,
3158  const RoutingDimension* base_dimension);
3159  RoutingDimension(RoutingModel* model, std::vector<int64_t> vehicle_capacities,
3160  const std::string& name, SelfBased);
3161  void Initialize(const std::vector<int>& transit_evaluators,
3162  const std::vector<int>& state_dependent_transit_evaluators,
3163  int64_t slack_max);
3164  void InitializeCumuls();
3165  void InitializeTransits(
3166  const std::vector<int>& transit_evaluators,
3167  const std::vector<int>& state_dependent_transit_evaluators,
3168  int64_t slack_max);
3169  void InitializeTransitVariables(int64_t slack_max);
3171  void SetupCumulVarSoftUpperBoundCosts(
3172  std::vector<IntVar*>* cost_elements) const;
3174  void SetupCumulVarSoftLowerBoundCosts(
3175  std::vector<IntVar*>* cost_elements) const;
3176  void SetupCumulVarPiecewiseLinearCosts(
3177  std::vector<IntVar*>* cost_elements) const;
3180  void SetupGlobalSpanCost(std::vector<IntVar*>* cost_elements) const;
3181  void SetupSlackAndDependentTransitCosts() const;
3183  void CloseModel(bool use_light_propagation);
3184 
3185  void SetOffsetForGlobalOptimizer(int64_t offset) {
3186  global_optimizer_offset_ = std::max(Zero(), offset);
3187  }
3189  void SetVehicleOffsetsForLocalOptimizer(std::vector<int64_t> offsets) {
3191  std::transform(offsets.begin(), offsets.end(), offsets.begin(),
3192  [](int64_t offset) { return std::max(Zero(), offset); });
3193  local_optimizer_offset_for_vehicle_ = std::move(offsets);
3194  }
3195 
3196  std::vector<IntVar*> cumuls_;
3197  std::vector<SortedDisjointIntervalList> forbidden_intervals_;
3198  std::vector<IntVar*> capacity_vars_;
3199  const std::vector<int64_t> vehicle_capacities_;
3200  std::vector<IntVar*> transits_;
3201  std::vector<IntVar*> fixed_transits_;
3204  std::vector<int> class_evaluators_;
3205  std::vector<int64_t> vehicle_to_class_;
3206 #ifndef SWIG
3207  ReverseArcListGraph<int, int> path_precedence_graph_;
3208 #endif
3209  // For every {first_node, second_node, offset} element in node_precedences_,
3210  // if both first_node and second_node are performed, then
3211  // cumuls_[second_node] must be greater than (or equal to)
3212  // cumuls_[first_node] + offset.
3213  std::vector<NodePrecedence> node_precedences_;
3214 
3215  // The transits of a dimension may depend on its cumuls or the cumuls of
3216  // another dimension. There can be no cycles, except for self loops, a
3217  // typical example for this is a time dimension.
3218  const RoutingDimension* const base_dimension_;
3219 
3220  // Values in state_dependent_class_evaluators_ correspond to the evaluators
3221  // in RoutingModel::state_dependent_transit_evaluators_ for each vehicle
3222  // class.
3223  std::vector<int> state_dependent_class_evaluators_;
3224  std::vector<int64_t> state_dependent_vehicle_to_class_;
3225 
3226  // For each pickup/delivery pair_index for which limits have been set,
3227  // pickup_to_delivery_limits_per_pair_index_[pair_index] contains the
3228  // PickupToDeliveryLimitFunction for the pickup and deliveries in this pair.
3229  std::vector<PickupToDeliveryLimitFunction>
3230  pickup_to_delivery_limits_per_pair_index_;
3231 
3232  // Used if some vehicle has breaks in this dimension, typically time.
3233  bool break_constraints_are_initialized_ = false;
3234  // clang-format off
3235  std::vector<std::vector<IntervalVar*> > vehicle_break_intervals_;
3236  std::vector<std::vector<std::pair<int64_t, int64_t> > >
3237  vehicle_break_distance_duration_;
3238  // clang-format on
3239  // For each vehicle, stores the part of travel that is made directly
3240  // after (before) the departure (arrival) node of the travel.
3241  // These parts of the travel are non-interruptible, in particular by a break.
3242  std::vector<int> vehicle_pre_travel_evaluators_;
3243  std::vector<int> vehicle_post_travel_evaluators_;
3244 
3245  std::vector<IntVar*> slacks_;
3246  std::vector<IntVar*> dependent_transits_;
3247  std::vector<int64_t> vehicle_span_upper_bounds_;
3248  int64_t global_span_cost_coefficient_;
3249  std::vector<int64_t> vehicle_span_cost_coefficients_;
3250  std::vector<SoftBound> cumul_var_soft_upper_bound_;
3251  std::vector<SoftBound> cumul_var_soft_lower_bound_;
3252  std::vector<PiecewiseLinearCost> cumul_var_piecewise_linear_cost_;
3253  RoutingModel* const model_;
3254  const std::string name_;
3255  int64_t global_optimizer_offset_;
3256  std::vector<int64_t> local_optimizer_offset_for_vehicle_;
3258  std::unique_ptr<SimpleBoundCosts> vehicle_soft_span_upper_bound_;
3259  std::unique_ptr<SimpleBoundCosts>
3260  vehicle_quadratic_cost_soft_span_upper_bound_;
3261  friend class RoutingModel;
3263 
3265 };
3266 
3270  std::vector<IntVar*> variables,
3271  std::vector<int64_t> targets);
3272 
3278  const RoutingSearchParameters& search_parameters,
3279  const Assignment* initial_solution,
3280  Assignment* solution);
3281 
3282 #if !defined(SWIG)
3284  const RoutingModel& routing_model, const RoutingDimension& dimension);
3285 
3286 // A decision builder that monitors solutions, and tries to fix dimension
3287 // variables whose route did not change in the candidate solution.
3288 // Dimension variables are Cumul, Slack and break variables of all dimensions.
3289 // The user must make sure that those variables will be always be fixed at
3290 // solution, typically by composing another DecisionBuilder after this one.
3291 // If this DecisionBuilder returns a non-nullptr value at some node of the
3292 // search tree, it will always return nullptr in the subtree of that node.
3293 // Moreover, the decision will be a simultaneous assignment of the dimension
3294 // variables of unchanged routes on the left branch, and an empty decision on
3295 // the right branch.
3297  RoutingModel* model);
3298 #endif
3299 
3300 } // namespace operations_research
3301 #endif // OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_H_
int64_t max
Definition: alldiff_cst.cc:140
An Assignment is a variable -> domains mapping, used to report solutions to the user.
A BaseObject is the root of all reversibly allocated objects.
A constraint is the main modeling object.
A DecisionBuilder is responsible for creating the search tree.
This class acts like a CP propagator: it takes a set of tasks given by their start/duration/end featu...
Definition: routing.h:2333
We call domain any subset of Int64 = [kint64min, kint64max].
GlobalVehicleBreaksConstraint ensures breaks constraints are enforced on all vehicles in the dimensio...
Definition: routing.h:2441
std::string DebugString() const override
Definition: routing.h:2444
The class IntVar is a subset of IntExpr.
Interval variables are often used in scheduling.
Local Search Filters are used for fast neighbor pruning.
The base class for all local search operators.
PathsMetadata(const RoutingIndexManager &manager)
Definition: routing.h:210
const std::vector< int64_t > & Ends() const
Definition: routing.h:236
bool IsEnd(int64_t node) const
Definition: routing.h:231
int GetPath(int64_t start_or_end_node) const
Definition: routing.h:232
bool IsStart(int64_t node) const
Definition: routing.h:230
const std::vector< int64_t > & Starts() const
Definition: routing.h:235
Dimensions represent quantities accumulated at nodes along the routes.
Definition: routing.h:2750
void SetSoftSpanUpperBoundForVehicle(BoundCost bound_cost, int vehicle)
If the span of vehicle on this dimension is larger than bound, the cost will be increased by cost * (...
Definition: routing.h:3108
void SetQuadraticCostSoftSpanUpperBoundForVehicle(BoundCost bound_cost, int vehicle)
If the span of vehicle on this dimension is larger than bound, the cost will be increased by cost * (...
Definition: routing.h:3124
const std::vector< IntVar * > & cumuls() const
Like CumulVar(), TransitVar(), SlackVar() but return the whole variable vectors instead (indexed by i...
Definition: routing.h:2779
IntVar * FixedTransitVar(int64_t index) const
Definition: routing.h:2771
const RoutingModel::TransitCallback2 & class_transit_evaluator(RoutingVehicleClassIndex vehicle_class) const
Returns the callback evaluating the transit value between two node indices for a given vehicle class.
Definition: routing.h:2840
int64_t GetSpanCostCoefficientForVehicleClass(RoutingVehicleClassIndex vehicle_class) const
Definition: routing.h:3078
RoutingModel * model() const
Returns the model on which the dimension was created.
Definition: routing.h:2754
int64_t GetGlobalOptimizerOffset() const
Definition: routing.h:3094
const RoutingModel::TransitCallback1 & GetUnaryTransitEvaluator(int vehicle) const
Returns the unary callback evaluating the transit value between two node indices for a given vehicle.
Definition: routing.h:2850
BoundCost GetSoftSpanUpperBoundForVehicle(int vehicle) const
Definition: routing.h:3118
int64_t GetSpanCostCoefficientForVehicle(int vehicle) const
Definition: routing.h:3074
int64_t global_span_cost_coefficient() const
Definition: routing.h:3090
int64_t GetSpanUpperBoundForVehicle(int vehicle) const
Definition: routing.h:3066
bool AreVehicleTransitsPositive(int vehicle) const
Returns true iff the transit evaluator of 'vehicle' is positive for all arcs.
Definition: routing.h:2862
void AddNodePrecedence(int64_t first_node, int64_t second_node, int64_t offset)
Definition: routing.h:3061
const std::vector< IntVar * > & fixed_transits() const
Definition: routing.h:2780
const RoutingModel::TransitCallback2 & GetBinaryTransitEvaluator(int vehicle) const
Definition: routing.h:2855
const std::vector< IntVar * > & transits() const
Definition: routing.h:2781
const RoutingDimension * base_dimension() const
Returns the parent in the dependency tree if any or nullptr otherwise.
Definition: routing.h:3008
std::function< int64_t(int, int)> PickupToDeliveryLimitFunction
Limits, in terms of maximum difference between the cumul variables, between the pickup and delivery a...
Definition: routing.h:3037
void AddNodePrecedence(NodePrecedence precedence)
Definition: routing.h:3053
const std::vector< int64_t > & vehicle_span_cost_coefficients() const
Definition: routing.h:3086
int64_t GetFirstPossibleGreaterOrEqualValueForNode(int64_t index, int64_t min_value) const
Returns the smallest value outside the forbidden intervals of node 'index' that is greater than or eq...
Definition: routing.h:2793
BoundCost GetQuadraticCostSoftSpanUpperBoundForVehicle(int vehicle) const
Definition: routing.h:3137
bool HasQuadraticCostSoftSpanUpperBounds() const
Definition: routing.h:3134
IntVar * SlackVar(int64_t index) const
Definition: routing.h:2774
int vehicle_to_class(int vehicle) const
Definition: routing.h:2866
const RoutingModel::TransitCallback2 & transit_evaluator(int vehicle) const
Returns the callback evaluating the transit value between two node indices for a given vehicle.
Definition: routing.h:2833
const std::vector< int64_t > & vehicle_capacities() const
Returns the capacities for all vehicles.
Definition: routing.h:2828
int64_t GetTransitValueFromClass(int64_t from_index, int64_t to_index, int64_t vehicle_class) const
Same as above but taking a vehicle class of the dimension instead of a vehicle (the class of a vehicl...
Definition: routing.h:2762
int64_t GetLastPossibleLessOrEqualValueForNode(int64_t index, int64_t max_value) const
Returns the largest value outside the forbidden intervals of node 'index' that is less than or equal ...
Definition: routing.h:2812
int64_t GetLocalOptimizerOffsetForVehicle(int vehicle) const
Definition: routing.h:3098
const ReverseArcListGraph< int, int > & GetPathPrecedenceGraph() const
Accessors.
Definition: routing.h:3023
const std::string & name() const
Returns the name of the dimension.
Definition: routing.h:3019
const std::vector< IntVar * > & slacks() const
Definition: routing.h:2782
IntVar * CumulVar(int64_t index) const
Get the cumul, transit and slack variables for the given node (given as int64_t var index).
Definition: routing.h:2769
const std::vector< NodePrecedence > & GetNodePrecedences() const
Definition: routing.h:3056
const std::vector< int64_t > & vehicle_span_upper_bounds() const
Definition: routing.h:3070
IntVar * TransitVar(int64_t index) const
Definition: routing.h:2770
const std::vector< SortedDisjointIntervalList > & forbidden_intervals() const
Returns forbidden intervals for each node.
Definition: routing.h:2785
Manager for any NodeIndex <-> variable index conversion.
const std::vector< int > & GetNeighborsOfNodeForCostClass(int cost_class, int node_index) const
Returns the neighbors of the given node for the given cost_class.
Definition: routing.h:1416
A Resource sets attributes (costs/constraints) for a set of dimensions.
Definition: routing.h:458
const ResourceGroup::Attributes & GetDimensionAttributes(const RoutingDimension *dimension) const
Definition: routing.cc:1711
A ResourceGroup defines a set of available Resources with attributes on one or multiple dimensions.
Definition: routing.h:437
const Resource & GetResource(int resource_index) const
Definition: routing.h:498
bool VehicleRequiresAResource(int vehicle) const
Definition: routing.h:493
int AddResource(Attributes attributes, const RoutingDimension *dimension)
Adds a Resource with the given attributes for the corresponding dimension.
Definition: routing.cc:1751
const std::vector< Resource > & GetResources() const
Definition: routing.h:497
const absl::flat_hash_set< DimensionIndex > & GetAffectedDimensionIndices() const
Definition: routing.h:502
ResourceGroup(const RoutingModel *model)
Definition: routing.h:477
const std::vector< int > & GetVehiclesRequiringAResource() const
Definition: routing.h:489
void NotifyVehicleRequiresAResource(int vehicle)
Notifies that the given vehicle index requires a resource from this group if the vehicle is used (i....
Definition: routing.cc:1768
IntVar * ResourceVar(int vehicle, int resource_group) const
Returns the resource variable for the given vehicle index in the given resource group.
Definition: routing.h:1505
const std::vector< std::unique_ptr< ResourceGroup > > & GetResourceGroups() const
Definition: routing.h:749
const std::vector< std::pair< DisjunctionIndex, DisjunctionIndex > > & GetPickupAndDeliveryDisjunctions() const
Definition: routing.h:916
const Assignment * PreAssignment() const
Returns an assignment used to fix some of the variables of the problem.
Definition: routing.h:1251
const std::string & GetPrimaryConstrainedDimension() const
Get the primary constrained dimension, or an empty string if it is unset.
Definition: routing.h:741
std::function< std::vector< operations_research::IntVar * >(RoutingModel *)> GetTabuVarsCallback
Sets the callback returning the variable to use for the Tabu Search metaheuristic.
Definition: routing.h:1679
int nodes() const
Sizes and indices Returns the number of nodes in the model.
Definition: routing.h:1650
const std::vector< int > & GetSameVehicleIndicesOfIndex(int node) const
Returns variable indices of nodes constrained to be on the same route.
Definition: routing.h:1583
ResourceGroup * GetResourceGroup(int rg_index) const
Definition: routing.h:754
bool AddDimensionDependentDimensionWithVehicleCapacity(const std::vector< int > &pure_transits, const std::vector< int > &dependent_transits, const RoutingDimension *base_dimension, int64_t slack_max, std::vector< int64_t > vehicle_capacities, bool fix_start_cumul_to_zero, const std::string &name)
Creates a dimension with transits depending on the cumuls of another dimension.
Definition: routing.h:644
std::vector< const RoutingDimension * > GetDimensionsWithGlobalCumulOptimizers() const
Returns the dimensions which have [global|local]_dimension_optimizers_.
Definition: routing.cc:5314
VehicleClassIndex GetVehicleClassIndexOfVehicle(int64_t vehicle) const
Definition: routing.h:1561
void ForEachNodeInDisjunctionWithMaxCardinalityFromIndex(int64_t index, int64_t max_cardinality, F f) const
Calls f for each variable index of indices in the same disjunctions as the node corresponding to the ...
Definition: routing.h:799
RoutingIndexPair IndexPair
Definition: routing.h:286
GlobalDimensionCumulOptimizer * GetMutableGlobalCumulLPOptimizer(const RoutingDimension &dimension) const
Returns the global/local dimension cumul optimizer for a given dimension, or nullptr if there is none...
Definition: routing.cc:1617
std::pair< int, bool > AddMatrixDimension(std::vector< std::vector< int64_t > > values, int64_t capacity, bool fix_start_cumul_to_zero, const std::string &name)
Creates a dimension where the transit variable is constrained to be equal to 'values[i][next(i)]' for...
Definition: routing.cc:1457
IntVar * ActiveVehicleVar(int vehicle) const
Returns the active variable of the vehicle.
Definition: routing.h:1490
RoutingTransitCallback1 TransitCallback1
Definition: routing.h:281
const std::vector< int > & GetDimensionResourceGroupIndices(const RoutingDimension *dimension) const
Returns the indices of resource groups for this dimension.
Definition: routing.cc:1775
bool IsVehicleUsedWhenEmpty(int vehicle) const
Definition: routing.h:1123
const std::vector< std::vector< int > > & GetTopologicallySortedVisitTypes() const
Definition: routing.h:969
int GetVehicleClassesCount() const
Returns the number of different vehicle classes in the model.
Definition: routing.h:1581
std::pair< int, bool > AddVectorDimension(std::vector< int64_t > values, int64_t capacity, bool fix_start_cumul_to_zero, const std::string &name)
Creates a dimension where the transit variable is constrained to be equal to 'values[i]' for node i; ...
Definition: routing.cc:1448
bool IsStart(int64_t index) const
Returns true if 'index' represents the first node of a route.
Definition: routing.h:1454
Assignment * MutablePreAssignment()
Definition: routing.h:1252
IntVar * ActiveVar(int64_t index) const
Returns the active variable of the node corresponding to index.
Definition: routing.h:1487
const std::vector< DisjunctionIndex > & GetDisjunctionIndices(int64_t index) const
Returns the indices of the disjunctions to which an index belongs.
Definition: routing.h:791
IntVar * NextVar(int64_t index) const
!defined(SWIGPYTHON)
Definition: routing.h:1485
int RegisterStateDependentTransitCallback(VariableIndexEvaluator2 callback)
Definition: routing.cc:1334
int GetDimensionResourceGroupIndex(const RoutingDimension *dimension) const
Returns the index of the resource group attached to the dimension.
Definition: routing.h:766
const std::vector< int64_t > & GetDisjunctionNodeIndices(DisjunctionIndex index) const
Returns the variable indices of the nodes in the disjunction of index 'index'.
Definition: routing.h:812
const std::vector< int64_t > & GetAmortizedQuadraticCostFactorOfVehicles() const
Definition: routing.h:1113
const TransitCallback1 & UnaryTransitCallbackOrNull(int callback_index) const
Definition: routing.h:551
VisitTypePolicy
Set the node visit types and incompatibilities/requirements between the types (see below).
Definition: routing.h:939
@ TYPE_ADDED_TO_VEHICLE
When visited, the number of types 'T' on the vehicle increases by one.
Definition: routing.h:941
@ ADDED_TYPE_REMOVED_FROM_VEHICLE
When visited, one instance of type 'T' previously added to the route (TYPE_ADDED_TO_VEHICLE),...
Definition: routing.h:946
@ TYPE_ON_VEHICLE_UP_TO_VISIT
With the following policy, the visit enforces that type 'T' is considered on the route from its start...
Definition: routing.h:949
GlobalDimensionCumulOptimizer * GetMutableGlobalCumulMPOptimizer(const RoutingDimension &dimension) const
Definition: routing.cc:1625
Constraint * MakePathSpansAndTotalSlacks(const RoutingDimension *dimension, std::vector< IntVar * > spans, std::vector< IntVar * > total_slacks)
For every vehicle of the routing model:
Definition: routing.cc:6479
int64_t GetHomogeneousCost(int64_t from_index, int64_t to_index) const
Returns the cost of the segment between two nodes supposing all vehicle costs are the same (returns t...
Definition: routing.h:1523
IntVar * VehicleVar(int64_t index) const
Returns the vehicle variable of the node corresponding to index.
Definition: routing.h:1501
int RegisterUnaryTransitVector(std::vector< int64_t > values)
Registers 'callback' and returns its index.
Definition: routing.cc:1256
bool HasLocalCumulOptimizer(const RoutingDimension &dimension) const
Definition: routing.h:709
void AddLocalSearchFilter(LocalSearchFilter *filter)
Adds a custom local search filter to the list of filters used to speed up local search by pruning unf...
Definition: routing.h:1439
int64_t Size() const
Returns the number of next variables in the model.
Definition: routing.h:1654
RoutingDimension * GetMutableDimension(const std::string &dimension_name) const
Returns a dimension from its name.
Definition: routing.cc:1690
bool HasTemporalTypeRequirements() const
Definition: routing.h:1036
Solver * solver() const
Returns the underlying constraint solver.
Definition: routing.h:1630
static const int64_t kNoPenalty
Constant used to express a hard constraint instead of a soft penalty.
Definition: routing.h:518
RoutingTransitCallback2 TransitCallback2
Definition: routing.h:282
const std::vector< RoutingDimension * > & GetDimensions() const
Returns all dimensions of the model.
Definition: routing.h:693
int64_t GetDisjunctionMaxCardinality(DisjunctionIndex index) const
Returns the maximum number of possible active nodes of the node disjunction of index 'index'.
Definition: routing.h:823
std::vector< std::string > GetAllDimensionNames() const
Outputs the names of all dimensions added to the routing engine.
Definition: routing.cc:1608
std::pair< int, bool > AddConstantDimensionWithSlack(int64_t value, int64_t capacity, int64_t slack_max, bool fix_start_cumul_to_zero, const std::string &name)
Creates a dimension where the transit variable is constrained to be equal to 'value'; 'capacity' is t...
Definition: routing.cc:1437
const std::vector< IntVar * > & ResourceVars(int resource_group) const
Returns vehicle resource variables for a given resource group, such that ResourceVars(r_g)[v] is the ...
Definition: routing.h:1479
const Solver::IndexEvaluator2 & first_solution_evaluator() const
Gets/sets the evaluator used during the search.
Definition: routing.h:1131
LocalDimensionCumulOptimizer * GetMutableLocalCumulLPOptimizer(const RoutingDimension &dimension) const
Definition: routing.cc:1646
Status
Status of the search.
Definition: routing.h:249
@ ROUTING_INFEASIBLE
Problem proven to be infeasible.
Definition: routing.h:265
@ ROUTING_SUCCESS
Problem solved successfully after calling RoutingModel::Solve().
Definition: routing.h:253
@ ROUTING_FAIL
No solution found to the problem after calling RoutingModel::Solve().
Definition: routing.h:259
@ ROUTING_NOT_SOLVED
Problem not solved yet (before calling RoutingModel::Solve()).
Definition: routing.h:251
@ ROUTING_PARTIAL_SUCCESS_LOCAL_OPTIMUM_NOT_REACHED
Problem solved successfully after calling RoutingModel::Solve(), except that a local optimum has not ...
Definition: routing.h:257
@ ROUTING_INVALID
Model, model parameters or flags are not valid.
Definition: routing.h:263
@ ROUTING_FAIL_TIMEOUT
Time limit reached before finding a solution with RoutingModel::Solve().
Definition: routing.h:261
bool HasVehicleWithCostClassIndex(CostClassIndex cost_class_index) const
Returns true iff the model contains a vehicle with the given cost_class_index.
Definition: routing.h:1548
bool enable_deep_serialization() const
Returns the value of the internal enable_deep_serialization_ parameter.
Definition: routing.h:1227
std::vector< RoutingDimension * > GetDimensionsWithSoftOrSpanCosts() const
Returns dimensions with soft or vehicle span costs.
Definition: routing.cc:5288
std::vector< const RoutingDimension * > GetDimensionsWithLocalCumulOptimizers() const
Definition: routing.cc:5326
RoutingIndexPairs IndexPairs
Definition: routing.h:287
bool CheckLimit(absl::Duration offset=absl::ZeroDuration())
Returns true if the search limit has been crossed with the given time offset.
Definition: routing.h:1634
bool IsVehicleAllowedForIndex(int vehicle, int64_t index)
Returns true if a vehicle is allowed to visit a given node.
Definition: routing.h:860
int RegisterPositiveUnaryTransitCallback(TransitCallback1 callback)
Definition: routing.cc:1293
const std::vector< IntVar * > & VehicleVars() const
Returns all vehicle variables of the model, such that VehicleVars(i) is the vehicle variable of the n...
Definition: routing.h:1475
absl::Duration TimeBuffer() const
Returns the time buffer to safely return a solution.
Definition: routing.h:1646
void SetMaximumNumberOfActiveVehicles(int max_active_vehicles)
Constrains the maximum number of active vehicles, aka the number of vehicles which do not have an emp...
Definition: routing.h:1067
const IndexPairs & GetImplicitUniquePickupAndDeliveryPairs() const
Returns implicit pickup and delivery pairs currently in the model.
Definition: routing.h:923
const std::vector< int64_t > & GetAmortizedLinearCostFactorOfVehicles() const
Definition: routing.h:1110
DisjunctionIndex AddDisjunction(const std::vector< int64_t > &indices, int64_t penalty=kNoPenalty, int64_t max_cardinality=1)
Adds a disjunction constraint on the indices: exactly 'max_cardinality' of the indices are active.
Definition: routing.cc:2179
bool HasGlobalCumulOptimizer(const RoutingDimension &dimension) const
Returns whether the given dimension has global/local cumul optimizers.
Definition: routing.h:706
int RegisterTransitCallback(TransitCallback2 callback)
Definition: routing.cc:1301
int AddResourceGroup()
Adds a resource group to the routing model.
Definition: routing.cc:1737
int GetMaximumNumberOfActiveVehicles() const
Returns the maximum number of active vehicles.
Definition: routing.h:1071
RoutingDimensionIndex DimensionIndex
Definition: routing.h:278
void SetVehicleUsedWhenEmpty(bool is_used, int vehicle)
Definition: routing.h:1118
LocalDimensionCumulOptimizer * GetMutableLocalCumulMPOptimizer(const RoutingDimension &dimension) const
Definition: routing.cc:1654
bool HasHardTypeIncompatibilities() const
Returns true iff any hard (resp.
Definition: routing.h:988
const IndexPairs & GetPickupAndDeliveryPairs() const
Returns pickup and delivery pairs currently in the model.
Definition: routing.h:912
int RegisterPositiveTransitCallback(TransitCallback2 callback)
Definition: routing.cc:1327
PickupAndDeliveryPolicy
Types of precedence policy applied to pickup and delivery pairs.
Definition: routing.h:269
@ PICKUP_AND_DELIVERY_LIFO
Deliveries must be performed in reverse order of pickups.
Definition: routing.h:273
@ PICKUP_AND_DELIVERY_NO_ORDER
Any precedence is accepted.
Definition: routing.h:271
@ PICKUP_AND_DELIVERY_FIFO
Deliveries must be performed in the same order as pickups.
Definition: routing.h:275
int64_t Start(int vehicle) const
Model inspection.
Definition: routing.h:1450
int vehicles() const
Returns the number of vehicle routes in the model.
Definition: routing.h:1652
int GetNumberOfDisjunctions() const
Returns the number of node disjunctions in the model.
Definition: routing.h:827
const std::vector< IntVar * > & Nexts() const
Returns all next variables of the model, such that Nexts(i) is the next variable of the node correspo...
Definition: routing.h:1472
bool HasTypeRegulations() const
Returns true iff the model has any incompatibilities or requirements set on node types.
Definition: routing.h:1042
void SetFirstSolutionEvaluator(Solver::IndexEvaluator2 evaluator)
Takes ownership of evaluator.
Definition: routing.h:1136
RoutingVehicleClassIndex VehicleClassIndex
Definition: routing.h:280
std::function< StateDependentTransit(int64_t, int64_t)> VariableIndexEvaluator2
Definition: routing.h:308
int GetNonZeroCostClassesCount() const
Ditto, minus the 'always zero', built-in cost class.
Definition: routing.h:1558
bool AddDimensionWithVehicleCapacity(int evaluator_index, int64_t slack_max, std::vector< int64_t > vehicle_capacities, bool fix_start_cumul_to_zero, const std::string &name)
Definition: routing.cc:1377
bool HasSameVehicleTypeRequirements() const
Returns true iff any same-route (resp.
Definition: routing.h:1033
IntVar * CostVar() const
Returns the global cost variable which is being minimized.
Definition: routing.h:1511
std::pair< int, bool > AddConstantDimension(int64_t value, int64_t capacity, bool fix_start_cumul_to_zero, const std::string &name)
Definition: routing.h:607
void SetPrimaryConstrainedDimension(const std::string &dimension_name)
Set the given dimension as "primary constrained".
Definition: routing.h:736
const VariableIndexEvaluator2 & StateDependentTransitCallback(int callback_index) const
Definition: routing.h:555
static RoutingModel::StateDependentTransit MakeStateDependentTransit(const std::function< int64_t(int64_t)> &f, int64_t domain_start, int64_t domain_end)
Creates a cached StateDependentTransit from an std::function.
Definition: routing.cc:1596
int RegisterUnaryTransitCallback(TransitCallback1 callback)
Definition: routing.cc:1266
bool IsEnd(int64_t index) const
Returns true if 'index' represents the last node of a route.
Definition: routing.h:1456
bool AddDimensionWithVehicleTransits(const std::vector< int > &evaluator_indices, int64_t slack_max, int64_t capacity, bool fix_start_cumul_to_zero, const std::string &name)
Definition: routing.cc:1368
RoutingCostClassIndex CostClassIndex
Definition: routing.h:277
bool HasTemporalTypeIncompatibilities() const
Definition: routing.h:991
int GetCostClassesCount() const
Returns the number of different cost classes in the model.
Definition: routing.h:1556
const TransitCallback2 & TransitCallback(int callback_index) const
Definition: routing.h:547
operations_research::FirstSolutionStrategy::Value GetAutomaticFirstSolutionStrategy() const
Returns the automatic first solution strategy selected.
Definition: routing.h:1664
const std::vector< SearchMonitor * > & GetSearchMonitors() const
Definition: routing.h:1709
IntVar * VehicleRouteConsideredVar(int vehicle) const
Returns the variable specifying whether or not the given vehicle route is considered for costs and co...
Definition: routing.h:1496
absl::Duration RemainingTime() const
Returns the time left in the search limit.
Definition: routing.h:1640
Status status() const
Returns the current status of the routing model.
Definition: routing.h:1225
int RegisterTransitMatrix(std::vector< std::vector< int64_t > > values)
Definition: routing.cc:1274
static const DimensionIndex kNoDimension
Constant used to express the "no dimension" index, returned when a dimension name does not correspond...
Definition: routing.h:526
bool CostsAreHomogeneousAcrossVehicles() const
Whether costs are homogeneous across all vehicles.
Definition: routing.h:1518
CostClassIndex GetCostClassIndexOfVehicle(int64_t vehicle) const
Get the cost class index of the given vehicle.
Definition: routing.h:1539
const VehicleTypeContainer & GetVehicleTypeContainer() const
Definition: routing.h:1588
static const DisjunctionIndex kNoDisjunction
Constant used to express the "no disjunction" index, returned when a node does not appear in any disj...
Definition: routing.h:522
bool HasDimension(const std::string &dimension_name) const
Returns true if a dimension exists for a given dimension name.
Definition: routing.cc:1675
int VehicleIndex(int64_t index) const
Returns the vehicle of the given start/end index, and -1 if the given index is not a vehicle start/en...
Definition: routing.h:1459
int GetVehicleOfClass(VehicleClassIndex vehicle_class) const
Returns a vehicle of the given vehicle class, and -1 if there are no vehicles for this class.
Definition: routing.h:1567
RoutingModel(const RoutingIndexManager &index_manager)
Constructor taking an index manager.
Definition: routing.cc:1138
bool AddDimensionWithVehicleTransitAndCapacity(const std::vector< int > &evaluator_indices, int64_t slack_max, std::vector< int64_t > vehicle_capacities, bool fix_start_cumul_to_zero, const std::string &name)
Definition: routing.cc:1387
RoutingDisjunctionIndex DisjunctionIndex
Definition: routing.h:279
int64_t End(int vehicle) const
Returns the variable index of the ending node of a vehicle route.
Definition: routing.h:1452
bool AddDimension(int evaluator_index, int64_t slack_max, int64_t capacity, bool fix_start_cumul_to_zero, const std::string &name)
Model creation.
Definition: routing.cc:1358
const RoutingDimension & GetDimensionOrDie(const std::string &dimension_name) const
Returns a dimension from its name. Dies if the dimension does not exist.
Definition: routing.cc:1685
A search monitor is a simple set of callbacks to monitor all search events.
BoundCost & bound_cost(int element)
Definition: routing.h:2719
SimpleBoundCosts(int num_bounds, BoundCost default_bound_cost)
Definition: routing.h:2716
BoundCost bound_cost(int element) const
Definition: routing.h:2721
SimpleBoundCosts(const SimpleBoundCosts &)=delete
SimpleBoundCosts operator=(const SimpleBoundCosts &)=delete
std::function< int64_t(int64_t, int64_t)> IndexEvaluator2
This class represents a sorted list of disjoint, closed intervals.
Iterator FirstIntervalGreaterOrEqual(int64_t value) const
Returns an iterator to either:
Class to arrange indices by their distance and their angle from the depot.
Checker for type incompatibilities.
Definition: routing.h:2598
virtual bool HasRegulationsToCheck() const =0
virtual bool CheckTypeRegulations(int type, VisitTypePolicy policy, int pos)=0
The following constraint ensures that incompatibilities and requirements between types are respected.
Definition: routing.h:2678
Checker for type requirements.
Definition: routing.h:2614
TypeRequirementChecker(const RoutingModel &model)
Definition: routing.h:2616
int64_t b
int64_t a
SatParameters parameters
const std::string name
int64_t value
IntVar * var
Definition: expr_array.cc:1874
const int64_t limit_
const std::vector< IntVar * > cumuls_
GRBmodel * model
MPCallback * callback
static const int64_t kint64max
static const int64_t kint64min
int index
#define DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition: macros.h:29
absl::StatusOr< SolveResult > Solve(const Model &model, const SolverType solver_type, const SolveArguments &solve_args, const SolverInitArguments &init_args)
H AbslHashValue(H h, const IndicatorConstraint &constraint)
std::function< int64_t(const Model &)> Value(IntegerVariable v)
Definition: integer.h:1795
CpSolverResponse SolveWithParameters(const CpModelProto &model_proto, const SatParameters &params)
Solves the given CpModelProto with the given parameters.
Collection of objects used to extend the Constraint Solver library.
bool SolveModelWithSat(const RoutingModel &model, const RoutingSearchParameters &search_parameters, const Assignment *initial_solution, Assignment *solution)
Attempts to solve the model using the cp-sat solver.
int64_t CapAdd(int64_t x, int64_t y)
std::function< int64_t(int64_t, int64_t)> RoutingTransitCallback2
Definition: routing_types.h:43
IntVarLocalSearchFilter * MakeVehicleBreaksFilter(const RoutingModel &routing_model, const RoutingDimension &dimension)
int64_t CapSub(int64_t x, int64_t y)
int64_t Zero()
NOLINT.
std::pair< std::vector< int64_t >, std::vector< int64_t > > RoutingIndexPair
Definition: routing_types.h:45
void AppendTasksFromIntervals(const std::vector< IntervalVar * > &intervals, DisjunctivePropagator::Tasks *tasks)
DecisionBuilder * MakeRestoreDimensionValuesForUnchangedRoutes(RoutingModel *model)
Definition: routing.cc:3275
DecisionBuilder * MakeSetValuesFromTargets(Solver *solver, std::vector< IntVar * > variables, std::vector< int64_t > targets)
A decision builder which tries to assign values to variables as close as possible to target values fi...
Definition: routing.cc:202
void AppendTasksFromPath(const std::vector< int64_t > &path, const TravelBounds &travel_bounds, const RoutingDimension &dimension, DisjunctivePropagator::Tasks *tasks)
std::function< int64_t(int64_t)> RoutingTransitCallback1
Definition: routing_types.h:42
void FillPathEvaluation(const std::vector< int64_t > &path, const RoutingModel::TransitCallback2 &evaluator, std::vector< int64_t > *values)
Definition: routing.cc:6774
void FillTravelBoundsOfVehicle(int vehicle, const std::vector< int64_t > &path, const RoutingDimension &dimension, TravelBounds *travel_bounds)
LinearRange operator==(const LinearExpr &lhs, const LinearExpr &rhs)
Definition: linear_expr.cc:184
std::vector< RoutingIndexPair > RoutingIndexPairs
Definition: routing_types.h:46
IntervalVar * interval
Definition: resource.cc:101
IntVar * upper_bound
Definition: routing.cc:1087
IntVar * lower_bound
Definition: routing.cc:1086
int64_t bound
int64_t coefficient
int64_t capacity
int64_t cost
int vehicle_class
double distance
Rev< int64_t > start_max
Rev< int64_t > end_max
Rev< int64_t > start_min
Rev< int64_t > end_min
std::optional< int64_t > end
int64_t start
A structure meant to store soft bounds and associated violation constants.
Definition: routing.h:2707
BoundCost(int64_t bound, int64_t cost)
Definition: routing.h:2711
A structure to hold tasks described by their features.
Definition: routing.h:2340
std::vector< std::pair< int64_t, int64_t > > distance_duration
Definition: routing.h:2350
std::vector< const SortedDisjointIntervalList * > forbidden_intervals
Definition: routing.h:2349
SUBTLE: The vehicle's fixed cost is skipped on purpose here, because we can afford to do so:
Definition: routing.h:336
bool operator<(const DimensionCost &cost) const
Definition: routing.h:340
int evaluator_index
Index of the arc cost evaluator, registered in the RoutingModel class.
Definition: routing.h:314
static bool LessThan(const CostClass &a, const CostClass &b)
Comparator for STL containers and algorithms.
Definition: routing.h:354
std::vector< DimensionCost > dimension_transit_evaluator_class_and_cost_coefficient
Definition: routing.h:348
The following struct defines a piecewise linear formulation, with int64_t values for the "anchor" x a...
Definition: routing.h:1352
absl::InlinedVector< int64_t, 8 > y_anchors
The y values used for the interpolation: For any x anchor value, let i be an index such that x_anchor...
Definition: routing.h:1360
absl::InlinedVector< int64_t, 8 > x_anchors
The set of increasing anchor cumul values for the interpolation.
Definition: routing.h:1354
Contains the information for a single transition on the route.
Definition: routing.h:1347
int64_t pre_travel_transit_value
The parts of the transit which occur pre/post travel between the nodes.
Definition: routing.h:1377
PiecewiseLinearFormulation travel_compression_cost
travel_compression_cost models the cost of the difference between the (real) travel value Tᵣ given by...
Definition: routing.h:1372
int64_t travel_value_upper_bound
The hard upper bound of the (real) travel value Tᵣ (see above).
Definition: routing.h:1388
int64_t compressed_travel_value_lower_bound
The hard lower bound of the compressed travel value that will be enforced by the scheduling module.
Definition: routing.h:1382
PiecewiseLinearFormulation travel_start_dependent_travel
Models the (real) travel value Tᵣ, for this transition based on the departure value of the travel.
Definition: routing.h:1367
Contains the information needed by the solver to optimize a dimension's cumuls with travel-start depe...
Definition: routing.h:1345
std::vector< TransitionInfo > transition_info
For each node #i on the route, transition_info[i] contains the relevant information for the travel be...
Definition: routing.h:1395
int64_t travel_cost_coefficient
The cost per unit of travel for this vehicle.
Definition: routing.h:1397
What follows is relevant for models with time/state dependent transits.
Definition: routing.h:303
RangeMinMaxIndexFunction * transit_plus_identity
f(x)
Definition: routing.h:305
int64_t fixed_cost
Contrarily to CostClass, here we need strict equivalence.
Definition: routing.h:367
absl::StrongVector< DimensionIndex, int64_t > dimension_end_cumuls_max
Definition: routing.h:383
std::vector< int > required_resource_group_indices
Sorted set of resource groups for which the vehicle requires a resource.
Definition: routing.h:391
uint64_t unvisitable_nodes_fprint
Fingerprint of unvisitable non-start/end nodes.
Definition: routing.h:389
bool used_when_empty
Whether or not the vehicle is used when empty.
Definition: routing.h:369
int start_equivalence_class
Vehicle start and end equivalence classes.
Definition: routing.h:376
absl::StrongVector< DimensionIndex, int64_t > dimension_capacities
Definition: routing.h:384
static bool LessThan(const VehicleClass &a, const VehicleClass &b)
Comparator for STL containers and algorithms.
Definition: routing.cc:1917
absl::StrongVector< DimensionIndex, int64_t > dimension_end_cumuls_min
Definition: routing.h:382
absl::StrongVector< DimensionIndex, int64_t > dimension_evaluator_classes
dimension_evaluators[d]->Run(from, to) is the transit value of arc from->to for a dimension d.
Definition: routing.h:387
absl::StrongVector< DimensionIndex, int64_t > dimension_start_cumuls_min
Bounds of cumul variables at start and end vehicle nodes.
Definition: routing.h:380
absl::StrongVector< DimensionIndex, int64_t > dimension_start_cumuls_max
Definition: routing.h:381
CostClassIndex cost_class_index
The cost class of the vehicle.
Definition: routing.h:365
Definition: routing.h:402
int64_t fixed_cost
Definition: routing.h:404
bool operator<(const VehicleClassEntry &other) const
Definition: routing.h:406
int vehicle_class
Definition: routing.h:403
Struct used to sort and store vehicles by their type.
Definition: routing.h:401
std::vector< std::set< VehicleClassEntry > > sorted_vehicle_classes_per_type
Definition: routing.h:421
std::vector< std::deque< int > > vehicles_per_vehicle_class
Definition: routing.h:422
std::vector< int64_t > post_travels
Definition: routing.h:2414
std::vector< int64_t > max_travels
Definition: routing.h:2412
std::vector< int64_t > pre_travels
Definition: routing.h:2413
std::vector< int64_t > min_travels
Definition: routing.h:2411