OR-Tools  9.0
routing.h
Go to the documentation of this file.
1 // Copyright 2010-2021 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 <deque>
162 #include <functional>
163 #include <memory>
164 #include <set>
165 #include <string>
166 #include <tuple>
167 #include <utility>
168 #include <vector>
169 
170 #include "absl/container/flat_hash_map.h"
171 #include "absl/container/flat_hash_set.h"
172 #include "absl/functional/bind_front.h"
173 #include "absl/memory/memory.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"
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:
211  enum Status {
222  };
223 
232  };
233  typedef RoutingCostClassIndex CostClassIndex;
234  typedef RoutingDimensionIndex DimensionIndex;
235  typedef RoutingDisjunctionIndex DisjunctionIndex;
236  typedef RoutingVehicleClassIndex VehicleClassIndex;
239 
240 // TODO(user): Remove all SWIG guards by adding the @ignore in .i.
241 #if !defined(SWIG)
244 #endif // SWIG
245 
246 #if !defined(SWIG)
262  };
263  typedef std::function<StateDependentTransit(int64_t, int64_t)>
265 #endif // SWIG
266 
267 #if !defined(SWIG)
268  struct CostClass {
271 
286 
292  struct DimensionCost {
296  bool operator<(const DimensionCost& cost) const {
297  if (transit_evaluator_class != cost.transit_evaluator_class) {
298  return transit_evaluator_class < cost.transit_evaluator_class;
299  }
300  return cost_coefficient < cost.cost_coefficient;
301  }
302  };
303  std::vector<DimensionCost>
305 
308 
310  static bool LessThan(const CostClass& a, const CostClass& b) {
311  if (a.evaluator_index != b.evaluator_index) {
312  return a.evaluator_index < b.evaluator_index;
313  }
314  return a.dimension_transit_evaluator_class_and_cost_coefficient <
315  b.dimension_transit_evaluator_class_and_cost_coefficient;
316  }
317  };
318 
319  struct VehicleClass {
323  int64_t fixed_cost;
328  // TODO(user): Find equivalent start/end nodes wrt dimensions and
329  // callbacks.
344 
346  static bool LessThan(const VehicleClass& a, const VehicleClass& b);
347  };
348 #endif // defined(SWIG)
349 
356  int64_t fixed_cost;
357 
358  bool operator<(const VehicleClassEntry& other) const {
359  return std::tie(fixed_cost, vehicle_class) <
360  std::tie(other.fixed_cost, other.vehicle_class);
361  }
362  };
363 
364  int NumTypes() const { return sorted_vehicle_classes_per_type.size(); }
365 
366  int Type(int vehicle) const {
367  DCHECK_LT(vehicle, type_index_of_vehicle.size());
368  return type_index_of_vehicle[vehicle];
369  }
370 
371  std::vector<int> type_index_of_vehicle;
372  // clang-format off
373  std::vector<std::set<VehicleClassEntry> > sorted_vehicle_classes_per_type;
374  std::vector<std::deque<int> > vehicles_per_vehicle_class;
375  // clang-format on
376  };
377 
379  static const int64_t kNoPenalty;
380 
384 
388 
392  explicit RoutingModel(const RoutingIndexManager& index_manager);
393  RoutingModel(const RoutingIndexManager& index_manager,
394  const RoutingModelParameters& parameters);
395  ~RoutingModel();
396 
398  int RegisterUnaryTransitVector(std::vector<int64_t> values);
401 
403  std::vector<std::vector<int64_t> /*needed_for_swig*/> values);
406 
408  const TransitCallback2& TransitCallback(int callback_index) const {
409  CHECK_LT(callback_index, transit_evaluators_.size());
410  return transit_evaluators_[callback_index];
411  }
412  const TransitCallback1& UnaryTransitCallbackOrNull(int callback_index) const {
413  CHECK_LT(callback_index, unary_transit_evaluators_.size());
414  return unary_transit_evaluators_[callback_index];
415  }
417  int callback_index) const {
418  CHECK_LT(callback_index, state_dependent_transit_evaluators_.size());
419  return state_dependent_transit_evaluators_[callback_index];
420  }
421 
423 
435 
444  bool AddDimension(int evaluator_index, int64_t slack_max, int64_t capacity,
445  bool fix_start_cumul_to_zero, const std::string& name);
447  const std::vector<int>& evaluator_indices, int64_t slack_max,
448  int64_t capacity, bool fix_start_cumul_to_zero, const std::string& name);
449  bool AddDimensionWithVehicleCapacity(int evaluator_index, int64_t slack_max,
450  std::vector<int64_t> vehicle_capacities,
451  bool fix_start_cumul_to_zero,
452  const std::string& name);
454  const std::vector<int>& evaluator_indices, int64_t slack_max,
455  std::vector<int64_t> vehicle_capacities, bool fix_start_cumul_to_zero,
456  const std::string& name);
465  std::pair<int, bool> AddConstantDimensionWithSlack(
466  int64_t value, int64_t capacity, int64_t slack_max,
467  bool fix_start_cumul_to_zero, const std::string& name);
468  std::pair<int, bool> AddConstantDimension(int64_t value, int64_t capacity,
469  bool fix_start_cumul_to_zero,
470  const std::string& name) {
472  fix_start_cumul_to_zero, name);
473  }
483  std::pair<int, bool> AddVectorDimension(std::vector<int64_t> values,
484  int64_t capacity,
485  bool fix_start_cumul_to_zero,
486  const std::string& name);
496  std::pair<int, bool> AddMatrixDimension(
497  std::vector<std::vector<int64_t> /*needed_for_swig*/> values,
498  int64_t capacity, bool fix_start_cumul_to_zero, const std::string& name);
506  const std::vector<int>& pure_transits,
507  const std::vector<int>& dependent_transits,
508  const RoutingDimension* base_dimension, int64_t slack_max,
509  std::vector<int64_t> vehicle_capacities, bool fix_start_cumul_to_zero,
510  const std::string& name) {
511  return AddDimensionDependentDimensionWithVehicleCapacityInternal(
512  pure_transits, dependent_transits, base_dimension, slack_max,
513  std::move(vehicle_capacities), fix_start_cumul_to_zero, name);
514  }
515 
518  const std::vector<int>& transits, const RoutingDimension* base_dimension,
519  int64_t slack_max, std::vector<int64_t> vehicle_capacities,
520  bool fix_start_cumul_to_zero, const std::string& name);
523  int transit, const RoutingDimension* base_dimension, int64_t slack_max,
524  int64_t vehicle_capacity, bool fix_start_cumul_to_zero,
525  const std::string& name);
527  int pure_transit, int dependent_transit,
528  const RoutingDimension* base_dimension, int64_t slack_max,
529  int64_t vehicle_capacity, bool fix_start_cumul_to_zero,
530  const std::string& name);
531 
534  const std::function<int64_t(int64_t)>& f, int64_t domain_start,
535  int64_t domain_end);
536 
547  std::vector<IntVar*> spans,
548  std::vector<IntVar*> total_slacks);
549 
551  // TODO(user): rename.
552  std::vector<std::string> GetAllDimensionNames() const;
554  const std::vector<RoutingDimension*>& GetDimensions() const {
555  return dimensions_.get();
556  }
558  std::vector<RoutingDimension*> GetDimensionsWithSoftOrSpanCosts() const;
559  // clang-format off
562  const std::vector<std::unique_ptr<GlobalDimensionCumulOptimizer> >&
564  return global_dimension_optimizers_;
565  }
566  const std::vector<std::unique_ptr<LocalDimensionCumulOptimizer> >&
568  return local_dimension_optimizers_;
569  }
570  const std::vector<std::unique_ptr<LocalDimensionCumulOptimizer> >&
572  return local_dimension_mp_optimizers_;
573  }
574  // clang-format on
575 
579  const RoutingDimension& dimension) const;
581  const RoutingDimension& dimension) const;
583  const RoutingDimension& dimension) const;
584 
586  bool HasDimension(const std::string& dimension_name) const;
589  const std::string& dimension_name) const;
593  const std::string& dimension_name) const;
598  void SetPrimaryConstrainedDimension(const std::string& dimension_name) {
599  DCHECK(dimension_name.empty() || HasDimension(dimension_name));
600  primary_constrained_dimension_ = dimension_name;
601  }
603  const std::string& GetPrimaryConstrainedDimension() const {
604  return primary_constrained_dimension_;
605  }
622  DisjunctionIndex AddDisjunction(const std::vector<int64_t>& indices,
623  int64_t penalty = kNoPenalty,
624  int64_t max_cardinality = 1);
626  const std::vector<DisjunctionIndex>& GetDisjunctionIndices(
627  int64_t index) const {
628  return index_to_disjunctions_[index];
629  }
633  template <typename F>
635  int64_t index, int64_t max_cardinality, F f) const {
636  for (const DisjunctionIndex disjunction : GetDisjunctionIndices(index)) {
637  if (disjunctions_[disjunction].value.max_cardinality == max_cardinality) {
638  for (const int64_t d_index : disjunctions_[disjunction].indices) {
639  f(d_index);
640  }
641  }
642  }
643  }
644 #if !defined(SWIGPYTHON)
647  const std::vector<int64_t>& GetDisjunctionIndices(
648  DisjunctionIndex index) const {
649  return disjunctions_[index].indices;
650  }
651 #endif // !defined(SWIGPYTHON)
653  int64_t GetDisjunctionPenalty(DisjunctionIndex index) const {
654  return disjunctions_[index].value.penalty;
655  }
659  return disjunctions_[index].value.max_cardinality;
660  }
662  int GetNumberOfDisjunctions() const { return disjunctions_.size(); }
667  std::vector<std::pair<int64_t, int64_t>> GetPerfectBinaryDisjunctions() const;
673  void IgnoreDisjunctionsAlreadyForcedToZero();
674 
678  void AddSoftSameVehicleConstraint(const std::vector<int64_t>& indices,
679  int64_t cost);
680 
685  void SetAllowedVehiclesForIndex(const std::vector<int>& vehicles,
686  int64_t index);
687 
689  bool IsVehicleAllowedForIndex(int vehicle, int64_t index) {
690  return allowed_vehicles_[index].empty() ||
691  allowed_vehicles_[index].find(vehicle) !=
692  allowed_vehicles_[index].end();
693  }
694 
709  // TODO(user): Remove this when model introspection detects linked nodes.
710  void AddPickupAndDelivery(int64_t pickup, int64_t delivery);
714  void AddPickupAndDeliverySets(DisjunctionIndex pickup_disjunction,
715  DisjunctionIndex delivery_disjunction);
716  // clang-format off
720  const std::vector<std::pair<int, int> >&
721  GetPickupIndexPairs(int64_t node_index) const;
723  const std::vector<std::pair<int, int> >&
724  GetDeliveryIndexPairs(int64_t node_index) const;
725  // clang-format on
726 
729  void SetPickupAndDeliveryPolicyOfAllVehicles(PickupAndDeliveryPolicy policy);
730  void SetPickupAndDeliveryPolicyOfVehicle(PickupAndDeliveryPolicy policy,
731  int vehicle);
732  PickupAndDeliveryPolicy GetPickupAndDeliveryPolicyOfVehicle(
733  int vehicle) const;
736 
737  int GetNumOfSingletonNodes() const;
738 
739 #ifndef SWIG
742  return pickup_delivery_pairs_;
743  }
744  const std::vector<std::pair<DisjunctionIndex, DisjunctionIndex>>&
746  return pickup_delivery_disjunctions_;
747  }
753  DCHECK(closed_);
754  return implicit_pickup_delivery_pairs_without_alternatives_;
755  }
756 #endif // SWIG
768  enum VisitTypePolicy {
783  TYPE_SIMULTANEOUSLY_ADDED_AND_REMOVED
784  };
785  // TODO(user): Support multiple visit types per node?
786  void SetVisitType(int64_t index, int type, VisitTypePolicy type_policy);
787  int GetVisitType(int64_t index) const;
788  const std::vector<int>& GetSingleNodesOfType(int type) const;
789  const std::vector<int>& GetPairIndicesOfType(int type) const;
790  VisitTypePolicy GetVisitTypePolicy(int64_t index) const;
793  // TODO(user): Reconsider the logic and potentially remove the need to
795  void CloseVisitTypes();
796  int GetNumberOfVisitTypes() const { return num_visit_types_; }
797 #ifndef SWIG
798  const std::vector<std::vector<int>>& GetTopologicallySortedVisitTypes()
799  const {
800  DCHECK(closed_);
801  return topologically_sorted_visit_types_;
802  }
803 #endif // SWIG
808  void AddHardTypeIncompatibility(int type1, int type2);
809  void AddTemporalTypeIncompatibility(int type1, int type2);
811  const absl::flat_hash_set<int>& GetHardTypeIncompatibilitiesOfType(
812  int type) const;
813  const absl::flat_hash_set<int>& GetTemporalTypeIncompatibilitiesOfType(
814  int type) const;
818  return has_hard_type_incompatibilities_;
819  }
821  return has_temporal_type_incompatibilities_;
822  }
833  void AddSameVehicleRequiredTypeAlternatives(
834  int dependent_type, absl::flat_hash_set<int> required_type_alternatives);
839  void AddRequiredTypeAlternativesWhenAddingType(
840  int dependent_type, absl::flat_hash_set<int> required_type_alternatives);
846  void AddRequiredTypeAlternativesWhenRemovingType(
847  int dependent_type, absl::flat_hash_set<int> required_type_alternatives);
848  // clang-format off
851  const std::vector<absl::flat_hash_set<int> >&
852  GetSameVehicleRequiredTypeAlternativesOfType(int type) const;
854  const std::vector<absl::flat_hash_set<int> >&
855  GetRequiredTypeAlternativesWhenAddingType(int type) const;
857  const std::vector<absl::flat_hash_set<int> >&
858  GetRequiredTypeAlternativesWhenRemovingType(int type) const;
859  // clang-format on
863  return has_same_vehicle_type_requirements_;
864  }
866  return has_temporal_type_requirements_;
867  }
868 
871  bool HasTypeRegulations() const {
872  return HasTemporalTypeIncompatibilities() ||
873  HasHardTypeIncompatibilities() || HasSameVehicleTypeRequirements() ||
874  HasTemporalTypeRequirements();
875  }
876 
881  int64_t UnperformedPenalty(int64_t var_index) const;
885  int64_t UnperformedPenaltyOrValue(int64_t default_value,
886  int64_t var_index) const;
890  int64_t GetDepot() const;
891 
896  void SetMaximumNumberOfActiveVehicles(int max_active_vehicles) {
897  max_active_vehicles_ = max_active_vehicles;
898  }
900  int GetMaximumNumberOfActiveVehicles() const { return max_active_vehicles_; }
904  void SetArcCostEvaluatorOfAllVehicles(int evaluator_index);
906  void SetArcCostEvaluatorOfVehicle(int evaluator_index, int vehicle);
909  void SetFixedCostOfAllVehicles(int64_t cost);
911  void SetFixedCostOfVehicle(int64_t cost, int vehicle);
915  int64_t GetFixedCostOfVehicle(int vehicle) const;
916 
932  void SetAmortizedCostFactorsOfAllVehicles(int64_t linear_cost_factor,
933  int64_t quadratic_cost_factor);
935  void SetAmortizedCostFactorsOfVehicle(int64_t linear_cost_factor,
936  int64_t quadratic_cost_factor,
937  int vehicle);
938 
939  const std::vector<int64_t>& GetAmortizedLinearCostFactorOfVehicles() const {
940  return linear_cost_factor_of_vehicle_;
941  }
942  const std::vector<int64_t>& GetAmortizedQuadraticCostFactorOfVehicles()
943  const {
944  return quadratic_cost_factor_of_vehicle_;
945  }
946 
947  void ConsiderEmptyRouteCostsForVehicle(bool consider_costs, int vehicle) {
948  DCHECK_LT(vehicle, vehicles_);
949  consider_empty_route_costs_[vehicle] = consider_costs;
950  }
951 
952  bool AreEmptyRouteCostsConsideredForVehicle(int vehicle) const {
953  DCHECK_LT(vehicle, vehicles_);
954  return consider_empty_route_costs_[vehicle];
955  }
956 
959 #ifndef SWIG
961  return first_solution_evaluator_;
962  }
963 #endif
966  first_solution_evaluator_ = std::move(evaluator);
967  }
970  void AddLocalSearchOperator(LocalSearchOperator* ls_operator);
972  void AddSearchMonitor(SearchMonitor* const monitor);
976  void AddAtSolutionCallback(std::function<void()> callback);
981  void AddVariableMinimizedByFinalizer(IntVar* var);
984  void AddVariableMaximizedByFinalizer(IntVar* var);
987  void AddWeightedVariableMinimizedByFinalizer(IntVar* var, int64_t cost);
990  void AddVariableTargetToFinalizer(IntVar* var, int64_t target);
997  void CloseModel();
1000  void CloseModelWithParameters(
1001  const RoutingSearchParameters& search_parameters);
1008  const Assignment* Solve(const Assignment* assignment = nullptr);
1017  const RoutingSearchParameters& search_parameters,
1018  std::vector<const Assignment*>* solutions = nullptr);
1021  const Assignment* SolveFromAssignmentWithParameters(
1022  const Assignment* assignment,
1023  const RoutingSearchParameters& search_parameters,
1024  std::vector<const Assignment*>* solutions = nullptr);
1027  const Assignment* SolveFromAssignmentsWithParameters(
1028  const std::vector<const Assignment*>& assignments,
1029  const RoutingSearchParameters& search_parameters,
1030  std::vector<const Assignment*>* solutions = nullptr);
1036  void SetAssignmentFromOtherModelAssignment(
1037  Assignment* target_assignment, const RoutingModel* source_model,
1038  const Assignment* source_assignment);
1044  // TODO(user): Add support for non-homogeneous costs and disjunctions.
1045  int64_t ComputeLowerBound();
1047  Status status() const { return status_; }
1056  IntVar* ApplyLocks(const std::vector<int64_t>& locks);
1065  bool ApplyLocksToAllVehicles(const std::vector<std::vector<int64_t>>& locks,
1066  bool close_routes);
1071  const Assignment* const PreAssignment() const { return preassignment_; }
1072  Assignment* MutablePreAssignment() { return preassignment_; }
1076  bool WriteAssignment(const std::string& file_name) const;
1080  Assignment* ReadAssignment(const std::string& file_name);
1083  Assignment* RestoreAssignment(const Assignment& solution);
1089  Assignment* ReadAssignmentFromRoutes(
1090  const std::vector<std::vector<int64_t>>& routes,
1091  bool ignore_inactive_indices);
1108  bool RoutesToAssignment(const std::vector<std::vector<int64_t>>& routes,
1109  bool ignore_inactive_indices, bool close_routes,
1110  Assignment* const assignment) const;
1114  void AssignmentToRoutes(
1115  const Assignment& assignment,
1116  std::vector<std::vector<int64_t>>* const routes) const;
1121 #ifndef SWIG
1122  std::vector<std::vector<int64_t>> GetRoutesFromAssignment(
1123  const Assignment& assignment);
1124 #endif
1142  Assignment* CompactAssignment(const Assignment& assignment) const;
1146  Assignment* CompactAndCheckAssignment(const Assignment& assignment) const;
1148  void AddToAssignment(IntVar* const var);
1149  void AddIntervalToAssignment(IntervalVar* const interval);
1160  const Assignment* PackCumulsOfOptimizerDimensionsFromAssignment(
1161  const Assignment* original_assignment, absl::Duration duration_limit);
1162 #ifndef SWIG
1163  // TODO(user): Revisit if coordinates are added to the RoutingModel class.
1164  void SetSweepArranger(SweepArranger* sweep_arranger);
1166  SweepArranger* sweep_arranger() const;
1167 #endif
1174  CHECK(filter != nullptr);
1175  if (closed_) {
1176  LOG(WARNING) << "Model is closed, filter addition will be ignored.";
1177  }
1178  extra_filters_.push_back({filter, LocalSearchFilterManager::kRelax});
1179  extra_filters_.push_back({filter, LocalSearchFilterManager::kAccept});
1180  }
1181 
1184  int64_t Start(int vehicle) const { return starts_[vehicle]; }
1186  int64_t End(int vehicle) const { return ends_[vehicle]; }
1188  bool IsStart(int64_t index) const;
1190  bool IsEnd(int64_t index) const { return index >= Size(); }
1193  int VehicleIndex(int64_t index) const { return index_to_vehicle_[index]; }
1197  int64_t Next(const Assignment& assignment, int64_t index) const;
1199  bool IsVehicleUsed(const Assignment& assignment, int vehicle) const;
1200 
1201 #if !defined(SWIGPYTHON)
1204  const std::vector<IntVar*>& Nexts() const { return nexts_; }
1207  const std::vector<IntVar*>& VehicleVars() const { return vehicle_vars_; }
1208 #endif
1211  IntVar* NextVar(int64_t index) const { return nexts_[index]; }
1213  IntVar* ActiveVar(int64_t index) const { return active_[index]; }
1216  IntVar* ActiveVehicleVar(int vehicle) const {
1217  return vehicle_active_[vehicle];
1218  }
1221  IntVar* VehicleCostsConsideredVar(int vehicle) const {
1222  return vehicle_costs_considered_[vehicle];
1223  }
1226  IntVar* VehicleVar(int64_t index) const { return vehicle_vars_[index]; }
1228  IntVar* CostVar() const { return cost_; }
1229 
1232  int64_t GetArcCostForVehicle(int64_t from_index, int64_t to_index,
1233  int64_t vehicle) const;
1236  return costs_are_homogeneous_across_vehicles_;
1237  }
1240  int64_t GetHomogeneousCost(int64_t from_index, int64_t to_index) const {
1241  return GetArcCostForVehicle(from_index, to_index, /*vehicle=*/0);
1242  }
1245  int64_t GetArcCostForFirstSolution(int64_t from_index,
1246  int64_t to_index) const;
1253  int64_t GetArcCostForClass(int64_t from_index, int64_t to_index,
1254  int64_t /*CostClassIndex*/ cost_class_index) const;
1257  DCHECK(closed_);
1258  DCHECK_GE(vehicle, 0);
1259  DCHECK_LT(vehicle, cost_class_index_of_vehicle_.size());
1260  DCHECK_GE(cost_class_index_of_vehicle_[vehicle], 0);
1261  return cost_class_index_of_vehicle_[vehicle];
1262  }
1265  bool HasVehicleWithCostClassIndex(CostClassIndex cost_class_index) const {
1266  DCHECK(closed_);
1267  if (cost_class_index == kCostClassIndexOfZeroCost) {
1268  return has_vehicle_with_zero_cost_class_;
1269  }
1270  return cost_class_index < cost_classes_.size();
1271  }
1273  int GetCostClassesCount() const { return cost_classes_.size(); }
1276  return std::max(0, GetCostClassesCount() - 1);
1277  }
1279  DCHECK(closed_);
1280  return vehicle_class_index_of_vehicle_[vehicle];
1281  }
1283  int GetVehicleClassesCount() const { return vehicle_classes_.size(); }
1285  const std::vector<int>& GetSameVehicleIndicesOfIndex(int node) const {
1286  DCHECK(closed_);
1287  return same_vehicle_groups_[same_vehicle_group_[node]];
1288  }
1289 
1291  DCHECK(closed_);
1292  return vehicle_type_container_;
1293  }
1294 
1313  bool ArcIsMoreConstrainedThanArc(int64_t from, int64_t to1, int64_t to2);
1318  std::string DebugOutputAssignment(
1319  const Assignment& solution_assignment,
1320  const std::string& dimension_to_print) const;
1326 #ifndef SWIG
1327  std::vector<std::vector<std::pair<int64_t, int64_t>>> GetCumulBounds(
1328  const Assignment& solution_assignment, const RoutingDimension& dimension);
1329 #endif
1332  Solver* solver() const { return solver_.get(); }
1333 
1335  bool CheckLimit() {
1336  DCHECK(limit_ != nullptr);
1337  return limit_->Check();
1338  }
1339 
1341  absl::Duration RemainingTime() const {
1342  DCHECK(limit_ != nullptr);
1343  return limit_->AbsoluteSolverDeadline() - solver_->Now();
1344  }
1345 
1348  int nodes() const { return nodes_; }
1350  int vehicles() const { return vehicles_; }
1352  int64_t Size() const { return nodes_ + vehicles_ - start_end_count_; }
1353 
1356  int64_t GetNumberOfDecisionsInFirstSolution(
1357  const RoutingSearchParameters& search_parameters) const;
1358  int64_t GetNumberOfRejectsInFirstSolution(
1359  const RoutingSearchParameters& search_parameters) const;
1363  return automatic_first_solution_strategy_;
1364  }
1365 
1367  bool IsMatchingModel() const;
1368 
1369 #ifndef SWIG
1373  std::function<std::vector<operations_research::IntVar*>(RoutingModel*)>;
1374 
1375  void SetTabuVarsCallback(GetTabuVarsCallback tabu_var_callback);
1376 #endif // SWIG
1377 
1379  // TODO(user): Find a way to test and restrict the access at the same time.
1391  DecisionBuilder* MakeGuidedSlackFinalizer(
1392  const RoutingDimension* dimension,
1393  std::function<int64_t(int64_t)> initializer);
1394 #ifndef SWIG
1395  // TODO(user): MakeGreedyDescentLSOperator is too general for routing.h.
1400  static std::unique_ptr<LocalSearchOperator> MakeGreedyDescentLSOperator(
1401  std::vector<IntVar*> variables);
1402 #endif
1416  DecisionBuilder* MakeSelfDependentDimensionFinalizer(
1417  const RoutingDimension* dimension);
1418 
1419  private:
1421  enum RoutingLocalSearchOperator {
1422  RELOCATE = 0,
1423  RELOCATE_PAIR,
1424  LIGHT_RELOCATE_PAIR,
1425  RELOCATE_NEIGHBORS,
1426  EXCHANGE,
1427  EXCHANGE_PAIR,
1428  CROSS,
1429  CROSS_EXCHANGE,
1430  TWO_OPT,
1431  OR_OPT,
1432  GLOBAL_CHEAPEST_INSERTION_CLOSE_NODES_LNS,
1433  LOCAL_CHEAPEST_INSERTION_CLOSE_NODES_LNS,
1434  GLOBAL_CHEAPEST_INSERTION_PATH_LNS,
1435  LOCAL_CHEAPEST_INSERTION_PATH_LNS,
1436  RELOCATE_PATH_GLOBAL_CHEAPEST_INSERTION_INSERT_UNPERFORMED,
1437  GLOBAL_CHEAPEST_INSERTION_EXPENSIVE_CHAIN_LNS,
1438  LOCAL_CHEAPEST_INSERTION_EXPENSIVE_CHAIN_LNS,
1439  RELOCATE_EXPENSIVE_CHAIN,
1440  LIN_KERNIGHAN,
1441  TSP_OPT,
1442  MAKE_ACTIVE,
1443  RELOCATE_AND_MAKE_ACTIVE,
1444  MAKE_ACTIVE_AND_RELOCATE,
1445  MAKE_INACTIVE,
1446  MAKE_CHAIN_INACTIVE,
1447  SWAP_ACTIVE,
1448  EXTENDED_SWAP_ACTIVE,
1449  NODE_PAIR_SWAP,
1450  PATH_LNS,
1451  FULL_PATH_LNS,
1452  TSP_LNS,
1453  INACTIVE_LNS,
1454  EXCHANGE_RELOCATE_PAIR,
1455  RELOCATE_SUBTRIP,
1456  EXCHANGE_SUBTRIP,
1457  LOCAL_SEARCH_OPERATOR_COUNTER
1458  };
1459 
1463  template <typename T>
1464  struct ValuedNodes {
1465  std::vector<int64_t> indices;
1466  T value;
1467  };
1468  struct DisjunctionValues {
1469  int64_t penalty;
1470  int64_t max_cardinality;
1471  };
1472  typedef ValuedNodes<DisjunctionValues> Disjunction;
1473 
1476  struct CostCacheElement {
1482  int index;
1483  CostClassIndex cost_class_index;
1484  int64_t cost;
1485  };
1486 
1488  void Initialize();
1489  void AddNoCycleConstraintInternal();
1490  bool AddDimensionWithCapacityInternal(
1491  const std::vector<int>& evaluator_indices, int64_t slack_max,
1492  std::vector<int64_t> vehicle_capacities, bool fix_start_cumul_to_zero,
1493  const std::string& name);
1494  bool AddDimensionDependentDimensionWithVehicleCapacityInternal(
1495  const std::vector<int>& pure_transits,
1496  const std::vector<int>& dependent_transits,
1497  const RoutingDimension* base_dimension, int64_t slack_max,
1498  std::vector<int64_t> vehicle_capacities, bool fix_start_cumul_to_zero,
1499  const std::string& name);
1500  bool InitializeDimensionInternal(
1501  const std::vector<int>& evaluator_indices,
1502  const std::vector<int>& state_dependent_evaluator_indices,
1503  int64_t slack_max, bool fix_start_cumul_to_zero,
1504  RoutingDimension* dimension);
1505  DimensionIndex GetDimensionIndex(const std::string& dimension_name) const;
1506 
1534  void StoreDimensionCumulOptimizers(const RoutingSearchParameters& parameters);
1535 
1536  void ComputeCostClasses(const RoutingSearchParameters& parameters);
1537  void ComputeVehicleClasses();
1545  void ComputeVehicleTypes();
1555  void FinalizeVisitTypes();
1556  // Called by FinalizeVisitTypes() to setup topologically_sorted_visit_types_.
1557  void TopologicallySortVisitTypes();
1558  int64_t GetArcCostForClassInternal(int64_t from_index, int64_t to_index,
1559  CostClassIndex cost_class_index) const;
1560  void AppendHomogeneousArcCosts(const RoutingSearchParameters& parameters,
1561  int node_index,
1562  std::vector<IntVar*>* cost_elements);
1563  void AppendArcCosts(const RoutingSearchParameters& parameters, int node_index,
1564  std::vector<IntVar*>* cost_elements);
1565  Assignment* DoRestoreAssignment();
1566  static const CostClassIndex kCostClassIndexOfZeroCost;
1567  int64_t SafeGetCostClassInt64OfVehicle(int64_t vehicle) const {
1568  DCHECK_LT(0, vehicles_);
1569  return (vehicle >= 0 ? GetCostClassIndexOfVehicle(vehicle)
1570  : kCostClassIndexOfZeroCost)
1571  .value();
1572  }
1573  int64_t GetDimensionTransitCostSum(int64_t i, int64_t j,
1574  const CostClass& cost_class) const;
1576  IntVar* CreateDisjunction(DisjunctionIndex disjunction);
1578  void AddPickupAndDeliverySetsInternal(const std::vector<int64_t>& pickups,
1579  const std::vector<int64_t>& deliveries);
1582  IntVar* CreateSameVehicleCost(int vehicle_index);
1585  int FindNextActive(int index, const std::vector<int64_t>& indices) const;
1586 
1589  bool RouteCanBeUsedByVehicle(const Assignment& assignment, int start_index,
1590  int vehicle) const;
1598  bool ReplaceUnusedVehicle(int unused_vehicle, int active_vehicle,
1599  Assignment* compact_assignment) const;
1600 
1601  void QuietCloseModel();
1602  void QuietCloseModelWithParameters(
1603  const RoutingSearchParameters& parameters) {
1604  if (!closed_) {
1605  CloseModelWithParameters(parameters);
1606  }
1607  }
1608 
1610  bool SolveMatchingModel(Assignment* assignment,
1611  const RoutingSearchParameters& parameters);
1612 #ifndef SWIG
1614  bool AppendAssignmentIfFeasible(
1615  const Assignment& assignment,
1616  std::vector<std::unique_ptr<Assignment>>* assignments);
1617 #endif
1619  void LogSolution(const RoutingSearchParameters& parameters,
1620  const std::string& description, int64_t solution_cost,
1621  int64_t start_time_ms);
1624  Assignment* CompactAssignmentInternal(const Assignment& assignment,
1625  bool check_compact_assignment) const;
1630  std::string FindErrorInSearchParametersForModel(
1631  const RoutingSearchParameters& search_parameters) const;
1633  void SetupSearch(const RoutingSearchParameters& search_parameters);
1635  // TODO(user): Document each auxiliary method.
1636  Assignment* GetOrCreateAssignment();
1637  Assignment* GetOrCreateTmpAssignment();
1638  RegularLimit* GetOrCreateLimit();
1639  RegularLimit* GetOrCreateLocalSearchLimit();
1640  RegularLimit* GetOrCreateLargeNeighborhoodSearchLimit();
1641  RegularLimit* GetOrCreateFirstSolutionLargeNeighborhoodSearchLimit();
1642  LocalSearchOperator* CreateInsertionOperator();
1643  LocalSearchOperator* CreateMakeInactiveOperator();
1644  template <class T>
1645  LocalSearchOperator* CreateCPOperator(const T& operator_factory) {
1646  return operator_factory(solver_.get(), nexts_,
1647  CostsAreHomogeneousAcrossVehicles()
1648  ? std::vector<IntVar*>()
1649  : vehicle_vars_,
1650  vehicle_start_class_callback_);
1651  }
1652  template <class T>
1653  LocalSearchOperator* CreateCPOperator() {
1654  return CreateCPOperator(absl::bind_front(MakeLocalSearchOperator<T>));
1655  }
1656  template <class T, class Arg>
1657  LocalSearchOperator* CreateOperator(const Arg& arg) {
1658  return solver_->RevAlloc(new T(nexts_,
1659  CostsAreHomogeneousAcrossVehicles()
1660  ? std::vector<IntVar*>()
1661  : vehicle_vars_,
1662  vehicle_start_class_callback_, arg));
1663  }
1664  template <class T>
1665  LocalSearchOperator* CreatePairOperator() {
1666  return CreateOperator<T>(pickup_delivery_pairs_);
1667  }
1668  void CreateNeighborhoodOperators(const RoutingSearchParameters& parameters);
1669  LocalSearchOperator* ConcatenateOperators(
1670  const RoutingSearchParameters& search_parameters,
1671  const std::vector<LocalSearchOperator*>& operators) const;
1672  LocalSearchOperator* GetNeighborhoodOperators(
1673  const RoutingSearchParameters& search_parameters) const;
1674  std::vector<LocalSearchFilterManager::FilterEvent>
1675  GetOrCreateLocalSearchFilters(const RoutingSearchParameters& parameters,
1676  bool filter_cost = true);
1677  LocalSearchFilterManager* GetOrCreateLocalSearchFilterManager(
1678  const RoutingSearchParameters& parameters);
1679  std::vector<LocalSearchFilterManager::FilterEvent>
1680  GetOrCreateFeasibilityFilters(const RoutingSearchParameters& parameters);
1681  LocalSearchFilterManager* GetOrCreateFeasibilityFilterManager(
1682  const RoutingSearchParameters& parameters);
1683  LocalSearchFilterManager* GetOrCreateStrongFeasibilityFilterManager(
1684  const RoutingSearchParameters& parameters);
1685  DecisionBuilder* CreateSolutionFinalizer(SearchLimit* lns_limit);
1686  DecisionBuilder* CreateFinalizerForMinimizedAndMaximizedVariables();
1687  void CreateFirstSolutionDecisionBuilders(
1688  const RoutingSearchParameters& search_parameters);
1689  DecisionBuilder* GetFirstSolutionDecisionBuilder(
1690  const RoutingSearchParameters& search_parameters) const;
1691  IntVarFilteredDecisionBuilder* GetFilteredFirstSolutionDecisionBuilderOrNull(
1692  const RoutingSearchParameters& parameters) const;
1693  LocalSearchPhaseParameters* CreateLocalSearchParameters(
1694  const RoutingSearchParameters& search_parameters);
1695  DecisionBuilder* CreateLocalSearchDecisionBuilder(
1696  const RoutingSearchParameters& search_parameters);
1697  void SetupDecisionBuilders(const RoutingSearchParameters& search_parameters);
1698  void SetupMetaheuristics(const RoutingSearchParameters& search_parameters);
1699  void SetupAssignmentCollector(
1700  const RoutingSearchParameters& search_parameters);
1701  void SetupTrace(const RoutingSearchParameters& search_parameters);
1702  void SetupImprovementLimit(const RoutingSearchParameters& search_parameters);
1703  void SetupSearchMonitors(const RoutingSearchParameters& search_parameters);
1704  bool UsesLightPropagation(
1705  const RoutingSearchParameters& search_parameters) const;
1706  GetTabuVarsCallback tabu_var_callback_;
1707 
1708  // Detects implicit pickup delivery pairs. These pairs are
1709  // non-pickup/delivery pairs for which there exists a unary dimension such
1710  // that the demand d of the implicit pickup is positive and the demand of the
1711  // implicit delivery is equal to -d.
1712  void DetectImplicitPickupAndDeliveries();
1713 
1714  int GetVehicleStartClass(int64_t start) const;
1715 
1716  void InitSameVehicleGroups(int number_of_groups) {
1717  same_vehicle_group_.assign(Size(), 0);
1718  same_vehicle_groups_.assign(number_of_groups, {});
1719  }
1720  void SetSameVehicleGroup(int index, int group) {
1721  same_vehicle_group_[index] = group;
1722  same_vehicle_groups_[group].push_back(index);
1723  }
1724 
1726  std::unique_ptr<Solver> solver_;
1727  int nodes_;
1728  int vehicles_;
1729  int max_active_vehicles_;
1730  Constraint* no_cycle_constraint_ = nullptr;
1732  std::vector<IntVar*> nexts_;
1733  std::vector<IntVar*> vehicle_vars_;
1734  std::vector<IntVar*> active_;
1735  // The following vectors are indexed by vehicle index.
1736  std::vector<IntVar*> vehicle_active_;
1737  std::vector<IntVar*> vehicle_costs_considered_;
1742  std::vector<IntVar*> is_bound_to_end_;
1743  mutable RevSwitch is_bound_to_end_ct_added_;
1745  absl::flat_hash_map<std::string, DimensionIndex> dimension_name_to_index_;
1747  // clang-format off
1751  std::vector<std::unique_ptr<GlobalDimensionCumulOptimizer> >
1752  global_dimension_optimizers_;
1753  absl::StrongVector<DimensionIndex, int> global_optimizer_index_;
1754  std::vector<std::unique_ptr<LocalDimensionCumulOptimizer> >
1755  local_dimension_optimizers_;
1756  std::vector<std::unique_ptr<LocalDimensionCumulOptimizer> >
1757  local_dimension_mp_optimizers_;
1758  // clang-format off
1759  absl::StrongVector<DimensionIndex, int> local_optimizer_index_;
1760  std::string primary_constrained_dimension_;
1762  IntVar* cost_ = nullptr;
1763  std::vector<int> vehicle_to_transit_cost_;
1764  std::vector<int64_t> fixed_cost_of_vehicle_;
1765  std::vector<CostClassIndex> cost_class_index_of_vehicle_;
1766  bool has_vehicle_with_zero_cost_class_;
1767  std::vector<int64_t> linear_cost_factor_of_vehicle_;
1768  std::vector<int64_t> quadratic_cost_factor_of_vehicle_;
1769  bool vehicle_amortized_cost_factors_set_;
1780  std::vector<bool> consider_empty_route_costs_;
1781 #ifndef SWIG
1783 #endif // SWIG
1784  bool costs_are_homogeneous_across_vehicles_;
1785  bool cache_callbacks_;
1786  mutable std::vector<CostCacheElement> cost_cache_;
1787  std::vector<VehicleClassIndex> vehicle_class_index_of_vehicle_;
1788 #ifndef SWIG
1790 #endif // SWIG
1791  VehicleTypeContainer vehicle_type_container_;
1792  std::function<int(int64_t)> vehicle_start_class_callback_;
1795  std::vector<std::vector<DisjunctionIndex> > index_to_disjunctions_;
1797  std::vector<ValuedNodes<int64_t> > same_vehicle_costs_;
1799 #ifndef SWIG
1800  std::vector<absl::flat_hash_set<int>> allowed_vehicles_;
1801 #endif // SWIG
1803  IndexPairs pickup_delivery_pairs_;
1804  IndexPairs implicit_pickup_delivery_pairs_without_alternatives_;
1805  std::vector<std::pair<DisjunctionIndex, DisjunctionIndex> >
1806  pickup_delivery_disjunctions_;
1807  // clang-format off
1808  // If node_index is a pickup, index_to_pickup_index_pairs_[node_index] is the
1809  // vector of pairs {pair_index, pickup_index} such that
1810  // (pickup_delivery_pairs_[pair_index].first)[pickup_index] == node_index
1811  std::vector<std::vector<std::pair<int, int> > > index_to_pickup_index_pairs_;
1812  // Same as above for deliveries.
1813  std::vector<std::vector<std::pair<int, int> > >
1814  index_to_delivery_index_pairs_;
1815  // clang-format on
1816  std::vector<PickupAndDeliveryPolicy> vehicle_pickup_delivery_policy_;
1817  // Same vehicle group to which a node belongs.
1818  std::vector<int> same_vehicle_group_;
1819  // Same vehicle node groups.
1820  std::vector<std::vector<int>> same_vehicle_groups_;
1821  // Node visit types
1822  // Variable index to visit type index.
1823  std::vector<int> index_to_visit_type_;
1824  // Variable index to VisitTypePolicy.
1825  std::vector<VisitTypePolicy> index_to_type_policy_;
1826  // clang-format off
1827  std::vector<std::vector<int> > single_nodes_of_type_;
1828  std::vector<std::vector<int> > pair_indices_of_type_;
1829 
1830  std::vector<absl::flat_hash_set<int> >
1831  hard_incompatible_types_per_type_index_;
1832  bool has_hard_type_incompatibilities_;
1833  std::vector<absl::flat_hash_set<int> >
1834  temporal_incompatible_types_per_type_index_;
1835  bool has_temporal_type_incompatibilities_;
1836 
1837  std::vector<std::vector<absl::flat_hash_set<int> > >
1838  same_vehicle_required_type_alternatives_per_type_index_;
1839  bool has_same_vehicle_type_requirements_;
1840  std::vector<std::vector<absl::flat_hash_set<int> > >
1841  required_type_alternatives_when_adding_type_index_;
1842  std::vector<std::vector<absl::flat_hash_set<int> > >
1843  required_type_alternatives_when_removing_type_index_;
1844  bool has_temporal_type_requirements_;
1845  absl::flat_hash_map</*type*/int, absl::flat_hash_set<VisitTypePolicy> >
1846  trivially_infeasible_visit_types_to_policies_;
1847 
1848  // Visit types sorted topologically based on required-->dependent requirement
1849  // arcs between the types (if the requirement/dependency graph is acyclic).
1850  // Visit types of the same topological level are sorted in each sub-vector
1851  // by decreasing requirement "tightness", computed as the pair of the two
1852  // following criteria:
1853  //
1854  // 1) How highly *dependent* this type is, determined by
1855  // (total number of required alternative sets for that type)
1856  // / (average number of types in the required alternative sets)
1857  // 2) How highly *required* this type t is, computed as
1858  // SUM_{S required set containing t} ( 1 / |S| ),
1859  // i.e. the sum of reverse number of elements of all required sets
1860  // containing the type t.
1861  //
1862  // The higher these two numbers, the tighter the type is wrt requirements.
1863  std::vector<std::vector<int> > topologically_sorted_visit_types_;
1864  // clang-format on
1865  int num_visit_types_;
1866  // Two indices are equivalent if they correspond to the same node (as given
1867  // to the constructors taking a RoutingIndexManager).
1868  std::vector<int> index_to_equivalence_class_;
1869  std::vector<int> index_to_vehicle_;
1870  std::vector<int64_t> starts_;
1871  std::vector<int64_t> ends_;
1872  // TODO(user): b/62478706 Once the port is done, this shouldn't be needed
1873  // anymore.
1874  RoutingIndexManager manager_;
1875  int start_end_count_;
1876  // Model status
1877  bool closed_ = false;
1878  Status status_ = ROUTING_NOT_SOLVED;
1879  bool enable_deep_serialization_ = true;
1880 
1881  // Search data
1882  std::vector<DecisionBuilder*> first_solution_decision_builders_;
1883  std::vector<IntVarFilteredDecisionBuilder*>
1884  first_solution_filtered_decision_builders_;
1885  Solver::IndexEvaluator2 first_solution_evaluator_;
1886  FirstSolutionStrategy::Value automatic_first_solution_strategy_ =
1887  FirstSolutionStrategy::UNSET;
1888  std::vector<LocalSearchOperator*> local_search_operators_;
1889  std::vector<SearchMonitor*> monitors_;
1890  SolutionCollector* collect_assignments_ = nullptr;
1891  SolutionCollector* collect_one_assignment_ = nullptr;
1892  SolutionCollector* packed_dimensions_assignment_collector_ = nullptr;
1893  DecisionBuilder* solve_db_ = nullptr;
1894  DecisionBuilder* improve_db_ = nullptr;
1895  DecisionBuilder* restore_assignment_ = nullptr;
1896  DecisionBuilder* restore_tmp_assignment_ = nullptr;
1897  Assignment* assignment_ = nullptr;
1898  Assignment* preassignment_ = nullptr;
1899  Assignment* tmp_assignment_ = nullptr;
1900  std::vector<IntVar*> extra_vars_;
1901  std::vector<IntervalVar*> extra_intervals_;
1902  std::vector<LocalSearchOperator*> extra_operators_;
1903  LocalSearchFilterManager* local_search_filter_manager_ = nullptr;
1904  LocalSearchFilterManager* feasibility_filter_manager_ = nullptr;
1905  LocalSearchFilterManager* strong_feasibility_filter_manager_ = nullptr;
1906  std::vector<LocalSearchFilterManager::FilterEvent> extra_filters_;
1907 #ifndef SWIG
1908  std::vector<std::pair<IntVar*, int64_t>> finalizer_variable_cost_pairs_;
1909  std::vector<std::pair<IntVar*, int64_t>> finalizer_variable_target_pairs_;
1910  absl::flat_hash_map<IntVar*, int> finalizer_variable_cost_index_;
1911  absl::flat_hash_set<IntVar*> finalizer_variable_target_set_;
1912  std::unique_ptr<SweepArranger> sweep_arranger_;
1913 #endif
1914 
1915  RegularLimit* limit_ = nullptr;
1916  RegularLimit* ls_limit_ = nullptr;
1917  RegularLimit* lns_limit_ = nullptr;
1918  RegularLimit* first_solution_lns_limit_ = nullptr;
1919 
1920  typedef std::pair<int64_t, int64_t> CacheKey;
1921  typedef absl::flat_hash_map<CacheKey, int64_t> TransitCallbackCache;
1922  typedef absl::flat_hash_map<CacheKey, StateDependentTransit>
1923  StateDependentTransitCallbackCache;
1924 
1925  std::vector<TransitCallback1> unary_transit_evaluators_;
1926  std::vector<TransitCallback2> transit_evaluators_;
1927  // The following vector stores a boolean per transit_evaluator_, indicating
1928  // whether the transits are all positive.
1929  // is_transit_evaluator_positive_ will be set to true only when registering a
1930  // callback via RegisterPositiveTransitCallback(), and to false otherwise.
1931  // The actual positivity of the transit values will only be checked in debug
1932  // mode, when calling RegisterPositiveTransitCallback().
1933  // Therefore, RegisterPositiveTransitCallback() should only be called when the
1934  // transits are known to be positive, as the positivity of a callback will
1935  // allow some improvements in the solver, but will entail in errors if the
1936  // transits are falsely assumed positive.
1937  std::vector<bool> is_transit_evaluator_positive_;
1938  std::vector<VariableIndexEvaluator2> state_dependent_transit_evaluators_;
1939  std::vector<std::unique_ptr<StateDependentTransitCallbackCache>>
1940  state_dependent_transit_evaluators_cache_;
1941 
1942  friend class RoutingDimension;
1944 
1946 };
1947 
1950  public:
1952  static const char kLightElement[];
1953  static const char kLightElement2[];
1954  static const char kRemoveValues[];
1955 };
1956 
1957 #if !defined(SWIG)
1961  public:
1967  struct Tasks {
1968  int num_chain_tasks = 0;
1969  std::vector<int64_t> start_min;
1970  std::vector<int64_t> start_max;
1971  std::vector<int64_t> duration_min;
1972  std::vector<int64_t> duration_max;
1973  std::vector<int64_t> end_min;
1974  std::vector<int64_t> end_max;
1975  std::vector<bool> is_preemptible;
1976  std::vector<const SortedDisjointIntervalList*> forbidden_intervals;
1977  std::vector<std::pair<int64_t, int64_t>> distance_duration;
1978  int64_t span_min = 0;
1979  int64_t span_max = kint64max;
1980 
1981  void Clear() {
1982  start_min.clear();
1983  start_max.clear();
1984  duration_min.clear();
1985  duration_max.clear();
1986  end_min.clear();
1987  end_max.clear();
1988  is_preemptible.clear();
1989  forbidden_intervals.clear();
1990  distance_duration.clear();
1991  span_min = 0;
1992  span_max = kint64max;
1993  num_chain_tasks = 0;
1994  }
1995  };
1996 
1999  bool Propagate(Tasks* tasks);
2000 
2002  bool Precedences(Tasks* tasks);
2005  bool MirrorTasks(Tasks* tasks);
2007  bool EdgeFinding(Tasks* tasks);
2010  bool DetectablePrecedencesWithChain(Tasks* tasks);
2012  bool ForbiddenIntervals(Tasks* tasks);
2014  bool DistanceDuration(Tasks* tasks);
2017  bool ChainSpanMin(Tasks* tasks);
2022  bool ChainSpanMinDynamic(Tasks* tasks);
2023 
2024  private:
2027  sat::ThetaLambdaTree<int64_t> theta_lambda_tree_;
2029  std::vector<int> tasks_by_start_min_;
2030  std::vector<int> tasks_by_end_max_;
2031  std::vector<int> event_of_task_;
2032  std::vector<int> nonchain_tasks_by_start_max_;
2034  std::vector<int64_t> total_duration_before_;
2035 };
2036 
2038  std::vector<int64_t> min_travels;
2039  std::vector<int64_t> max_travels;
2040  std::vector<int64_t> pre_travels;
2041  std::vector<int64_t> post_travels;
2042 };
2043 
2044 void AppendTasksFromPath(const std::vector<int64_t>& path,
2045  const TravelBounds& travel_bounds,
2046  const RoutingDimension& dimension,
2048 void AppendTasksFromIntervals(const std::vector<IntervalVar*>& intervals,
2050 void FillPathEvaluation(const std::vector<int64_t>& path,
2051  const RoutingModel::TransitCallback2& evaluator,
2052  std::vector<int64_t>* values);
2053 void FillTravelBoundsOfVehicle(int vehicle, const std::vector<int64_t>& path,
2054  const RoutingDimension& dimension,
2055  TravelBounds* travel_bounds);
2056 #endif // !defined(SWIG)
2057 
2069  public:
2070  explicit GlobalVehicleBreaksConstraint(const RoutingDimension* dimension);
2071  std::string DebugString() const override {
2072  return "GlobalVehicleBreaksConstraint";
2073  }
2074 
2075  void Post() override;
2076  void InitialPropagate() override;
2077 
2078  private:
2079  void PropagateNode(int node);
2080  void PropagateVehicle(int vehicle);
2081  void PropagateMaxBreakDistance(int vehicle);
2082 
2083  const RoutingModel* model_;
2084  const RoutingDimension* const dimension_;
2085  std::vector<Demon*> vehicle_demons_;
2086  std::vector<int64_t> path_;
2087 
2092  void FillPartialPathOfVehicle(int vehicle);
2093  void FillPathTravels(const std::vector<int64_t>& path);
2094 
2105  class TaskTranslator {
2106  public:
2107  TaskTranslator(IntVar* start, int64_t before_start, int64_t after_start)
2108  : start_(start),
2109  before_start_(before_start),
2110  after_start_(after_start) {}
2111  explicit TaskTranslator(IntervalVar* interval) : interval_(interval) {}
2112  TaskTranslator() {}
2113 
2114  void SetStartMin(int64_t value) {
2115  if (start_ != nullptr) {
2116  start_->SetMin(CapAdd(before_start_, value));
2117  } else if (interval_ != nullptr) {
2118  interval_->SetStartMin(value);
2119  }
2120  }
2121  void SetStartMax(int64_t value) {
2122  if (start_ != nullptr) {
2123  start_->SetMax(CapAdd(before_start_, value));
2124  } else if (interval_ != nullptr) {
2125  interval_->SetStartMax(value);
2126  }
2127  }
2128  void SetDurationMin(int64_t value) {
2129  if (interval_ != nullptr) {
2130  interval_->SetDurationMin(value);
2131  }
2132  }
2133  void SetEndMin(int64_t value) {
2134  if (start_ != nullptr) {
2135  start_->SetMin(CapSub(value, after_start_));
2136  } else if (interval_ != nullptr) {
2137  interval_->SetEndMin(value);
2138  }
2139  }
2140  void SetEndMax(int64_t value) {
2141  if (start_ != nullptr) {
2142  start_->SetMax(CapSub(value, after_start_));
2143  } else if (interval_ != nullptr) {
2144  interval_->SetEndMax(value);
2145  }
2146  }
2147 
2148  private:
2149  IntVar* start_ = nullptr;
2150  int64_t before_start_;
2151  int64_t after_start_;
2152  IntervalVar* interval_ = nullptr;
2153  };
2154 
2156  std::vector<TaskTranslator> task_translators_;
2157 
2159  DisjunctivePropagator disjunctive_propagator_;
2160  DisjunctivePropagator::Tasks tasks_;
2161 
2163  TravelBounds travel_bounds_;
2164 };
2165 
2167  public:
2168  explicit TypeRegulationsChecker(const RoutingModel& model);
2170 
2171  bool CheckVehicle(int vehicle,
2172  const std::function<int64_t(int64_t)>& next_accessor);
2173 
2174  protected:
2175 #ifndef SWIG
2177 #endif // SWIG
2178 
2183  int num_type_added_to_vehicle = 0;
2189  int num_type_removed_from_vehicle = 0;
2194  int position_of_last_type_on_vehicle_up_to_visit = -1;
2195  };
2196 
2201  bool TypeOccursOnRoute(int type) const;
2208  bool TypeCurrentlyOnRoute(int type, int pos) const;
2209 
2210  void InitializeCheck(int vehicle,
2211  const std::function<int64_t(int64_t)>& next_accessor);
2212  virtual void OnInitializeCheck() {}
2213  virtual bool HasRegulationsToCheck() const = 0;
2214  virtual bool CheckTypeRegulations(int type, VisitTypePolicy policy,
2215  int pos) = 0;
2216  virtual bool FinalizeCheck() const { return true; }
2217 
2219 
2220  private:
2221  std::vector<TypePolicyOccurrence> occurrences_of_type_;
2222  std::vector<int64_t> current_route_visits_;
2223 };
2224 
2227  public:
2229  bool check_hard_incompatibilities);
2231 
2232  private:
2233  bool HasRegulationsToCheck() const override;
2234  bool CheckTypeRegulations(int type, VisitTypePolicy policy, int pos) override;
2238  bool check_hard_incompatibilities_;
2239 };
2240 
2243  public:
2247 
2248  private:
2249  bool HasRegulationsToCheck() const override;
2250  void OnInitializeCheck() override {
2251  types_with_same_vehicle_requirements_on_route_.clear();
2252  }
2253  // clang-format off
2256  bool CheckRequiredTypesCurrentlyOnRoute(
2257  const std::vector<absl::flat_hash_set<int> >& required_type_alternatives,
2258  int pos);
2259  // clang-format on
2260  bool CheckTypeRegulations(int type, VisitTypePolicy policy, int pos) override;
2261  bool FinalizeCheck() const override;
2262 
2263  absl::flat_hash_set<int> types_with_same_vehicle_requirements_on_route_;
2264 };
2265 
2307  public:
2308  explicit TypeRegulationsConstraint(const RoutingModel& model);
2309 
2310  void Post() override;
2311  void InitialPropagate() override;
2312 
2313  private:
2314  void PropagateNodeRegulations(int node);
2315  void CheckRegulationsOnVehicle(int vehicle);
2316 
2317  const RoutingModel& model_;
2318  TypeIncompatibilityChecker incompatibility_checker_;
2319  TypeRequirementChecker requirement_checker_;
2320  std::vector<Demon*> vehicle_demons_;
2321 };
2322 #if !defined SWIG
2336  public:
2337  struct BoundCost {
2338  int64_t bound;
2339  int64_t cost;
2340  };
2341  SimpleBoundCosts(int num_bounds, BoundCost default_bound_cost)
2342  : bound_costs_(num_bounds, default_bound_cost) {}
2343  BoundCost& bound_cost(int element) { return bound_costs_[element]; }
2344  BoundCost bound_cost(int element) const { return bound_costs_[element]; }
2345  int Size() { return bound_costs_.size(); }
2348 
2349  private:
2350  std::vector<BoundCost> bound_costs_;
2351 };
2352 #endif // !defined SWIG
2353 
2371 // TODO(user): Break constraints need to know the service time of nodes
2375  public:
2376  ~RoutingDimension();
2378  RoutingModel* model() const { return model_; }
2382  int64_t GetTransitValue(int64_t from_index, int64_t to_index,
2383  int64_t vehicle) const;
2386  int64_t GetTransitValueFromClass(int64_t from_index, int64_t to_index,
2387  int64_t vehicle_class) const {
2388  return model_->TransitCallback(class_evaluators_[vehicle_class])(from_index,
2389  to_index);
2390  }
2393  IntVar* CumulVar(int64_t index) const { return cumuls_[index]; }
2394  IntVar* TransitVar(int64_t index) const { return transits_[index]; }
2395  IntVar* FixedTransitVar(int64_t index) const {
2396  return fixed_transits_[index];
2397  }
2398  IntVar* SlackVar(int64_t index) const { return slacks_[index]; }
2399 
2400 #if !defined(SWIGPYTHON)
2403  const std::vector<IntVar*>& cumuls() const { return cumuls_; }
2404  const std::vector<IntVar*>& fixed_transits() const { return fixed_transits_; }
2405  const std::vector<IntVar*>& transits() const { return transits_; }
2406  const std::vector<IntVar*>& slacks() const { return slacks_; }
2407 #if !defined(SWIGCSHARP) && !defined(SWIGJAVA)
2409  const std::vector<SortedDisjointIntervalList>& forbidden_intervals() const {
2410  return forbidden_intervals_;
2411  }
2413  SortedDisjointIntervalList GetAllowedIntervalsInRange(
2414  int64_t index, int64_t min_value, int64_t max_value) const;
2418  int64_t min_value) const {
2419  DCHECK_LT(index, forbidden_intervals_.size());
2420  const SortedDisjointIntervalList& forbidden_intervals =
2421  forbidden_intervals_[index];
2422  const auto first_forbidden_interval_it =
2423  forbidden_intervals.FirstIntervalGreaterOrEqual(min_value);
2424  if (first_forbidden_interval_it != forbidden_intervals.end() &&
2425  min_value >= first_forbidden_interval_it->start) {
2427  return CapAdd(first_forbidden_interval_it->end, 1);
2428  }
2430  return min_value;
2431  }
2437  int64_t max_value) const {
2438  DCHECK_LT(index, forbidden_intervals_.size());
2439  const SortedDisjointIntervalList& forbidden_intervals =
2440  forbidden_intervals_[index];
2441  const auto last_forbidden_interval_it =
2442  forbidden_intervals.LastIntervalLessOrEqual(max_value);
2443  if (last_forbidden_interval_it != forbidden_intervals.end() &&
2444  max_value <= last_forbidden_interval_it->end) {
2446  return CapSub(last_forbidden_interval_it->start, 1);
2447  }
2449  return max_value;
2450  }
2452  const std::vector<int64_t>& vehicle_capacities() const {
2453  return vehicle_capacities_;
2454  }
2458  return model_->TransitCallback(
2459  class_evaluators_[vehicle_to_class_[vehicle]]);
2460  }
2465  int vehicle) const {
2466  return model_->UnaryTransitCallbackOrNull(
2467  class_evaluators_[vehicle_to_class_[vehicle]]);
2468  }
2471  bool AreVehicleTransitsPositive(int vehicle) const {
2472  return model()->is_transit_evaluator_positive_
2473  [class_evaluators_[vehicle_to_class_[vehicle]]];
2474  }
2475  int vehicle_to_class(int vehicle) const { return vehicle_to_class_[vehicle]; }
2476 #endif
2477 #endif
2481  void SetSpanUpperBoundForVehicle(int64_t upper_bound, int vehicle);
2488  void SetSpanCostCoefficientForVehicle(int64_t coefficient, int vehicle);
2489  void SetSpanCostCoefficientForAllVehicles(int64_t coefficient);
2496  void SetGlobalSpanCostCoefficient(int64_t coefficient);
2497 
2498 #ifndef SWIG
2503  void SetCumulVarPiecewiseLinearCost(int64_t index,
2504  const PiecewiseLinearFunction& cost);
2507  bool HasCumulVarPiecewiseLinearCost(int64_t index) const;
2510  const PiecewiseLinearFunction* GetCumulVarPiecewiseLinearCost(
2511  int64_t index) const;
2512 #endif
2513 
2522  void SetCumulVarSoftUpperBound(int64_t index, int64_t upper_bound,
2523  int64_t coefficient);
2526  bool HasCumulVarSoftUpperBound(int64_t index) const;
2530  int64_t GetCumulVarSoftUpperBound(int64_t index) const;
2534  int64_t GetCumulVarSoftUpperBoundCoefficient(int64_t index) const;
2535 
2545  void SetCumulVarSoftLowerBound(int64_t index, int64_t lower_bound,
2546  int64_t coefficient);
2549  bool HasCumulVarSoftLowerBound(int64_t index) const;
2553  int64_t GetCumulVarSoftLowerBound(int64_t index) const;
2557  int64_t GetCumulVarSoftLowerBoundCoefficient(int64_t index) const;
2573  // TODO(user): Remove if !defined when routing.i is repaired.
2574 #if !defined(SWIGPYTHON)
2575  void SetBreakIntervalsOfVehicle(std::vector<IntervalVar*> breaks, int vehicle,
2576  int pre_travel_evaluator,
2577  int post_travel_evaluator);
2578 #endif // !defined(SWIGPYTHON)
2579 
2581  void SetBreakIntervalsOfVehicle(std::vector<IntervalVar*> breaks, int vehicle,
2582  std::vector<int64_t> node_visit_transits);
2583 
2588  void SetBreakDistanceDurationOfVehicle(int64_t distance, int64_t duration,
2589  int vehicle);
2592  void InitializeBreaks();
2594  bool HasBreakConstraints() const;
2595 #if !defined(SWIGPYTHON)
2598  void SetBreakIntervalsOfVehicle(
2599  std::vector<IntervalVar*> breaks, int vehicle,
2600  std::vector<int64_t> node_visit_transits,
2601  std::function<int64_t(int64_t, int64_t)> delays);
2602 
2604  const std::vector<IntervalVar*>& GetBreakIntervalsOfVehicle(
2605  int vehicle) const;
2608  // clang-format off
2609  const std::vector<std::pair<int64_t, int64_t> >&
2610  GetBreakDistanceDurationOfVehicle(int vehicle) const;
2611  // clang-format on
2612 #endif
2613  int GetPreTravelEvaluatorOfVehicle(int vehicle) const;
2614  int GetPostTravelEvaluatorOfVehicle(int vehicle) const;
2615 
2617  const RoutingDimension* base_dimension() const { return base_dimension_; }
2625  int64_t ShortestTransitionSlack(int64_t node) const;
2626 
2628  const std::string& name() const { return name_; }
2629 
2631 #ifndef SWIG
2633  return path_precedence_graph_;
2634  }
2635 #endif // SWIG
2636 
2646  typedef std::function<int64_t(int, int)> PickupToDeliveryLimitFunction;
2647 
2648  void SetPickupToDeliveryLimitFunctionForPair(
2649  PickupToDeliveryLimitFunction limit_function, int pair_index);
2650 
2651  bool HasPickupToDeliveryLimits() const;
2652 #ifndef SWIG
2653  int64_t GetPickupToDeliveryLimitForPair(int pair_index, int pickup,
2654  int delivery) const;
2655 
2657  int64_t first_node;
2658  int64_t second_node;
2659  int64_t offset;
2660  };
2661 
2663  node_precedences_.push_back(precedence);
2664  }
2665  const std::vector<NodePrecedence>& GetNodePrecedences() const {
2666  return node_precedences_;
2667  }
2668 #endif // SWIG
2669 
2670  void AddNodePrecedence(int64_t first_node, int64_t second_node,
2671  int64_t offset) {
2672  AddNodePrecedence({first_node, second_node, offset});
2673  }
2674 
2675  int64_t GetSpanUpperBoundForVehicle(int vehicle) const {
2676  return vehicle_span_upper_bounds_[vehicle];
2677  }
2678 #ifndef SWIG
2679  const std::vector<int64_t>& vehicle_span_upper_bounds() const {
2680  return vehicle_span_upper_bounds_;
2681  }
2682 #endif // SWIG
2683  int64_t GetSpanCostCoefficientForVehicle(int vehicle) const {
2684  return vehicle_span_cost_coefficients_[vehicle];
2685  }
2686 #ifndef SWIG
2687  const std::vector<int64_t>& vehicle_span_cost_coefficients() const {
2688  return vehicle_span_cost_coefficients_;
2689  }
2690 #endif // SWIG
2692  return global_span_cost_coefficient_;
2693  }
2694 
2695  int64_t GetGlobalOptimizerOffset() const {
2696  DCHECK_GE(global_optimizer_offset_, 0);
2697  return global_optimizer_offset_;
2698  }
2699  int64_t GetLocalOptimizerOffsetForVehicle(int vehicle) const {
2700  if (vehicle >= local_optimizer_offset_for_vehicle_.size()) {
2701  return 0;
2702  }
2703  DCHECK_GE(local_optimizer_offset_for_vehicle_[vehicle], 0);
2704  return local_optimizer_offset_for_vehicle_[vehicle];
2705  }
2706 #if !defined SWIG
2710  int vehicle) {
2711  if (!HasSoftSpanUpperBounds()) {
2712  vehicle_soft_span_upper_bound_ = absl::make_unique<SimpleBoundCosts>(
2713  model_->vehicles(), SimpleBoundCosts::BoundCost{kint64max, 0});
2714  }
2715  vehicle_soft_span_upper_bound_->bound_cost(vehicle) = bound_cost;
2716  }
2717  bool HasSoftSpanUpperBounds() const {
2718  return vehicle_soft_span_upper_bound_ != nullptr;
2719  }
2721  int vehicle) const {
2722  DCHECK(HasSoftSpanUpperBounds());
2723  return vehicle_soft_span_upper_bound_->bound_cost(vehicle);
2724  }
2728  SimpleBoundCosts::BoundCost bound_cost, int vehicle) {
2729  if (!HasQuadraticCostSoftSpanUpperBounds()) {
2730  vehicle_quadratic_cost_soft_span_upper_bound_ =
2731  absl::make_unique<SimpleBoundCosts>(
2732  model_->vehicles(), SimpleBoundCosts::BoundCost{kint64max, 0});
2733  }
2734  vehicle_quadratic_cost_soft_span_upper_bound_->bound_cost(vehicle) =
2735  bound_cost;
2736  }
2738  return vehicle_quadratic_cost_soft_span_upper_bound_ != nullptr;
2739  }
2741  int vehicle) const {
2742  DCHECK(HasQuadraticCostSoftSpanUpperBounds());
2743  return vehicle_quadratic_cost_soft_span_upper_bound_->bound_cost(vehicle);
2744  }
2745 #endif
2746 
2747  private:
2748  struct SoftBound {
2749  IntVar* var;
2750  int64_t bound;
2751  int64_t coefficient;
2752  };
2753 
2754  struct PiecewiseLinearCost {
2755  PiecewiseLinearCost() : var(nullptr), cost(nullptr) {}
2756  IntVar* var;
2757  std::unique_ptr<PiecewiseLinearFunction> cost;
2758  };
2759 
2760  class SelfBased {};
2761  RoutingDimension(RoutingModel* model, std::vector<int64_t> vehicle_capacities,
2762  const std::string& name,
2763  const RoutingDimension* base_dimension);
2764  RoutingDimension(RoutingModel* model, std::vector<int64_t> vehicle_capacities,
2765  const std::string& name, SelfBased);
2766  void Initialize(const std::vector<int>& transit_evaluators,
2767  const std::vector<int>& state_dependent_transit_evaluators,
2768  int64_t slack_max);
2769  void InitializeCumuls();
2770  void InitializeTransits(
2771  const std::vector<int>& transit_evaluators,
2772  const std::vector<int>& state_dependent_transit_evaluators,
2773  int64_t slack_max);
2774  void InitializeTransitVariables(int64_t slack_max);
2776  void SetupCumulVarSoftUpperBoundCosts(
2777  std::vector<IntVar*>* cost_elements) const;
2779  void SetupCumulVarSoftLowerBoundCosts(
2780  std::vector<IntVar*>* cost_elements) const;
2781  void SetupCumulVarPiecewiseLinearCosts(
2782  std::vector<IntVar*>* cost_elements) const;
2785  void SetupGlobalSpanCost(std::vector<IntVar*>* cost_elements) const;
2786  void SetupSlackAndDependentTransitCosts() const;
2788  void CloseModel(bool use_light_propagation);
2789 
2790  void SetOffsetForGlobalOptimizer(int64_t offset) {
2791  global_optimizer_offset_ = std::max(Zero(), offset);
2792  }
2794  void SetVehicleOffsetsForLocalOptimizer(std::vector<int64_t> offsets) {
2796  std::transform(offsets.begin(), offsets.end(), offsets.begin(),
2797  [](int64_t offset) { return std::max(Zero(), offset); });
2798  local_optimizer_offset_for_vehicle_ = std::move(offsets);
2799  }
2800 
2801  std::vector<IntVar*> cumuls_;
2802  std::vector<SortedDisjointIntervalList> forbidden_intervals_;
2803  std::vector<IntVar*> capacity_vars_;
2804  const std::vector<int64_t> vehicle_capacities_;
2805  std::vector<IntVar*> transits_;
2806  std::vector<IntVar*> fixed_transits_;
2809  std::vector<int> class_evaluators_;
2810  std::vector<int64_t> vehicle_to_class_;
2811 #ifndef SWIG
2812  ReverseArcListGraph<int, int> path_precedence_graph_;
2813 #endif
2814  // For every {first_node, second_node, offset} element in node_precedences_,
2815  // if both first_node and second_node are performed, then
2816  // cumuls_[second_node] must be greater than (or equal to)
2817  // cumuls_[first_node] + offset.
2818  std::vector<NodePrecedence> node_precedences_;
2819 
2820  // The transits of a dimension may depend on its cumuls or the cumuls of
2821  // another dimension. There can be no cycles, except for self loops, a
2822  // typical example for this is a time dimension.
2823  const RoutingDimension* const base_dimension_;
2824 
2825  // Values in state_dependent_class_evaluators_ correspond to the evaluators
2826  // in RoutingModel::state_dependent_transit_evaluators_ for each vehicle
2827  // class.
2828  std::vector<int> state_dependent_class_evaluators_;
2829  std::vector<int64_t> state_dependent_vehicle_to_class_;
2830 
2831  // For each pickup/delivery pair_index for which limits have been set,
2832  // pickup_to_delivery_limits_per_pair_index_[pair_index] contains the
2833  // PickupToDeliveryLimitFunction for the pickup and deliveries in this pair.
2834  std::vector<PickupToDeliveryLimitFunction>
2835  pickup_to_delivery_limits_per_pair_index_;
2836 
2837  // Used if some vehicle has breaks in this dimension, typically time.
2838  bool break_constraints_are_initialized_ = false;
2839  // clang-format off
2840  std::vector<std::vector<IntervalVar*> > vehicle_break_intervals_;
2841  std::vector<std::vector<std::pair<int64_t, int64_t> > >
2842  vehicle_break_distance_duration_;
2843  // clang-format on
2844  // For each vehicle, stores the part of travel that is made directly
2845  // after (before) the departure (arrival) node of the travel.
2846  // These parts of the travel are non-interruptible, in particular by a break.
2847  std::vector<int> vehicle_pre_travel_evaluators_;
2848  std::vector<int> vehicle_post_travel_evaluators_;
2849 
2850  std::vector<IntVar*> slacks_;
2851  std::vector<IntVar*> dependent_transits_;
2852  std::vector<int64_t> vehicle_span_upper_bounds_;
2853  int64_t global_span_cost_coefficient_;
2854  std::vector<int64_t> vehicle_span_cost_coefficients_;
2855  std::vector<SoftBound> cumul_var_soft_upper_bound_;
2856  std::vector<SoftBound> cumul_var_soft_lower_bound_;
2857  std::vector<PiecewiseLinearCost> cumul_var_piecewise_linear_cost_;
2858  RoutingModel* const model_;
2859  const std::string name_;
2860  int64_t global_optimizer_offset_;
2861  std::vector<int64_t> local_optimizer_offset_for_vehicle_;
2863  std::unique_ptr<SimpleBoundCosts> vehicle_soft_span_upper_bound_;
2864  std::unique_ptr<SimpleBoundCosts>
2865  vehicle_quadratic_cost_soft_span_upper_bound_;
2866  friend class RoutingModel;
2868  friend void AppendDimensionCumulFilters(
2869  const std::vector<RoutingDimension*>& dimensions,
2870  const RoutingSearchParameters& parameters, bool filter_objective_cost,
2871  std::vector<LocalSearchFilterManager::FilterEvent>* filters);
2872 
2874 };
2875 
2879  std::vector<IntVar*> variables,
2880  std::vector<int64_t> targets);
2881 
2887  const RoutingSearchParameters& search_parameters,
2888  const Assignment* initial_solution,
2889  Assignment* solution);
2890 
2891 #if !defined(SWIG)
2893  const RoutingModel& routing_model, const RoutingDimension& dimension);
2894 #endif
2895 
2896 } // namespace operations_research
2897 #endif // OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_H_
int64_t max
Definition: alldiff_cst.cc:140
#define CHECK(condition)
Definition: base/logging.h:498
#define CHECK_LT(val1, val2)
Definition: base/logging.h:708
#define DCHECK_GE(val1, val2)
Definition: base/logging.h:897
#define DCHECK_LT(val1, val2)
Definition: base/logging.h:896
#define LOG(severity)
Definition: base/logging.h:423
#define DCHECK(condition)
Definition: base/logging.h:892
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:1960
GlobalVehicleBreaksConstraint ensures breaks constraints are enforced on all vehicles in the dimensio...
Definition: routing.h:2068
std::string DebugString() const override
Definition: routing.h:2071
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.
Dimensions represent quantities accumulated at nodes along the routes.
Definition: routing.h:2374
void SetQuadraticCostSoftSpanUpperBoundForVehicle(SimpleBoundCosts::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:2727
SimpleBoundCosts::BoundCost GetSoftSpanUpperBoundForVehicle(int vehicle) const
Definition: routing.h:2720
const std::vector< IntVar * > & cumuls() const
Like CumulVar(), TransitVar(), SlackVar() but return the whole variable vectors instead (indexed by i...
Definition: routing.h:2403
IntVar * FixedTransitVar(int64_t index) const
Definition: routing.h:2395
void SetSoftSpanUpperBoundForVehicle(SimpleBoundCosts::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:2709
RoutingModel * model() const
Returns the model on which the dimension was created.
Definition: routing.h:2378
int64_t GetGlobalOptimizerOffset() const
Definition: routing.h:2695
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:2464
int64_t GetSpanCostCoefficientForVehicle(int vehicle) const
Definition: routing.h:2683
int64_t global_span_cost_coefficient() const
Definition: routing.h:2691
int64_t GetSpanUpperBoundForVehicle(int vehicle) const
Definition: routing.h:2675
bool AreVehicleTransitsPositive(int vehicle) const
Returns true iff the transit evaluator of 'vehicle' is positive for all arcs.
Definition: routing.h:2471
void AddNodePrecedence(int64_t first_node, int64_t second_node, int64_t offset)
Definition: routing.h:2670
const std::vector< IntVar * > & fixed_transits() const
Definition: routing.h:2404
const std::vector< IntVar * > & transits() const
Definition: routing.h:2405
const RoutingDimension * base_dimension() const
Returns the parent in the dependency tree if any or nullptr otherwise.
Definition: routing.h:2617
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:2646
void AddNodePrecedence(NodePrecedence precedence)
Definition: routing.h:2662
const std::vector< int64_t > & vehicle_span_cost_coefficients() const
Definition: routing.h:2687
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:2417
bool HasQuadraticCostSoftSpanUpperBounds() const
Definition: routing.h:2737
IntVar * SlackVar(int64_t index) const
Definition: routing.h:2398
int vehicle_to_class(int vehicle) const
Definition: routing.h:2475
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:2457
const std::vector< int64_t > & vehicle_capacities() const
Returns the capacities for all vehicles.
Definition: routing.h:2452
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:2386
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:2436
int64_t GetLocalOptimizerOffsetForVehicle(int vehicle) const
Definition: routing.h:2699
const ReverseArcListGraph< int, int > & GetPathPrecedenceGraph() const
Accessors.
Definition: routing.h:2632
const std::string & name() const
Returns the name of the dimension.
Definition: routing.h:2628
const std::vector< IntVar * > & slacks() const
Definition: routing.h:2406
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:2393
const std::vector< NodePrecedence > & GetNodePrecedences() const
Definition: routing.h:2665
const std::vector< int64_t > & vehicle_span_upper_bounds() const
Definition: routing.h:2679
IntVar * TransitVar(int64_t index) const
Definition: routing.h:2394
SimpleBoundCosts::BoundCost GetQuadraticCostSoftSpanUpperBoundForVehicle(int vehicle) const
Definition: routing.h:2740
const std::vector< SortedDisjointIntervalList > & forbidden_intervals() const
Returns forbidden intervals for each node.
Definition: routing.h:2409
Manager for any NodeIndex <-> variable index conversion.
const std::vector< std::pair< DisjunctionIndex, DisjunctionIndex > > & GetPickupAndDeliveryDisjunctions() const
Definition: routing.h:745
const std::string & GetPrimaryConstrainedDimension() const
Get the primary constrained dimension, or an empty string if it is unset.
Definition: routing.h:603
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:1373
int nodes() const
Sizes and indices Returns the number of nodes in the model.
Definition: routing.h:1348
const std::vector< int > & GetSameVehicleIndicesOfIndex(int node) const
Returns variable indices of nodes constrained to be on the same route.
Definition: routing.h:1285
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:505
VehicleClassIndex GetVehicleClassIndexOfVehicle(int64_t vehicle) const
Definition: routing.h:1278
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:634
RoutingIndexPair IndexPair
Definition: routing.h:242
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:1012
IntVar * ActiveVehicleVar(int vehicle) const
Returns the active variable of the vehicle.
Definition: routing.h:1216
RoutingTransitCallback1 TransitCallback1
Definition: routing.h:237
const std::vector< std::vector< int > > & GetTopologicallySortedVisitTypes() const
Definition: routing.h:798
int GetVehicleClassesCount() const
Returns the number of different vehicle classes in the model.
Definition: routing.h:1283
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:1003
Assignment * MutablePreAssignment()
Definition: routing.h:1072
IntVar * ActiveVar(int64_t index) const
Returns the active variable of the node corresponding to index.
Definition: routing.h:1213
bool CheckLimit()
Returns true if the search limit has been crossed.
Definition: routing.h:1335
const std::vector< DisjunctionIndex > & GetDisjunctionIndices(int64_t index) const
Returns the indices of the disjunctions to which an index belongs.
Definition: routing.h:626
IntVar * NextVar(int64_t index) const
!defined(SWIGPYTHON)
Definition: routing.h:1211
int RegisterStateDependentTransitCallback(VariableIndexEvaluator2 callback)
Definition: routing.cc:889
const std::vector< int64_t > & GetAmortizedQuadraticCostFactorOfVehicles() const
Definition: routing.h:942
const std::vector< std::unique_ptr< LocalDimensionCumulOptimizer > > & GetLocalDimensionCumulOptimizers() const
Definition: routing.h:567
const TransitCallback1 & UnaryTransitCallbackOrNull(int callback_index) const
Definition: routing.h:412
VisitTypePolicy
Set the node visit types and incompatibilities/requirements between the types (see below).
Definition: routing.h:768
@ TYPE_ADDED_TO_VEHICLE
When visited, the number of types 'T' on the vehicle increases by one.
Definition: routing.h:770
@ ADDED_TYPE_REMOVED_FROM_VEHICLE
When visited, one instance of type 'T' previously added to the route (TYPE_ADDED_TO_VEHICLE),...
Definition: routing.h:775
@ 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:778
Constraint * MakePathSpansAndTotalSlacks(const RoutingDimension *dimension, std::vector< IntVar * > spans, std::vector< IntVar * > total_slacks)
For every vehicle of the routing model:
Definition: routing.cc:5399
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:1240
IntVar * VehicleVar(int64_t index) const
Returns the vehicle variable of the node corresponding to index.
Definition: routing.h:1226
LocalDimensionCumulOptimizer * GetMutableLocalCumulOptimizer(const RoutingDimension &dimension) const
Definition: routing.cc:1184
int RegisterUnaryTransitVector(std::vector< int64_t > values)
Registers 'callback' and returns its index.
Definition: routing.cc:810
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:1173
int64_t Size() const
Returns the number of next variables in the model.
Definition: routing.h:1352
RoutingDimension * GetMutableDimension(const std::string &dimension_name) const
Returns a dimension from its name.
Definition: routing.cc:1223
bool HasTemporalTypeRequirements() const
Definition: routing.h:865
Solver * solver() const
Returns the underlying constraint solver.
Definition: routing.h:1332
static const int64_t kNoPenalty
Constant used to express a hard constraint instead of a soft penalty.
Definition: routing.h:379
RoutingTransitCallback2 TransitCallback2
Definition: routing.h:238
const std::vector< RoutingDimension * > & GetDimensions() const
Returns all dimensions of the model.
Definition: routing.h:554
int64_t GetDisjunctionMaxCardinality(DisjunctionIndex index) const
Returns the maximum number of possible active nodes of the node disjunction of index 'index'.
Definition: routing.h:658
std::vector< std::string > GetAllDimensionNames() const
Outputs the names of all dimensions added to the routing engine.
Definition: routing.cc:1163
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:992
const Solver::IndexEvaluator2 & first_solution_evaluator() const
Gets/sets the evaluator used during the search.
Definition: routing.h:960
Status
Status of the search.
Definition: routing.h:211
@ ROUTING_SUCCESS
Problem solved successfully after calling RoutingModel::Solve().
Definition: routing.h:215
@ ROUTING_FAIL
No solution found to the problem after calling RoutingModel::Solve().
Definition: routing.h:217
@ ROUTING_NOT_SOLVED
Problem not solved yet (before calling RoutingModel::Solve()).
Definition: routing.h:213
@ ROUTING_INVALID
Model, model parameters or flags are not valid.
Definition: routing.h:221
@ ROUTING_FAIL_TIMEOUT
Time limit reached before finding a solution with RoutingModel::Solve().
Definition: routing.h:219
bool HasVehicleWithCostClassIndex(CostClassIndex cost_class_index) const
Returns true iff the model contains a vehicle with the given cost_class_index.
Definition: routing.h:1265
const std::vector< int64_t > & GetDisjunctionIndices(DisjunctionIndex index) const
Returns the variable indices of the nodes in the disjunction of index 'index'.
Definition: routing.h:647
std::vector< RoutingDimension * > GetDimensionsWithSoftOrSpanCosts() const
Returns dimensions with soft or vehicle span costs.
Definition: routing.cc:4452
RoutingIndexPairs IndexPairs
Definition: routing.h:243
IntVar * VehicleCostsConsideredVar(int vehicle) const
Returns the variable specifying whether or not costs are considered for vehicle.
Definition: routing.h:1221
void ConsiderEmptyRouteCostsForVehicle(bool consider_costs, int vehicle)
Definition: routing.h:947
bool IsVehicleAllowedForIndex(int vehicle, int64_t index)
Returns true if a vehicle is allowed to visit a given node.
Definition: routing.h:689
int RegisterPositiveUnaryTransitCallback(TransitCallback1 callback)
Definition: routing.cc:848
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:1207
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:896
const IndexPairs & GetImplicitUniquePickupAndDeliveryPairs() const
Returns implicit pickup and delivery pairs currently in the model.
Definition: routing.h:752
const std::vector< int64_t > & GetAmortizedLinearCostFactorOfVehicles() const
Definition: routing.h:939
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:1617
int RegisterTransitCallback(TransitCallback2 callback)
Definition: routing.cc:856
const std::vector< std::unique_ptr< LocalDimensionCumulOptimizer > > & GetLocalDimensionCumulMPOptimizers() const
Definition: routing.h:571
int GetMaximumNumberOfActiveVehicles() const
Returns the maximum number of active vehicles.
Definition: routing.h:900
RoutingDimensionIndex DimensionIndex
Definition: routing.h:234
LocalDimensionCumulOptimizer * GetMutableLocalCumulMPOptimizer(const RoutingDimension &dimension) const
Definition: routing.cc:1196
bool HasHardTypeIncompatibilities() const
Returns true iff any hard (resp.
Definition: routing.h:817
const IndexPairs & GetPickupAndDeliveryPairs() const
Returns pickup and delivery pairs currently in the model.
Definition: routing.h:741
int RegisterPositiveTransitCallback(TransitCallback2 callback)
Definition: routing.cc:882
PickupAndDeliveryPolicy
Types of precedence policy applied to pickup and delivery pairs.
Definition: routing.h:225
@ PICKUP_AND_DELIVERY_LIFO
Deliveries must be performed in reverse order of pickups.
Definition: routing.h:229
@ PICKUP_AND_DELIVERY_NO_ORDER
Any precedence is accepted.
Definition: routing.h:227
@ PICKUP_AND_DELIVERY_FIFO
Deliveries must be performed in the same order as pickups.
Definition: routing.h:231
int64_t Start(int vehicle) const
Model inspection.
Definition: routing.h:1184
int vehicles() const
Returns the number of vehicle routes in the model.
Definition: routing.h:1350
int GetNumberOfDisjunctions() const
Returns the number of node disjunctions in the model.
Definition: routing.h:662
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:1204
bool HasTypeRegulations() const
Returns true iff the model has any incompatibilities or requirements set on node types.
Definition: routing.h:871
void SetFirstSolutionEvaluator(Solver::IndexEvaluator2 evaluator)
Takes ownership of evaluator.
Definition: routing.h:965
RoutingVehicleClassIndex VehicleClassIndex
Definition: routing.h:236
std::function< StateDependentTransit(int64_t, int64_t)> VariableIndexEvaluator2
Definition: routing.h:264
int GetNonZeroCostClassesCount() const
Ditto, minus the 'always zero', built-in cost class.
Definition: routing.h:1275
GlobalDimensionCumulOptimizer * GetMutableGlobalCumulOptimizer(const RoutingDimension &dimension) const
Returns the global/local dimension cumul optimizer for a given dimension, or nullptr if there is none...
Definition: routing.cc:1172
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:932
bool HasSameVehicleTypeRequirements() const
Returns true iff any same-route (resp.
Definition: routing.h:862
IntVar * CostVar() const
Returns the global cost variable which is being minimized.
Definition: routing.h:1228
std::pair< int, bool > AddConstantDimension(int64_t value, int64_t capacity, bool fix_start_cumul_to_zero, const std::string &name)
Definition: routing.h:468
void SetPrimaryConstrainedDimension(const std::string &dimension_name)
Set the given dimension as "primary constrained".
Definition: routing.h:598
const VariableIndexEvaluator2 & StateDependentTransitCallback(int callback_index) const
Definition: routing.h:416
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:1151
int RegisterUnaryTransitCallback(TransitCallback1 callback)
Definition: routing.cc:821
bool IsEnd(int64_t index) const
Returns true if 'index' represents the last node of a route.
Definition: routing.h:1190
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:923
RoutingCostClassIndex CostClassIndex
Definition: routing.h:233
bool HasTemporalTypeIncompatibilities() const
Definition: routing.h:820
int GetCostClassesCount() const
Returns the number of different cost classes in the model.
Definition: routing.h:1273
const TransitCallback2 & TransitCallback(int callback_index) const
Definition: routing.h:408
const std::vector< std::unique_ptr< GlobalDimensionCumulOptimizer > > & GetGlobalDimensionCumulOptimizers() const
Returns [global|local]_dimension_optimizers_, which are empty if the model has not been closed.
Definition: routing.h:563
operations_research::FirstSolutionStrategy::Value GetAutomaticFirstSolutionStrategy() const
Returns the automatic first solution strategy selected.
Definition: routing.h:1362
absl::Duration RemainingTime() const
Returns the time left in the search limit.
Definition: routing.h:1341
Status status() const
Returns the current status of the routing model.
Definition: routing.h:1047
int RegisterTransitMatrix(std::vector< std::vector< int64_t > > values)
Definition: routing.cc:829
static const DimensionIndex kNoDimension
Constant used to express the "no dimension" index, returned when a dimension name does not correspond...
Definition: routing.h:387
const Assignment *const PreAssignment() const
Returns an assignment used to fix some of the variables of the problem.
Definition: routing.h:1071
bool CostsAreHomogeneousAcrossVehicles() const
Whether costs are homogeneous across all vehicles.
Definition: routing.h:1235
CostClassIndex GetCostClassIndexOfVehicle(int64_t vehicle) const
Get the cost class index of the given vehicle.
Definition: routing.h:1256
const VehicleTypeContainer & GetVehicleTypeContainer() const
Definition: routing.h:1290
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:383
bool HasDimension(const std::string &dimension_name) const
Returns true if a dimension exists for a given dimension name.
Definition: routing.cc:1208
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:1193
bool AreEmptyRouteCostsConsideredForVehicle(int vehicle) const
Definition: routing.h:952
RoutingModel(const RoutingIndexManager &index_manager)
Constructor taking an index manager.
Definition: routing.cc:683
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:942
RoutingDisjunctionIndex DisjunctionIndex
Definition: routing.h:235
int64_t End(int vehicle) const
Returns the variable index of the ending node of a vehicle route.
Definition: routing.h:1186
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:913
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:1218
A search monitor is a simple set of callbacks to monitor all search events.
A structure meant to store soft bounds and associated violation constants.
Definition: routing.h:2335
BoundCost & bound_cost(int element)
Definition: routing.h:2343
SimpleBoundCosts(int num_bounds, BoundCost default_bound_cost)
Definition: routing.h:2341
BoundCost bound_cost(int element) const
Definition: routing.h:2344
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 by their distance and their angles from the depot.
Checker for type incompatibilities.
Definition: routing.h:2226
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:2306
Checker for type requirements.
Definition: routing.h:2242
TypeRequirementChecker(const RoutingModel &model)
Definition: routing.h:2244
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_
double upper_bound
double lower_bound
GRBmodel * model
MPCallback * callback
static const int64_t kint64max
const int WARNING
Definition: log_severity.h:31
#define DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition: macros.h:29
std::function< int64_t(const Model &)> Value(IntegerVariable v)
Definition: integer.h:1492
CpSolverResponse SolveWithParameters(const CpModelProto &model_proto, const SatParameters &params)
Solves the given CpModelProto with the given parameters.
CpSolverResponse Solve(const CpModelProto &model_proto)
Solves the given CpModelProto and returns an instance of CpSolverResponse.
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.
Definition: routing_sat.cc:525
void AppendDimensionCumulFilters(const std::vector< RoutingDimension * > &dimensions, const RoutingSearchParameters &parameters, bool filter_objective_cost, std::vector< LocalSearchFilterManager::FilterEvent > *filters)
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 * 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:167
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:5690
void FillTravelBoundsOfVehicle(int vehicle, const std::vector< int64_t > &path, const RoutingDimension &dimension, TravelBounds *travel_bounds)
std::vector< RoutingIndexPair > RoutingIndexPairs
Definition: routing_types.h:46
int index
Definition: pack.cc:509
IntervalVar * interval
Definition: resource.cc:100
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
A structure to hold tasks described by their features.
Definition: routing.h:1967
std::vector< std::pair< int64_t, int64_t > > distance_duration
Definition: routing.h:1977
std::vector< const SortedDisjointIntervalList * > forbidden_intervals
Definition: routing.h:1976
SUBTLE: The vehicle's fixed cost is skipped on purpose here, because we can afford to do so:
Definition: routing.h:292
bool operator<(const DimensionCost &cost) const
Definition: routing.h:296
int evaluator_index
Index of the arc cost evaluator, registered in the RoutingModel class.
Definition: routing.h:270
static bool LessThan(const CostClass &a, const CostClass &b)
Comparator for STL containers and algorithms.
Definition: routing.h:310
std::vector< DimensionCost > dimension_transit_evaluator_class_and_cost_coefficient
Definition: routing.h:304
What follows is relevant for models with time/state dependent transits.
Definition: routing.h:259
RangeMinMaxIndexFunction * transit_plus_identity
f(x)
Definition: routing.h:261
int64_t fixed_cost
Contrarily to CostClass, here we need strict equivalence.
Definition: routing.h:323
absl::StrongVector< DimensionIndex, int64_t > dimension_end_cumuls_max
Definition: routing.h:337
uint64_t unvisitable_nodes_fprint
Fingerprint of unvisitable non-start/end nodes.
Definition: routing.h:343
int start_equivalence_class
Vehicle start and end equivalence classes.
Definition: routing.h:330
absl::StrongVector< DimensionIndex, int64_t > dimension_capacities
Definition: routing.h:338
static bool LessThan(const VehicleClass &a, const VehicleClass &b)
Comparator for STL containers and algorithms.
Definition: routing.cc:1366
absl::StrongVector< DimensionIndex, int64_t > dimension_end_cumuls_min
Definition: routing.h:336
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:341
absl::StrongVector< DimensionIndex, int64_t > dimension_start_cumuls_min
Bounds of cumul variables at start and end vehicle nodes.
Definition: routing.h:334
absl::StrongVector< DimensionIndex, int64_t > dimension_start_cumuls_max
Definition: routing.h:335
CostClassIndex cost_class_index
The cost class of the vehicle.
Definition: routing.h:321
Definition: routing.h:354
int64_t fixed_cost
Definition: routing.h:356
bool operator<(const VehicleClassEntry &other) const
Definition: routing.h:358
int vehicle_class
Definition: routing.h:355
Struct used to sort and store vehicles by their type.
Definition: routing.h:353
std::vector< std::set< VehicleClassEntry > > sorted_vehicle_classes_per_type
Definition: routing.h:373
std::vector< std::deque< int > > vehicles_per_vehicle_class
Definition: routing.h:374
std::vector< int64_t > post_travels
Definition: routing.h:2041
std::vector< int64_t > max_travels
Definition: routing.h:2039
std::vector< int64_t > pre_travels
Definition: routing.h:2040
std::vector< int64_t > min_travels
Definition: routing.h:2038