OR-Tools  8.2
routing.h
Go to the documentation of this file.
1 // Copyright 2010-2018 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 <cstddef>
161 #include <deque>
162 #include <functional>
163 #include <memory>
164 #include <queue>
165 #include <string>
166 #include <utility>
167 #include <vector>
168 
169 #include "absl/container/flat_hash_map.h"
170 #include "absl/container/flat_hash_set.h"
171 #include "absl/functional/bind_front.h"
172 #include "absl/hash/hash.h"
173 #include "absl/time/time.h"
177 #include "ortools/base/hash.h"
178 #include "ortools/base/logging.h"
179 #include "ortools/base/macros.h"
180 #include "ortools/base/mathutil.h"
187 #include "ortools/glop/lp_solver.h"
189 #include "ortools/graph/graph.h"
190 #include "ortools/lp_data/lp_data.h"
192 #include "ortools/sat/theta_tree.h"
195 
196 namespace operations_research {
197 
198 class GlobalDimensionCumulOptimizer;
199 class LocalDimensionCumulOptimizer;
200 class LocalSearchOperator;
201 #ifndef SWIG
202 class IntVarFilteredDecisionBuilder;
203 class IntVarFilteredHeuristic;
204 class IndexNeighborFinder;
205 #endif
206 class RoutingDimension;
207 #ifndef SWIG
209 class SweepArranger;
210 #endif
211 struct SweepIndex;
212 
214  public:
216  enum Status {
227  };
228 
237  };
238  typedef RoutingCostClassIndex CostClassIndex;
239  typedef RoutingDimensionIndex DimensionIndex;
240  typedef RoutingDisjunctionIndex DisjunctionIndex;
241  typedef RoutingVehicleClassIndex VehicleClassIndex;
244 
245 // TODO(user): Remove all SWIG guards by adding the @ignore in .i.
246 #if !defined(SWIG)
249 #endif // SWIG
250 
251 #if !defined(SWIG)
267  };
268  typedef std::function<StateDependentTransit(int64, int64)>
270 #endif // SWIG
271 
272 #if !defined(SWIG)
273  struct CostClass {
276 
291 
297  struct DimensionCost {
301  bool operator<(const DimensionCost& cost) const {
302  if (transit_evaluator_class != cost.transit_evaluator_class) {
303  return transit_evaluator_class < cost.transit_evaluator_class;
304  }
305  return cost_coefficient < cost.cost_coefficient;
306  }
307  };
308  std::vector<DimensionCost>
310 
313 
315  static bool LessThan(const CostClass& a, const CostClass& b) {
316  if (a.evaluator_index != b.evaluator_index) {
317  return a.evaluator_index < b.evaluator_index;
318  }
319  return a.dimension_transit_evaluator_class_and_cost_coefficient <
320  b.dimension_transit_evaluator_class_and_cost_coefficient;
321  }
322  };
323 
324  struct VehicleClass {
333  // TODO(user): Find equivalent start/end nodes wrt dimensions and
334  // callbacks.
349 
351  static bool LessThan(const VehicleClass& a, const VehicleClass& b);
352  };
353 #endif // defined(SWIG)
354 
362 
363  bool operator<(const VehicleClassEntry& other) const {
364  return std::tie(fixed_cost, vehicle_class) <
365  std::tie(other.fixed_cost, other.vehicle_class);
366  }
367  };
368 
369  int NumTypes() const { return sorted_vehicle_classes_per_type.size(); }
370 
371  int Type(int vehicle) const {
372  DCHECK_LT(vehicle, type_index_of_vehicle.size());
373  return type_index_of_vehicle[vehicle];
374  }
375 
376  std::vector<int> type_index_of_vehicle;
377  // clang-format off
378  std::vector<std::set<VehicleClassEntry> > sorted_vehicle_classes_per_type;
379  std::vector<std::deque<int> > vehicles_per_vehicle_class;
380  // clang-format on
381  };
382 
384  static const int64 kNoPenalty;
385 
389 
393 
397  explicit RoutingModel(const RoutingIndexManager& index_manager);
398  RoutingModel(const RoutingIndexManager& index_manager,
399  const RoutingModelParameters& parameters);
400  ~RoutingModel();
401 
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 slack_max, int64 capacity,
445  bool fix_start_cumul_to_zero, const std::string& name);
447  const std::vector<int>& evaluator_indices, int64 slack_max,
448  int64 capacity, bool fix_start_cumul_to_zero, const std::string& name);
449  bool AddDimensionWithVehicleCapacity(int evaluator_index, int64 slack_max,
450  std::vector<int64> vehicle_capacities,
451  bool fix_start_cumul_to_zero,
452  const std::string& name);
454  const std::vector<int>& evaluator_indices, int64 slack_max,
455  std::vector<int64> vehicle_capacities, bool fix_start_cumul_to_zero,
456  const std::string& name);
464  int64 slack_max,
465  bool fix_start_cumul_to_zero,
466  const std::string& name);
468  bool fix_start_cumul_to_zero,
469  const std::string& name) {
471  fix_start_cumul_to_zero, name);
472  }
480  bool AddVectorDimension(std::vector<int64> values, int64 capacity,
481  bool fix_start_cumul_to_zero,
482  const std::string& name);
490  bool AddMatrixDimension(
491  std::vector<std::vector<int64> /*needed_for_swig*/> values,
492  int64 capacity, bool fix_start_cumul_to_zero, const std::string& name);
500  const std::vector<int>& pure_transits,
501  const std::vector<int>& dependent_transits,
502  const RoutingDimension* base_dimension, int64 slack_max,
503  std::vector<int64> vehicle_capacities, bool fix_start_cumul_to_zero,
504  const std::string& name) {
505  return AddDimensionDependentDimensionWithVehicleCapacityInternal(
506  pure_transits, dependent_transits, base_dimension, slack_max,
507  std::move(vehicle_capacities), fix_start_cumul_to_zero, name);
508  }
509 
512  const std::vector<int>& transits, const RoutingDimension* base_dimension,
513  int64 slack_max, std::vector<int64> vehicle_capacities,
514  bool fix_start_cumul_to_zero, const std::string& name);
517  int transit, const RoutingDimension* base_dimension, int64 slack_max,
518  int64 vehicle_capacity, bool fix_start_cumul_to_zero,
519  const std::string& name);
521  int pure_transit, int dependent_transit,
522  const RoutingDimension* base_dimension, int64 slack_max,
523  int64 vehicle_capacity, bool fix_start_cumul_to_zero,
524  const std::string& name);
525 
528  const std::function<int64(int64)>& f, int64 domain_start,
529  int64 domain_end);
530 
541  std::vector<IntVar*> spans,
542  std::vector<IntVar*> total_slacks);
543 
545  // TODO(user): rename.
546  std::vector<std::string> GetAllDimensionNames() const;
548  const std::vector<RoutingDimension*>& GetDimensions() const {
549  return dimensions_.get();
550  }
552  std::vector<RoutingDimension*> GetDimensionsWithSoftOrSpanCosts() const;
553  // clang-format off
556  const std::vector<std::unique_ptr<GlobalDimensionCumulOptimizer> >&
558  return global_dimension_optimizers_;
559  }
560  const std::vector<std::unique_ptr<LocalDimensionCumulOptimizer> >&
562  return local_dimension_optimizers_;
563  }
564  const std::vector<std::unique_ptr<LocalDimensionCumulOptimizer> >&
566  return local_dimension_mp_optimizers_;
567  }
568  // clang-format on
569 
573  const RoutingDimension& dimension) const;
575  const RoutingDimension& dimension) const;
577  const RoutingDimension& dimension) const;
578 
580  bool HasDimension(const std::string& dimension_name) const;
583  const std::string& dimension_name) const;
587  const std::string& dimension_name) const;
592  void SetPrimaryConstrainedDimension(const std::string& dimension_name) {
593  DCHECK(dimension_name.empty() || HasDimension(dimension_name));
594  primary_constrained_dimension_ = dimension_name;
595  }
597  const std::string& GetPrimaryConstrainedDimension() const {
598  return primary_constrained_dimension_;
599  }
616  DisjunctionIndex AddDisjunction(const std::vector<int64>& indices,
617  int64 penalty = kNoPenalty,
618  int64 max_cardinality = 1);
620  const std::vector<DisjunctionIndex>& GetDisjunctionIndices(
621  int64 index) const {
622  return index_to_disjunctions_[index];
623  }
627  template <typename F>
629  int64 index, int64 max_cardinality, F f) const {
630  for (const DisjunctionIndex disjunction : GetDisjunctionIndices(index)) {
631  if (disjunctions_[disjunction].value.max_cardinality == max_cardinality) {
632  for (const int64 d_index : disjunctions_[disjunction].indices) {
633  f(d_index);
634  }
635  }
636  }
637  }
638 #if !defined(SWIGPYTHON)
641  const std::vector<int64>& GetDisjunctionIndices(
642  DisjunctionIndex index) const {
643  return disjunctions_[index].indices;
644  }
645 #endif // !defined(SWIGPYTHON)
647  int64 GetDisjunctionPenalty(DisjunctionIndex index) const {
648  return disjunctions_[index].value.penalty;
649  }
653  return disjunctions_[index].value.max_cardinality;
654  }
656  int GetNumberOfDisjunctions() const { return disjunctions_.size(); }
661  std::vector<std::pair<int64, int64>> GetPerfectBinaryDisjunctions() const;
667  void IgnoreDisjunctionsAlreadyForcedToZero();
668 
672  void AddSoftSameVehicleConstraint(const std::vector<int64>& indices,
673  int64 cost);
674 
679  void SetAllowedVehiclesForIndex(const std::vector<int>& vehicles,
680  int64 index);
681 
683  bool IsVehicleAllowedForIndex(int vehicle, int64 index) {
684  return allowed_vehicles_[index].empty() ||
685  allowed_vehicles_[index].find(vehicle) !=
686  allowed_vehicles_[index].end();
687  }
688 
703  // TODO(user): Remove this when model introspection detects linked nodes.
704  void AddPickupAndDelivery(int64 pickup, int64 delivery);
708  void AddPickupAndDeliverySets(DisjunctionIndex pickup_disjunction,
709  DisjunctionIndex delivery_disjunction);
710  // clang-format off
714  const std::vector<std::pair<int, int> >&
715  GetPickupIndexPairs(int64 node_index) const;
717  const std::vector<std::pair<int, int> >&
718  GetDeliveryIndexPairs(int64 node_index) const;
719  // clang-format on
720 
723  void SetPickupAndDeliveryPolicyOfAllVehicles(PickupAndDeliveryPolicy policy);
724  void SetPickupAndDeliveryPolicyOfVehicle(PickupAndDeliveryPolicy policy,
725  int vehicle);
726  PickupAndDeliveryPolicy GetPickupAndDeliveryPolicyOfVehicle(
727  int vehicle) const;
730 
731  int GetNumOfSingletonNodes() const;
732 
733 #ifndef SWIG
736  return pickup_delivery_pairs_;
737  }
738  const std::vector<std::pair<DisjunctionIndex, DisjunctionIndex>>&
740  return pickup_delivery_disjunctions_;
741  }
747  DCHECK(closed_);
748  return implicit_pickup_delivery_pairs_without_alternatives_;
749  }
750 #endif // SWIG
762  enum VisitTypePolicy {
777  TYPE_SIMULTANEOUSLY_ADDED_AND_REMOVED
778  };
779  // TODO(user): Support multiple visit types per node?
780  void SetVisitType(int64 index, int type, VisitTypePolicy type_policy);
781  int GetVisitType(int64 index) const;
782  const std::vector<int>& GetSingleNodesOfType(int type) const;
783  const std::vector<int>& GetPairIndicesOfType(int type) const;
784  VisitTypePolicy GetVisitTypePolicy(int64 index) const;
787  // TODO(user): Reconsider the logic and potentially remove the need to
789  void CloseVisitTypes();
790  int GetNumberOfVisitTypes() const { return num_visit_types_; }
791 #ifndef SWIG
792  const std::vector<std::vector<int>>& GetTopologicallySortedVisitTypes()
793  const {
794  DCHECK(closed_);
795  return topologically_sorted_visit_types_;
796  }
797 #endif // SWIG
802  void AddHardTypeIncompatibility(int type1, int type2);
803  void AddTemporalTypeIncompatibility(int type1, int type2);
805  const absl::flat_hash_set<int>& GetHardTypeIncompatibilitiesOfType(
806  int type) const;
807  const absl::flat_hash_set<int>& GetTemporalTypeIncompatibilitiesOfType(
808  int type) const;
812  return has_hard_type_incompatibilities_;
813  }
815  return has_temporal_type_incompatibilities_;
816  }
827  void AddSameVehicleRequiredTypeAlternatives(
828  int dependent_type, absl::flat_hash_set<int> required_type_alternatives);
833  void AddRequiredTypeAlternativesWhenAddingType(
834  int dependent_type, absl::flat_hash_set<int> required_type_alternatives);
840  void AddRequiredTypeAlternativesWhenRemovingType(
841  int dependent_type, absl::flat_hash_set<int> required_type_alternatives);
842  // clang-format off
845  const std::vector<absl::flat_hash_set<int> >&
846  GetSameVehicleRequiredTypeAlternativesOfType(int type) const;
848  const std::vector<absl::flat_hash_set<int> >&
849  GetRequiredTypeAlternativesWhenAddingType(int type) const;
851  const std::vector<absl::flat_hash_set<int> >&
852  GetRequiredTypeAlternativesWhenRemovingType(int type) const;
853  // clang-format on
857  return has_same_vehicle_type_requirements_;
858  }
860  return has_temporal_type_requirements_;
861  }
862 
865  bool HasTypeRegulations() const {
866  return HasTemporalTypeIncompatibilities() ||
867  HasHardTypeIncompatibilities() || HasSameVehicleTypeRequirements() ||
868  HasTemporalTypeRequirements();
869  }
870 
875  int64 UnperformedPenalty(int64 var_index) const;
879  int64 UnperformedPenaltyOrValue(int64 default_value, int64 var_index) const;
883  int64 GetDepot() const;
884 
889  void SetMaximumNumberOfActiveVehicles(int max_active_vehicles) {
890  max_active_vehicles_ = max_active_vehicles;
891  }
893  int GetMaximumNumberOfActiveVehicles() const { return max_active_vehicles_; }
897  void SetArcCostEvaluatorOfAllVehicles(int evaluator_index);
899  void SetArcCostEvaluatorOfVehicle(int evaluator_index, int vehicle);
902  void SetFixedCostOfAllVehicles(int64 cost);
904  void SetFixedCostOfVehicle(int64 cost, int vehicle);
908  int64 GetFixedCostOfVehicle(int vehicle) const;
909 
925  void SetAmortizedCostFactorsOfAllVehicles(int64 linear_cost_factor,
926  int64 quadratic_cost_factor);
928  void SetAmortizedCostFactorsOfVehicle(int64 linear_cost_factor,
929  int64 quadratic_cost_factor,
930  int vehicle);
931 
932  const std::vector<int64>& GetAmortizedLinearCostFactorOfVehicles() const {
933  return linear_cost_factor_of_vehicle_;
934  }
935  const std::vector<int64>& GetAmortizedQuadraticCostFactorOfVehicles() const {
936  return quadratic_cost_factor_of_vehicle_;
937  }
938 
939  void ConsiderEmptyRouteCostsForVehicle(bool consider_costs, int vehicle) {
940  DCHECK_LT(vehicle, vehicles_);
941  consider_empty_route_costs_[vehicle] = consider_costs;
942  }
943 
944  bool AreEmptyRouteCostsConsideredForVehicle(int vehicle) const {
945  DCHECK_LT(vehicle, vehicles_);
946  return consider_empty_route_costs_[vehicle];
947  }
948 
951 #ifndef SWIG
953  return first_solution_evaluator_;
954  }
955 #endif
958  first_solution_evaluator_ = std::move(evaluator);
959  }
962  void AddLocalSearchOperator(LocalSearchOperator* ls_operator);
964  void AddSearchMonitor(SearchMonitor* const monitor);
968  void AddAtSolutionCallback(std::function<void()> callback);
973  void AddVariableMinimizedByFinalizer(IntVar* var);
976  void AddVariableMaximizedByFinalizer(IntVar* var);
979  void AddWeightedVariableMinimizedByFinalizer(IntVar* var, int64 cost);
982  void AddVariableTargetToFinalizer(IntVar* var, int64 target);
989  void CloseModel();
992  void CloseModelWithParameters(
993  const RoutingSearchParameters& search_parameters);
1000  const Assignment* Solve(const Assignment* assignment = nullptr);
1009  const RoutingSearchParameters& search_parameters,
1010  std::vector<const Assignment*>* solutions = nullptr);
1011  const Assignment* SolveFromAssignmentWithParameters(
1012  const Assignment* assignment,
1013  const RoutingSearchParameters& search_parameters,
1014  std::vector<const Assignment*>* solutions = nullptr);
1020  void SetAssignmentFromOtherModelAssignment(
1021  Assignment* target_assignment, const RoutingModel* source_model,
1022  const Assignment* source_assignment);
1028  // TODO(user): Add support for non-homogeneous costs and disjunctions.
1029  int64 ComputeLowerBound();
1031  Status status() const { return status_; }
1040  IntVar* ApplyLocks(const std::vector<int64>& locks);
1049  bool ApplyLocksToAllVehicles(const std::vector<std::vector<int64>>& locks,
1050  bool close_routes);
1055  const Assignment* const PreAssignment() const { return preassignment_; }
1056  Assignment* MutablePreAssignment() { return preassignment_; }
1060  bool WriteAssignment(const std::string& file_name) const;
1064  Assignment* ReadAssignment(const std::string& file_name);
1067  Assignment* RestoreAssignment(const Assignment& solution);
1073  Assignment* ReadAssignmentFromRoutes(
1074  const std::vector<std::vector<int64>>& routes,
1075  bool ignore_inactive_indices);
1092  bool RoutesToAssignment(const std::vector<std::vector<int64>>& routes,
1093  bool ignore_inactive_indices, bool close_routes,
1094  Assignment* const assignment) const;
1098  void AssignmentToRoutes(const Assignment& assignment,
1099  std::vector<std::vector<int64>>* const routes) const;
1104 #ifndef SWIG
1105  std::vector<std::vector<int64>> GetRoutesFromAssignment(
1106  const Assignment& assignment);
1107 #endif
1125  Assignment* CompactAssignment(const Assignment& assignment) const;
1129  Assignment* CompactAndCheckAssignment(const Assignment& assignment) const;
1131  void AddToAssignment(IntVar* const var);
1132  void AddIntervalToAssignment(IntervalVar* const interval);
1143  const Assignment* PackCumulsOfOptimizerDimensionsFromAssignment(
1144  const Assignment* original_assignment, absl::Duration duration_limit);
1145 #ifndef SWIG
1146  // TODO(user): Revisit if coordinates are added to the RoutingModel class.
1147  void SetSweepArranger(SweepArranger* sweep_arranger) {
1148  sweep_arranger_.reset(sweep_arranger);
1149  }
1151  SweepArranger* sweep_arranger() const { return sweep_arranger_.get(); }
1152 #endif
1159  CHECK(filter != nullptr);
1160  if (closed_) {
1161  LOG(WARNING) << "Model is closed, filter addition will be ignored.";
1162  }
1163  extra_filters_.push_back({filter, LocalSearchFilterManager::kRelax});
1164  extra_filters_.push_back({filter, LocalSearchFilterManager::kAccept});
1165  }
1166 
1169  int64 Start(int vehicle) const { return starts_[vehicle]; }
1171  int64 End(int vehicle) const { return ends_[vehicle]; }
1173  bool IsStart(int64 index) const;
1175  bool IsEnd(int64 index) const { return index >= Size(); }
1178  int VehicleIndex(int64 index) const { return index_to_vehicle_[index]; }
1182  int64 Next(const Assignment& assignment, int64 index) const;
1184  bool IsVehicleUsed(const Assignment& assignment, int vehicle) const;
1185 
1186 #if !defined(SWIGPYTHON)
1189  const std::vector<IntVar*>& Nexts() const { return nexts_; }
1192  const std::vector<IntVar*>& VehicleVars() const { return vehicle_vars_; }
1193 #endif
1196  IntVar* NextVar(int64 index) const { return nexts_[index]; }
1198  IntVar* ActiveVar(int64 index) const { return active_[index]; }
1201  IntVar* ActiveVehicleVar(int vehicle) const {
1202  return vehicle_active_[vehicle];
1203  }
1206  IntVar* VehicleCostsConsideredVar(int vehicle) const {
1207  return vehicle_costs_considered_[vehicle];
1208  }
1211  IntVar* VehicleVar(int64 index) const { return vehicle_vars_[index]; }
1213  IntVar* CostVar() const { return cost_; }
1214 
1217  int64 GetArcCostForVehicle(int64 from_index, int64 to_index,
1218  int64 vehicle) const;
1221  return costs_are_homogeneous_across_vehicles_;
1222  }
1225  int64 GetHomogeneousCost(int64 from_index, int64 to_index) const {
1226  return GetArcCostForVehicle(from_index, to_index, /*vehicle=*/0);
1227  }
1230  int64 GetArcCostForFirstSolution(int64 from_index, int64 to_index) const;
1237  int64 GetArcCostForClass(int64 from_index, int64 to_index,
1238  int64 /*CostClassIndex*/ cost_class_index) const;
1241  DCHECK(closed_);
1242  DCHECK_GE(vehicle, 0);
1243  DCHECK_LT(vehicle, cost_class_index_of_vehicle_.size());
1244  DCHECK_GE(cost_class_index_of_vehicle_[vehicle], 0);
1245  return cost_class_index_of_vehicle_[vehicle];
1246  }
1249  bool HasVehicleWithCostClassIndex(CostClassIndex cost_class_index) const {
1250  DCHECK(closed_);
1251  if (cost_class_index == kCostClassIndexOfZeroCost) {
1252  return has_vehicle_with_zero_cost_class_;
1253  }
1254  return cost_class_index < cost_classes_.size();
1255  }
1257  int GetCostClassesCount() const { return cost_classes_.size(); }
1260  return std::max(0, GetCostClassesCount() - 1);
1261  }
1263  DCHECK(closed_);
1264  return vehicle_class_index_of_vehicle_[vehicle];
1265  }
1267  int GetVehicleClassesCount() const { return vehicle_classes_.size(); }
1269  const std::vector<int>& GetSameVehicleIndicesOfIndex(int node) const {
1270  DCHECK(closed_);
1271  return same_vehicle_groups_[same_vehicle_group_[node]];
1272  }
1273 
1275  DCHECK(closed_);
1276  return vehicle_type_container_;
1277  }
1278 
1297  bool ArcIsMoreConstrainedThanArc(int64 from, int64 to1, int64 to2);
1302  std::string DebugOutputAssignment(
1303  const Assignment& solution_assignment,
1304  const std::string& dimension_to_print) const;
1310 #ifndef SWIG
1311  std::vector<std::vector<std::pair<int64, int64>>> GetCumulBounds(
1312  const Assignment& solution_assignment, const RoutingDimension& dimension);
1313 #endif
1316  Solver* solver() const { return solver_.get(); }
1317 
1319  bool CheckLimit() {
1320  DCHECK(limit_ != nullptr);
1321  return limit_->Check();
1322  }
1323 
1325  absl::Duration RemainingTime() const {
1326  DCHECK(limit_ != nullptr);
1327  return limit_->AbsoluteSolverDeadline() - solver_->Now();
1328  }
1329 
1332  int nodes() const { return nodes_; }
1334  int vehicles() const { return vehicles_; }
1336  int64 Size() const { return nodes_ + vehicles_ - start_end_count_; }
1337 
1340  int64 GetNumberOfDecisionsInFirstSolution(
1341  const RoutingSearchParameters& search_parameters) const;
1342  int64 GetNumberOfRejectsInFirstSolution(
1343  const RoutingSearchParameters& search_parameters) const;
1347  return automatic_first_solution_strategy_;
1348  }
1349 
1351  bool IsMatchingModel() const;
1352 
1353 #ifndef SWIG
1357  std::function<std::vector<operations_research::IntVar*>(RoutingModel*)>;
1358 
1359  void SetTabuVarsCallback(GetTabuVarsCallback tabu_var_callback);
1360 #endif // SWIG
1361 
1363  // TODO(user): Find a way to test and restrict the access at the same time.
1375  DecisionBuilder* MakeGuidedSlackFinalizer(
1376  const RoutingDimension* dimension,
1377  std::function<int64(int64)> initializer);
1378 #ifndef SWIG
1379  // TODO(user): MakeGreedyDescentLSOperator is too general for routing.h.
1384  static std::unique_ptr<LocalSearchOperator> MakeGreedyDescentLSOperator(
1385  std::vector<IntVar*> variables);
1386 #endif
1400  DecisionBuilder* MakeSelfDependentDimensionFinalizer(
1401  const RoutingDimension* dimension);
1402 
1403  private:
1405  enum RoutingLocalSearchOperator {
1406  RELOCATE = 0,
1407  RELOCATE_PAIR,
1408  LIGHT_RELOCATE_PAIR,
1409  RELOCATE_NEIGHBORS,
1410  EXCHANGE,
1411  EXCHANGE_PAIR,
1412  CROSS,
1413  CROSS_EXCHANGE,
1414  TWO_OPT,
1415  OR_OPT,
1416  GLOBAL_CHEAPEST_INSERTION_CLOSE_NODES_LNS,
1417  LOCAL_CHEAPEST_INSERTION_CLOSE_NODES_LNS,
1418  GLOBAL_CHEAPEST_INSERTION_PATH_LNS,
1419  LOCAL_CHEAPEST_INSERTION_PATH_LNS,
1420  RELOCATE_PATH_GLOBAL_CHEAPEST_INSERTION_INSERT_UNPERFORMED,
1421  GLOBAL_CHEAPEST_INSERTION_EXPENSIVE_CHAIN_LNS,
1422  LOCAL_CHEAPEST_INSERTION_EXPENSIVE_CHAIN_LNS,
1423  RELOCATE_EXPENSIVE_CHAIN,
1424  LIN_KERNIGHAN,
1425  TSP_OPT,
1426  MAKE_ACTIVE,
1427  RELOCATE_AND_MAKE_ACTIVE,
1428  MAKE_ACTIVE_AND_RELOCATE,
1429  MAKE_INACTIVE,
1430  MAKE_CHAIN_INACTIVE,
1431  SWAP_ACTIVE,
1432  EXTENDED_SWAP_ACTIVE,
1433  NODE_PAIR_SWAP,
1434  PATH_LNS,
1435  FULL_PATH_LNS,
1436  TSP_LNS,
1437  INACTIVE_LNS,
1438  EXCHANGE_RELOCATE_PAIR,
1439  RELOCATE_SUBTRIP,
1440  EXCHANGE_SUBTRIP,
1441  LOCAL_SEARCH_OPERATOR_COUNTER
1442  };
1443 
1447  template <typename T>
1448  struct ValuedNodes {
1449  std::vector<int64> indices;
1450  T value;
1451  };
1452  struct DisjunctionValues {
1453  int64 penalty;
1454  int64 max_cardinality;
1455  };
1456  typedef ValuedNodes<DisjunctionValues> Disjunction;
1457 
1460  struct CostCacheElement {
1465  int index;
1466  CostClassIndex cost_class_index;
1467  int64 cost;
1468  };
1469 
1471  void Initialize();
1472  void AddNoCycleConstraintInternal();
1473  bool AddDimensionWithCapacityInternal(
1474  const std::vector<int>& evaluator_indices, int64 slack_max,
1475  std::vector<int64> vehicle_capacities, bool fix_start_cumul_to_zero,
1476  const std::string& name);
1477  bool AddDimensionDependentDimensionWithVehicleCapacityInternal(
1478  const std::vector<int>& pure_transits,
1479  const std::vector<int>& dependent_transits,
1480  const RoutingDimension* base_dimension, int64 slack_max,
1481  std::vector<int64> vehicle_capacities, bool fix_start_cumul_to_zero,
1482  const std::string& name);
1483  bool InitializeDimensionInternal(
1484  const std::vector<int>& evaluator_indices,
1485  const std::vector<int>& state_dependent_evaluator_indices,
1486  int64 slack_max, bool fix_start_cumul_to_zero,
1487  RoutingDimension* dimension);
1488  DimensionIndex GetDimensionIndex(const std::string& dimension_name) const;
1489 
1517  void StoreDimensionCumulOptimizers(const RoutingSearchParameters& parameters);
1518 
1519  void ComputeCostClasses(const RoutingSearchParameters& parameters);
1520  void ComputeVehicleClasses();
1528  void ComputeVehicleTypes();
1538  void FinalizeVisitTypes();
1539  // Called by FinalizeVisitTypes() to setup topologically_sorted_visit_types_.
1540  void TopologicallySortVisitTypes();
1541  int64 GetArcCostForClassInternal(int64 from_index, int64 to_index,
1542  CostClassIndex cost_class_index) const;
1543  void AppendHomogeneousArcCosts(const RoutingSearchParameters& parameters,
1544  int node_index,
1545  std::vector<IntVar*>* cost_elements);
1546  void AppendArcCosts(const RoutingSearchParameters& parameters, int node_index,
1547  std::vector<IntVar*>* cost_elements);
1548  Assignment* DoRestoreAssignment();
1549  static const CostClassIndex kCostClassIndexOfZeroCost;
1550  int64 SafeGetCostClassInt64OfVehicle(int64 vehicle) const {
1551  DCHECK_LT(0, vehicles_);
1552  return (vehicle >= 0 ? GetCostClassIndexOfVehicle(vehicle)
1553  : kCostClassIndexOfZeroCost)
1554  .value();
1555  }
1556  int64 GetDimensionTransitCostSum(int64 i, int64 j,
1557  const CostClass& cost_class) const;
1559  IntVar* CreateDisjunction(DisjunctionIndex disjunction);
1561  void AddPickupAndDeliverySetsInternal(const std::vector<int64>& pickups,
1562  const std::vector<int64>& deliveries);
1565  IntVar* CreateSameVehicleCost(int vehicle_index);
1568  int FindNextActive(int index, const std::vector<int64>& indices) const;
1569 
1572  bool RouteCanBeUsedByVehicle(const Assignment& assignment, int start_index,
1573  int vehicle) const;
1581  bool ReplaceUnusedVehicle(int unused_vehicle, int active_vehicle,
1582  Assignment* compact_assignment) const;
1583 
1584  void QuietCloseModel();
1585  void QuietCloseModelWithParameters(
1586  const RoutingSearchParameters& parameters) {
1587  if (!closed_) {
1588  CloseModelWithParameters(parameters);
1589  }
1590  }
1591 
1593  bool SolveMatchingModel(Assignment* assignment,
1594  const RoutingSearchParameters& parameters);
1595 #ifndef SWIG
1597  bool AppendAssignmentIfFeasible(
1598  const Assignment& assignment,
1599  std::vector<std::unique_ptr<Assignment>>* assignments);
1600 #endif
1602  void LogSolution(const RoutingSearchParameters& parameters,
1603  const std::string& description, int64 solution_cost,
1604  int64 start_time_ms);
1607  Assignment* CompactAssignmentInternal(const Assignment& assignment,
1608  bool check_compact_assignment) const;
1613  std::string FindErrorInSearchParametersForModel(
1614  const RoutingSearchParameters& search_parameters) const;
1616  void SetupSearch(const RoutingSearchParameters& search_parameters);
1618  // TODO(user): Document each auxiliary method.
1619  Assignment* GetOrCreateAssignment();
1620  Assignment* GetOrCreateTmpAssignment();
1621  RegularLimit* GetOrCreateLimit();
1622  RegularLimit* GetOrCreateLocalSearchLimit();
1623  RegularLimit* GetOrCreateLargeNeighborhoodSearchLimit();
1624  RegularLimit* GetOrCreateFirstSolutionLargeNeighborhoodSearchLimit();
1625  LocalSearchOperator* CreateInsertionOperator();
1626  LocalSearchOperator* CreateMakeInactiveOperator();
1627  template <class T>
1628  LocalSearchOperator* CreateCPOperator(const T& operator_factory) {
1629  return operator_factory(solver_.get(), nexts_,
1630  CostsAreHomogeneousAcrossVehicles()
1631  ? std::vector<IntVar*>()
1632  : vehicle_vars_,
1633  vehicle_start_class_callback_);
1634  }
1635  template <class T>
1636  LocalSearchOperator* CreateCPOperator() {
1637  return CreateCPOperator(absl::bind_front(MakeLocalSearchOperator<T>));
1638  }
1639  template <class T, class Arg>
1640  LocalSearchOperator* CreateOperator(const Arg& arg) {
1641  return solver_->RevAlloc(new T(nexts_,
1642  CostsAreHomogeneousAcrossVehicles()
1643  ? std::vector<IntVar*>()
1644  : vehicle_vars_,
1645  vehicle_start_class_callback_, arg));
1646  }
1647  template <class T>
1648  LocalSearchOperator* CreatePairOperator() {
1649  return CreateOperator<T>(pickup_delivery_pairs_);
1650  }
1651  void CreateNeighborhoodOperators(const RoutingSearchParameters& parameters);
1652  LocalSearchOperator* ConcatenateOperators(
1653  const RoutingSearchParameters& search_parameters,
1654  const std::vector<LocalSearchOperator*>& operators) const;
1655  LocalSearchOperator* GetNeighborhoodOperators(
1656  const RoutingSearchParameters& search_parameters) const;
1657  std::vector<LocalSearchFilterManager::FilterEvent>
1658  GetOrCreateLocalSearchFilters(const RoutingSearchParameters& parameters,
1659  bool filter_cost = true);
1660  LocalSearchFilterManager* GetOrCreateLocalSearchFilterManager(
1661  const RoutingSearchParameters& parameters);
1662  std::vector<LocalSearchFilterManager::FilterEvent>
1663  GetOrCreateFeasibilityFilters(const RoutingSearchParameters& parameters);
1664  LocalSearchFilterManager* GetOrCreateFeasibilityFilterManager(
1665  const RoutingSearchParameters& parameters);
1666  LocalSearchFilterManager* GetOrCreateStrongFeasibilityFilterManager(
1667  const RoutingSearchParameters& parameters);
1668  DecisionBuilder* CreateSolutionFinalizer(SearchLimit* lns_limit);
1669  DecisionBuilder* CreateFinalizerForMinimizedAndMaximizedVariables();
1670  void CreateFirstSolutionDecisionBuilders(
1671  const RoutingSearchParameters& search_parameters);
1672  DecisionBuilder* GetFirstSolutionDecisionBuilder(
1673  const RoutingSearchParameters& search_parameters) const;
1674  IntVarFilteredDecisionBuilder* GetFilteredFirstSolutionDecisionBuilderOrNull(
1675  const RoutingSearchParameters& parameters) const;
1676  LocalSearchPhaseParameters* CreateLocalSearchParameters(
1677  const RoutingSearchParameters& search_parameters);
1678  DecisionBuilder* CreateLocalSearchDecisionBuilder(
1679  const RoutingSearchParameters& search_parameters);
1680  void SetupDecisionBuilders(const RoutingSearchParameters& search_parameters);
1681  void SetupMetaheuristics(const RoutingSearchParameters& search_parameters);
1682  void SetupAssignmentCollector(
1683  const RoutingSearchParameters& search_parameters);
1684  void SetupTrace(const RoutingSearchParameters& search_parameters);
1685  void SetupImprovementLimit(const RoutingSearchParameters& search_parameters);
1686  void SetupSearchMonitors(const RoutingSearchParameters& search_parameters);
1687  bool UsesLightPropagation(
1688  const RoutingSearchParameters& search_parameters) const;
1689  GetTabuVarsCallback tabu_var_callback_;
1690 
1691  // Detects implicit pickup delivery pairs. These pairs are
1692  // non-pickup/delivery pairs for which there exists a unary dimension such
1693  // that the demand d of the implicit pickup is positive and the demand of the
1694  // implicit delivery is equal to -d.
1695  void DetectImplicitPickupAndDeliveries();
1696 
1697  int GetVehicleStartClass(int64 start) const;
1698 
1699  void InitSameVehicleGroups(int number_of_groups) {
1700  same_vehicle_group_.assign(Size(), 0);
1701  same_vehicle_groups_.assign(number_of_groups, {});
1702  }
1703  void SetSameVehicleGroup(int index, int group) {
1704  same_vehicle_group_[index] = group;
1705  same_vehicle_groups_[group].push_back(index);
1706  }
1707 
1709  std::unique_ptr<Solver> solver_;
1710  int nodes_;
1711  int vehicles_;
1712  int max_active_vehicles_;
1713  Constraint* no_cycle_constraint_ = nullptr;
1715  std::vector<IntVar*> nexts_;
1716  std::vector<IntVar*> vehicle_vars_;
1717  std::vector<IntVar*> active_;
1718  // The following vectors are indexed by vehicle index.
1719  std::vector<IntVar*> vehicle_active_;
1720  std::vector<IntVar*> vehicle_costs_considered_;
1725  std::vector<IntVar*> is_bound_to_end_;
1726  mutable RevSwitch is_bound_to_end_ct_added_;
1728  absl::flat_hash_map<std::string, DimensionIndex> dimension_name_to_index_;
1730  // clang-format off
1734  std::vector<std::unique_ptr<GlobalDimensionCumulOptimizer> >
1735  global_dimension_optimizers_;
1736  absl::StrongVector<DimensionIndex, int> global_optimizer_index_;
1737  std::vector<std::unique_ptr<LocalDimensionCumulOptimizer> >
1738  local_dimension_optimizers_;
1739  std::vector<std::unique_ptr<LocalDimensionCumulOptimizer> >
1740  local_dimension_mp_optimizers_;
1741  // clang-format off
1742  absl::StrongVector<DimensionIndex, int> local_optimizer_index_;
1743  std::string primary_constrained_dimension_;
1745  IntVar* cost_ = nullptr;
1746  std::vector<int> vehicle_to_transit_cost_;
1747  std::vector<int64> fixed_cost_of_vehicle_;
1748  std::vector<CostClassIndex> cost_class_index_of_vehicle_;
1749  bool has_vehicle_with_zero_cost_class_;
1750  std::vector<int64> linear_cost_factor_of_vehicle_;
1751  std::vector<int64> quadratic_cost_factor_of_vehicle_;
1752  bool vehicle_amortized_cost_factors_set_;
1763  std::vector<bool> consider_empty_route_costs_;
1764 #ifndef SWIG
1766 #endif // SWIG
1767  bool costs_are_homogeneous_across_vehicles_;
1768  bool cache_callbacks_;
1769  mutable std::vector<CostCacheElement> cost_cache_;
1770  std::vector<VehicleClassIndex> vehicle_class_index_of_vehicle_;
1771 #ifndef SWIG
1773 #endif // SWIG
1774  VehicleTypeContainer vehicle_type_container_;
1775  std::function<int(int64)> vehicle_start_class_callback_;
1778  std::vector<std::vector<DisjunctionIndex> > index_to_disjunctions_;
1780  std::vector<ValuedNodes<int64> > same_vehicle_costs_;
1782 #ifndef SWIG
1783  std::vector<absl::flat_hash_set<int>> allowed_vehicles_;
1784 #endif // SWIG
1786  IndexPairs pickup_delivery_pairs_;
1787  IndexPairs implicit_pickup_delivery_pairs_without_alternatives_;
1788  std::vector<std::pair<DisjunctionIndex, DisjunctionIndex> >
1789  pickup_delivery_disjunctions_;
1790  // clang-format off
1791  // If node_index is a pickup, index_to_pickup_index_pairs_[node_index] is the
1792  // vector of pairs {pair_index, pickup_index} such that
1793  // (pickup_delivery_pairs_[pair_index].first)[pickup_index] == node_index
1794  std::vector<std::vector<std::pair<int, int> > > index_to_pickup_index_pairs_;
1795  // Same as above for deliveries.
1796  std::vector<std::vector<std::pair<int, int> > >
1797  index_to_delivery_index_pairs_;
1798  // clang-format on
1799  std::vector<PickupAndDeliveryPolicy> vehicle_pickup_delivery_policy_;
1800  // Same vehicle group to which a node belongs.
1801  std::vector<int> same_vehicle_group_;
1802  // Same vehicle node groups.
1803  std::vector<std::vector<int>> same_vehicle_groups_;
1804  // Node visit types
1805  // Variable index to visit type index.
1806  std::vector<int> index_to_visit_type_;
1807  // Variable index to VisitTypePolicy.
1808  std::vector<VisitTypePolicy> index_to_type_policy_;
1809  // clang-format off
1810  std::vector<std::vector<int> > single_nodes_of_type_;
1811  std::vector<std::vector<int> > pair_indices_of_type_;
1812 
1813  std::vector<absl::flat_hash_set<int> >
1814  hard_incompatible_types_per_type_index_;
1815  bool has_hard_type_incompatibilities_;
1816  std::vector<absl::flat_hash_set<int> >
1817  temporal_incompatible_types_per_type_index_;
1818  bool has_temporal_type_incompatibilities_;
1819 
1820  std::vector<std::vector<absl::flat_hash_set<int> > >
1821  same_vehicle_required_type_alternatives_per_type_index_;
1822  bool has_same_vehicle_type_requirements_;
1823  std::vector<std::vector<absl::flat_hash_set<int> > >
1824  required_type_alternatives_when_adding_type_index_;
1825  std::vector<std::vector<absl::flat_hash_set<int> > >
1826  required_type_alternatives_when_removing_type_index_;
1827  bool has_temporal_type_requirements_;
1828  absl::flat_hash_map</*type*/int, absl::flat_hash_set<VisitTypePolicy> >
1829  trivially_infeasible_visit_types_to_policies_;
1830 
1831  // Visit types sorted topologically based on required-->dependent requirement
1832  // arcs between the types (if the requirement/dependency graph is acyclic).
1833  // Visit types of the same topological level are sorted in each sub-vector
1834  // by decreasing requirement "tightness", computed as the pair of the two
1835  // following criteria:
1836  //
1837  // 1) How highly *dependent* this type is, determined by
1838  // (total number of required alternative sets for that type)
1839  // / (average number of types in the required alternative sets)
1840  // 2) How highly *required* this type t is, computed as
1841  // SUM_{S required set containing t} ( 1 / |S| ),
1842  // i.e. the sum of reverse number of elements of all required sets
1843  // containing the type t.
1844  //
1845  // The higher these two numbers, the tighter the type is wrt requirements.
1846  std::vector<std::vector<int> > topologically_sorted_visit_types_;
1847  // clang-format on
1848  int num_visit_types_;
1849  // Two indices are equivalent if they correspond to the same node (as given
1850  // to the constructors taking a RoutingIndexManager).
1851  std::vector<int> index_to_equivalence_class_;
1852  std::vector<int> index_to_vehicle_;
1853  std::vector<int64> starts_;
1854  std::vector<int64> ends_;
1855  // TODO(user): b/62478706 Once the port is done, this shouldn't be needed
1856  // anymore.
1857  RoutingIndexManager manager_;
1858  int start_end_count_;
1859  // Model status
1860  bool closed_ = false;
1861  Status status_ = ROUTING_NOT_SOLVED;
1862  bool enable_deep_serialization_ = true;
1863 
1864  // Search data
1865  std::vector<DecisionBuilder*> first_solution_decision_builders_;
1866  std::vector<IntVarFilteredDecisionBuilder*>
1867  first_solution_filtered_decision_builders_;
1868  Solver::IndexEvaluator2 first_solution_evaluator_;
1869  FirstSolutionStrategy::Value automatic_first_solution_strategy_ =
1870  FirstSolutionStrategy::UNSET;
1871  std::vector<LocalSearchOperator*> local_search_operators_;
1872  std::vector<SearchMonitor*> monitors_;
1873  SolutionCollector* collect_assignments_ = nullptr;
1874  SolutionCollector* collect_one_assignment_ = nullptr;
1875  SolutionCollector* packed_dimensions_assignment_collector_ = nullptr;
1876  DecisionBuilder* solve_db_ = nullptr;
1877  DecisionBuilder* improve_db_ = nullptr;
1878  DecisionBuilder* restore_assignment_ = nullptr;
1879  DecisionBuilder* restore_tmp_assignment_ = nullptr;
1880  Assignment* assignment_ = nullptr;
1881  Assignment* preassignment_ = nullptr;
1882  Assignment* tmp_assignment_ = nullptr;
1883  std::vector<IntVar*> extra_vars_;
1884  std::vector<IntervalVar*> extra_intervals_;
1885  std::vector<LocalSearchOperator*> extra_operators_;
1886  LocalSearchFilterManager* local_search_filter_manager_ = nullptr;
1887  LocalSearchFilterManager* feasibility_filter_manager_ = nullptr;
1888  LocalSearchFilterManager* strong_feasibility_filter_manager_ = nullptr;
1889  std::vector<LocalSearchFilterManager::FilterEvent> extra_filters_;
1890 #ifndef SWIG
1891  std::vector<std::pair<IntVar*, int64>> finalizer_variable_cost_pairs_;
1892  std::vector<std::pair<IntVar*, int64>> finalizer_variable_target_pairs_;
1893  absl::flat_hash_map<IntVar*, int> finalizer_variable_cost_index_;
1894  absl::flat_hash_set<IntVar*> finalizer_variable_target_set_;
1895  std::unique_ptr<SweepArranger> sweep_arranger_;
1896 #endif
1897 
1898  RegularLimit* limit_ = nullptr;
1899  RegularLimit* ls_limit_ = nullptr;
1900  RegularLimit* lns_limit_ = nullptr;
1901  RegularLimit* first_solution_lns_limit_ = nullptr;
1902 
1903  typedef std::pair<int64, int64> CacheKey;
1904  typedef absl::flat_hash_map<CacheKey, int64> TransitCallbackCache;
1905  typedef absl::flat_hash_map<CacheKey, StateDependentTransit>
1906  StateDependentTransitCallbackCache;
1907 
1908  std::vector<TransitCallback1> unary_transit_evaluators_;
1909  std::vector<TransitCallback2> transit_evaluators_;
1910  // The following vector stores a boolean per transit_evaluator_, indicating
1911  // whether the transits are all positive.
1912  // is_transit_evaluator_positive_ will be set to true only when registering a
1913  // callback via RegisterPositiveTransitCallback(), and to false otherwise.
1914  // The actual positivity of the transit values will only be checked in debug
1915  // mode, when calling RegisterPositiveTransitCallback().
1916  // Therefore, RegisterPositiveTransitCallback() should only be called when the
1917  // transits are known to be positive, as the positivity of a callback will
1918  // allow some improvements in the solver, but will entail in errors if the
1919  // transits are falsely assumed positive.
1920  std::vector<bool> is_transit_evaluator_positive_;
1921  std::vector<VariableIndexEvaluator2> state_dependent_transit_evaluators_;
1922  std::vector<std::unique_ptr<StateDependentTransitCallbackCache>>
1923  state_dependent_transit_evaluators_cache_;
1924 
1925  friend class RoutingDimension;
1927 
1929 };
1930 
1933  public:
1935  static const char kLightElement[];
1936  static const char kLightElement2[];
1937  static const char kRemoveValues[];
1938 };
1939 
1940 #if !defined(SWIG)
1944  public:
1950  struct Tasks {
1951  int num_chain_tasks = 0;
1952  std::vector<int64> start_min;
1953  std::vector<int64> start_max;
1954  std::vector<int64> duration_min;
1955  std::vector<int64> duration_max;
1956  std::vector<int64> end_min;
1957  std::vector<int64> end_max;
1958  std::vector<bool> is_preemptible;
1959  std::vector<const SortedDisjointIntervalList*> forbidden_intervals;
1960  std::vector<std::pair<int64, int64>> distance_duration;
1961  int64 span_min = 0;
1962  int64 span_max = kint64max;
1963 
1964  void Clear() {
1965  start_min.clear();
1966  start_max.clear();
1967  duration_min.clear();
1968  duration_max.clear();
1969  end_min.clear();
1970  end_max.clear();
1971  is_preemptible.clear();
1972  forbidden_intervals.clear();
1973  distance_duration.clear();
1974  span_min = 0;
1975  span_max = kint64max;
1976  num_chain_tasks = 0;
1977  }
1978  };
1979 
1982  bool Propagate(Tasks* tasks);
1983 
1985  bool Precedences(Tasks* tasks);
1988  bool MirrorTasks(Tasks* tasks);
1990  bool EdgeFinding(Tasks* tasks);
1993  bool DetectablePrecedencesWithChain(Tasks* tasks);
1995  bool ForbiddenIntervals(Tasks* tasks);
1997  bool DistanceDuration(Tasks* tasks);
2000  bool ChainSpanMin(Tasks* tasks);
2005  bool ChainSpanMinDynamic(Tasks* tasks);
2006 
2007  private:
2010  sat::ThetaLambdaTree<int64> theta_lambda_tree_;
2012  std::vector<int> tasks_by_start_min_;
2013  std::vector<int> tasks_by_end_max_;
2014  std::vector<int> event_of_task_;
2015  std::vector<int> nonchain_tasks_by_start_max_;
2017  std::vector<int64> total_duration_before_;
2018 };
2019 
2021  std::vector<int64> min_travels;
2022  std::vector<int64> max_travels;
2023  std::vector<int64> pre_travels;
2024  std::vector<int64> post_travels;
2025 };
2026 
2027 void AppendTasksFromPath(const std::vector<int64>& path,
2028  const TravelBounds& travel_bounds,
2029  const RoutingDimension& dimension,
2031 void AppendTasksFromIntervals(const std::vector<IntervalVar*>& intervals,
2033 void FillPathEvaluation(const std::vector<int64>& path,
2034  const RoutingModel::TransitCallback2& evaluator,
2035  std::vector<int64>* values);
2036 void FillTravelBoundsOfVehicle(int vehicle, const std::vector<int64>& path,
2037  const RoutingDimension& dimension,
2038  TravelBounds* travel_bounds);
2039 #endif // !defined(SWIG)
2040 
2052  public:
2053  explicit GlobalVehicleBreaksConstraint(const RoutingDimension* dimension);
2054  std::string DebugString() const override {
2055  return "GlobalVehicleBreaksConstraint";
2056  }
2057 
2058  void Post() override;
2059  void InitialPropagate() override;
2060 
2061  private:
2062  void PropagateNode(int node);
2063  void PropagateVehicle(int vehicle);
2064  void PropagateMaxBreakDistance(int vehicle);
2065 
2066  const RoutingModel* model_;
2067  const RoutingDimension* const dimension_;
2068  std::vector<Demon*> vehicle_demons_;
2069  std::vector<int64> path_;
2070 
2075  void FillPartialPathOfVehicle(int vehicle);
2076  void FillPathTravels(const std::vector<int64>& path);
2077 
2088  class TaskTranslator {
2089  public:
2090  TaskTranslator(IntVar* start, int64 before_start, int64 after_start)
2091  : start_(start),
2092  before_start_(before_start),
2093  after_start_(after_start) {}
2094  explicit TaskTranslator(IntervalVar* interval) : interval_(interval) {}
2095  TaskTranslator() {}
2096 
2097  void SetStartMin(int64 value) {
2098  if (start_ != nullptr) {
2099  start_->SetMin(CapAdd(before_start_, value));
2100  } else if (interval_ != nullptr) {
2101  interval_->SetStartMin(value);
2102  }
2103  }
2104  void SetStartMax(int64 value) {
2105  if (start_ != nullptr) {
2106  start_->SetMax(CapAdd(before_start_, value));
2107  } else if (interval_ != nullptr) {
2108  interval_->SetStartMax(value);
2109  }
2110  }
2111  void SetDurationMin(int64 value) {
2112  if (interval_ != nullptr) {
2113  interval_->SetDurationMin(value);
2114  }
2115  }
2116  void SetEndMin(int64 value) {
2117  if (start_ != nullptr) {
2118  start_->SetMin(CapSub(value, after_start_));
2119  } else if (interval_ != nullptr) {
2120  interval_->SetEndMin(value);
2121  }
2122  }
2123  void SetEndMax(int64 value) {
2124  if (start_ != nullptr) {
2125  start_->SetMax(CapSub(value, after_start_));
2126  } else if (interval_ != nullptr) {
2127  interval_->SetEndMax(value);
2128  }
2129  }
2130 
2131  private:
2132  IntVar* start_ = nullptr;
2133  int64 before_start_;
2134  int64 after_start_;
2135  IntervalVar* interval_ = nullptr;
2136  };
2137 
2139  std::vector<TaskTranslator> task_translators_;
2140 
2142  DisjunctivePropagator disjunctive_propagator_;
2143  DisjunctivePropagator::Tasks tasks_;
2144 
2146  TravelBounds travel_bounds_;
2147 };
2148 
2150  public:
2151  explicit TypeRegulationsChecker(const RoutingModel& model);
2153 
2154  bool CheckVehicle(int vehicle,
2155  const std::function<int64(int64)>& next_accessor);
2156 
2157  protected:
2158 #ifndef SWIG
2160 #endif // SWIG
2161 
2166  int num_type_added_to_vehicle = 0;
2172  int num_type_removed_from_vehicle = 0;
2177  int position_of_last_type_on_vehicle_up_to_visit = -1;
2178  };
2179 
2184  bool TypeOccursOnRoute(int type) const;
2191  bool TypeCurrentlyOnRoute(int type, int pos) const;
2192 
2193  void InitializeCheck(int vehicle,
2194  const std::function<int64(int64)>& next_accessor);
2195  virtual void OnInitializeCheck() {}
2196  virtual bool HasRegulationsToCheck() const = 0;
2197  virtual bool CheckTypeRegulations(int type, VisitTypePolicy policy,
2198  int pos) = 0;
2199  virtual bool FinalizeCheck() const { return true; }
2200 
2202 
2203  private:
2204  std::vector<TypePolicyOccurrence> occurrences_of_type_;
2205  std::vector<int64> current_route_visits_;
2206 };
2207 
2210  public:
2212  bool check_hard_incompatibilities);
2214 
2215  private:
2216  bool HasRegulationsToCheck() const override;
2217  bool CheckTypeRegulations(int type, VisitTypePolicy policy, int pos) override;
2221  bool check_hard_incompatibilities_;
2222 };
2223 
2226  public:
2230 
2231  private:
2232  bool HasRegulationsToCheck() const override;
2233  void OnInitializeCheck() override {
2234  types_with_same_vehicle_requirements_on_route_.clear();
2235  }
2236  // clang-format off
2239  bool CheckRequiredTypesCurrentlyOnRoute(
2240  const std::vector<absl::flat_hash_set<int> >& required_type_alternatives,
2241  int pos);
2242  // clang-format on
2243  bool CheckTypeRegulations(int type, VisitTypePolicy policy, int pos) override;
2244  bool FinalizeCheck() const override;
2245 
2246  absl::flat_hash_set<int> types_with_same_vehicle_requirements_on_route_;
2247 };
2248 
2290  public:
2291  explicit TypeRegulationsConstraint(const RoutingModel& model);
2292 
2293  void Post() override;
2294  void InitialPropagate() override;
2295 
2296  private:
2297  void PropagateNodeRegulations(int node);
2298  void CheckRegulationsOnVehicle(int vehicle);
2299 
2300  const RoutingModel& model_;
2301  TypeIncompatibilityChecker incompatibility_checker_;
2302  TypeRequirementChecker requirement_checker_;
2303  std::vector<Demon*> vehicle_demons_;
2304 };
2305 #if !defined SWIG
2319  public:
2320  struct BoundCost {
2323  };
2324  SimpleBoundCosts(int num_bounds, BoundCost default_bound_cost)
2325  : bound_costs_(num_bounds, default_bound_cost) {}
2326  BoundCost& bound_cost(int element) { return bound_costs_[element]; }
2327  BoundCost bound_cost(int element) const { return bound_costs_[element]; }
2328  int Size() { return bound_costs_.size(); }
2331 
2332  private:
2333  std::vector<BoundCost> bound_costs_;
2334 };
2335 #endif // !defined SWIG
2336 
2354 // TODO(user): Break constraints need to know the service time of nodes
2358  public:
2359  ~RoutingDimension();
2361  RoutingModel* model() const { return model_; }
2365  int64 GetTransitValue(int64 from_index, int64 to_index, int64 vehicle) const;
2369  int64 vehicle_class) const {
2370  return model_->TransitCallback(class_evaluators_[vehicle_class])(from_index,
2371  to_index);
2372  }
2375  IntVar* CumulVar(int64 index) const { return cumuls_[index]; }
2376  IntVar* TransitVar(int64 index) const { return transits_[index]; }
2377  IntVar* FixedTransitVar(int64 index) const { return fixed_transits_[index]; }
2378  IntVar* SlackVar(int64 index) const { return slacks_[index]; }
2379 
2380 #if !defined(SWIGPYTHON)
2383  const std::vector<IntVar*>& cumuls() const { return cumuls_; }
2384  const std::vector<IntVar*>& fixed_transits() const { return fixed_transits_; }
2385  const std::vector<IntVar*>& transits() const { return transits_; }
2386  const std::vector<IntVar*>& slacks() const { return slacks_; }
2387 #if !defined(SWIGCSHARP) && !defined(SWIGJAVA)
2389  const std::vector<SortedDisjointIntervalList>& forbidden_intervals() const {
2390  return forbidden_intervals_;
2391  }
2393  SortedDisjointIntervalList GetAllowedIntervalsInRange(int64 index,
2394  int64 min_value,
2395  int64 max_value) const;
2399  int64 min_value) const {
2400  DCHECK_LT(index, forbidden_intervals_.size());
2401  const SortedDisjointIntervalList& forbidden_intervals =
2402  forbidden_intervals_[index];
2403  const auto first_forbidden_interval_it =
2404  forbidden_intervals.FirstIntervalGreaterOrEqual(min_value);
2405  if (first_forbidden_interval_it != forbidden_intervals.end() &&
2406  min_value >= first_forbidden_interval_it->start) {
2408  return CapAdd(first_forbidden_interval_it->end, 1);
2409  }
2411  return min_value;
2412  }
2418  int64 max_value) const {
2419  DCHECK_LT(index, forbidden_intervals_.size());
2420  const SortedDisjointIntervalList& forbidden_intervals =
2421  forbidden_intervals_[index];
2422  const auto last_forbidden_interval_it =
2423  forbidden_intervals.LastIntervalLessOrEqual(max_value);
2424  if (last_forbidden_interval_it != forbidden_intervals.end() &&
2425  max_value <= last_forbidden_interval_it->end) {
2427  return CapSub(last_forbidden_interval_it->start, 1);
2428  }
2430  return max_value;
2431  }
2433  const std::vector<int64>& vehicle_capacities() const {
2434  return vehicle_capacities_;
2435  }
2439  return model_->TransitCallback(
2440  class_evaluators_[vehicle_to_class_[vehicle]]);
2441  }
2446  int vehicle) const {
2447  return model_->UnaryTransitCallbackOrNull(
2448  class_evaluators_[vehicle_to_class_[vehicle]]);
2449  }
2452  bool AreVehicleTransitsPositive(int vehicle) const {
2453  return model()->is_transit_evaluator_positive_
2454  [class_evaluators_[vehicle_to_class_[vehicle]]];
2455  }
2456  int vehicle_to_class(int vehicle) const { return vehicle_to_class_[vehicle]; }
2457 #endif
2458 #endif
2462  void SetSpanUpperBoundForVehicle(int64 upper_bound, int vehicle);
2469  void SetSpanCostCoefficientForVehicle(int64 coefficient, int vehicle);
2470  void SetSpanCostCoefficientForAllVehicles(int64 coefficient);
2477  void SetGlobalSpanCostCoefficient(int64 coefficient);
2478 
2479 #ifndef SWIG
2484  void SetCumulVarPiecewiseLinearCost(int64 index,
2485  const PiecewiseLinearFunction& cost);
2488  bool HasCumulVarPiecewiseLinearCost(int64 index) const;
2491  const PiecewiseLinearFunction* GetCumulVarPiecewiseLinearCost(
2492  int64 index) const;
2493 #endif
2494 
2503  void SetCumulVarSoftUpperBound(int64 index, int64 upper_bound,
2504  int64 coefficient);
2507  bool HasCumulVarSoftUpperBound(int64 index) const;
2511  int64 GetCumulVarSoftUpperBound(int64 index) const;
2515  int64 GetCumulVarSoftUpperBoundCoefficient(int64 index) const;
2516 
2526  void SetCumulVarSoftLowerBound(int64 index, int64 lower_bound,
2527  int64 coefficient);
2530  bool HasCumulVarSoftLowerBound(int64 index) const;
2534  int64 GetCumulVarSoftLowerBound(int64 index) const;
2538  int64 GetCumulVarSoftLowerBoundCoefficient(int64 index) const;
2554  // TODO(user): Remove if !defined when routing.i is repaired.
2555 #if !defined(SWIGPYTHON)
2556  void SetBreakIntervalsOfVehicle(std::vector<IntervalVar*> breaks, int vehicle,
2557  int pre_travel_evaluator,
2558  int post_travel_evaluator);
2559 #endif // !defined(SWIGPYTHON)
2560 
2562  void SetBreakIntervalsOfVehicle(std::vector<IntervalVar*> breaks, int vehicle,
2563  std::vector<int64> node_visit_transits);
2564 
2569  void SetBreakDistanceDurationOfVehicle(int64 distance, int64 duration,
2570  int vehicle);
2573  void InitializeBreaks();
2575  bool HasBreakConstraints() const;
2576 #if !defined(SWIGPYTHON)
2579  void SetBreakIntervalsOfVehicle(
2580  std::vector<IntervalVar*> breaks, int vehicle,
2581  std::vector<int64> node_visit_transits,
2582  std::function<int64(int64, int64)> group_delays);
2583 
2585  const std::vector<IntervalVar*>& GetBreakIntervalsOfVehicle(
2586  int vehicle) const;
2589  // clang-format off
2590  const std::vector<std::pair<int64, int64> >&
2591  GetBreakDistanceDurationOfVehicle(int vehicle) const;
2592  // clang-format on
2593 #endif
2594  int GetPreTravelEvaluatorOfVehicle(int vehicle) const;
2595  int GetPostTravelEvaluatorOfVehicle(int vehicle) const;
2596 
2598  const RoutingDimension* base_dimension() const { return base_dimension_; }
2606  int64 ShortestTransitionSlack(int64 node) const;
2607 
2609  const std::string& name() const { return name_; }
2610 
2612 #ifndef SWIG
2614  return path_precedence_graph_;
2615  }
2616 #endif // SWIG
2617 
2627  typedef std::function<int64(int, int)> PickupToDeliveryLimitFunction;
2628 
2629  void SetPickupToDeliveryLimitFunctionForPair(
2630  PickupToDeliveryLimitFunction limit_function, int pair_index);
2631 
2632  bool HasPickupToDeliveryLimits() const;
2633 #ifndef SWIG
2634  int64 GetPickupToDeliveryLimitForPair(int pair_index, int pickup,
2635  int delivery) const;
2636 
2641  };
2642 
2644  node_precedences_.push_back(precedence);
2645  }
2646  const std::vector<NodePrecedence>& GetNodePrecedences() const {
2647  return node_precedences_;
2648  }
2649 #endif // SWIG
2650 
2651  void AddNodePrecedence(int64 first_node, int64 second_node, int64 offset) {
2652  AddNodePrecedence({first_node, second_node, offset});
2653  }
2654 
2655  int64 GetSpanUpperBoundForVehicle(int vehicle) const {
2656  return vehicle_span_upper_bounds_[vehicle];
2657  }
2658 #ifndef SWIG
2659  const std::vector<int64>& vehicle_span_upper_bounds() const {
2660  return vehicle_span_upper_bounds_;
2661  }
2662 #endif // SWIG
2664  return vehicle_span_cost_coefficients_[vehicle];
2665  }
2666 #ifndef SWIG
2667  const std::vector<int64>& vehicle_span_cost_coefficients() const {
2668  return vehicle_span_cost_coefficients_;
2669  }
2670 #endif // SWIG
2672  return global_span_cost_coefficient_;
2673  }
2674 
2676  DCHECK_GE(global_optimizer_offset_, 0);
2677  return global_optimizer_offset_;
2678  }
2680  if (vehicle >= local_optimizer_offset_for_vehicle_.size()) {
2681  return 0;
2682  }
2683  DCHECK_GE(local_optimizer_offset_for_vehicle_[vehicle], 0);
2684  return local_optimizer_offset_for_vehicle_[vehicle];
2685  }
2686 #if !defined SWIG
2690  int vehicle) {
2691  if (!HasSoftSpanUpperBounds()) {
2692  vehicle_soft_span_upper_bound_ = absl::make_unique<SimpleBoundCosts>(
2693  model_->vehicles(), SimpleBoundCosts::BoundCost{kint64max, 0});
2694  }
2695  vehicle_soft_span_upper_bound_->bound_cost(vehicle) = bound_cost;
2696  }
2697  bool HasSoftSpanUpperBounds() const {
2698  return vehicle_soft_span_upper_bound_ != nullptr;
2699  }
2701  int vehicle) const {
2702  DCHECK(HasSoftSpanUpperBounds());
2703  return vehicle_soft_span_upper_bound_->bound_cost(vehicle);
2704  }
2708  SimpleBoundCosts::BoundCost bound_cost, int vehicle) {
2709  if (!HasQuadraticCostSoftSpanUpperBounds()) {
2710  vehicle_quadratic_cost_soft_span_upper_bound_ =
2711  absl::make_unique<SimpleBoundCosts>(
2712  model_->vehicles(), SimpleBoundCosts::BoundCost{kint64max, 0});
2713  }
2714  vehicle_quadratic_cost_soft_span_upper_bound_->bound_cost(vehicle) =
2715  bound_cost;
2716  }
2718  return vehicle_quadratic_cost_soft_span_upper_bound_ != nullptr;
2719  }
2721  int vehicle) const {
2722  DCHECK(HasQuadraticCostSoftSpanUpperBounds());
2723  return vehicle_quadratic_cost_soft_span_upper_bound_->bound_cost(vehicle);
2724  }
2725 #endif
2726 
2727  private:
2728  struct SoftBound {
2729  IntVar* var;
2730  int64 bound;
2732  };
2733 
2734  struct PiecewiseLinearCost {
2735  PiecewiseLinearCost() : var(nullptr), cost(nullptr) {}
2736  IntVar* var;
2737  std::unique_ptr<PiecewiseLinearFunction> cost;
2738  };
2739 
2740  class SelfBased {};
2741  RoutingDimension(RoutingModel* model, std::vector<int64> vehicle_capacities,
2742  const std::string& name,
2743  const RoutingDimension* base_dimension);
2744  RoutingDimension(RoutingModel* model, std::vector<int64> vehicle_capacities,
2745  const std::string& name, SelfBased);
2746  void Initialize(const std::vector<int>& transit_evaluators,
2747  const std::vector<int>& state_dependent_transit_evaluators,
2748  int64 slack_max);
2749  void InitializeCumuls();
2750  void InitializeTransits(
2751  const std::vector<int>& transit_evaluators,
2752  const std::vector<int>& state_dependent_transit_evaluators,
2753  int64 slack_max);
2754  void InitializeTransitVariables(int64 slack_max);
2756  void SetupCumulVarSoftUpperBoundCosts(
2757  std::vector<IntVar*>* cost_elements) const;
2759  void SetupCumulVarSoftLowerBoundCosts(
2760  std::vector<IntVar*>* cost_elements) const;
2761  void SetupCumulVarPiecewiseLinearCosts(
2762  std::vector<IntVar*>* cost_elements) const;
2765  void SetupGlobalSpanCost(std::vector<IntVar*>* cost_elements) const;
2766  void SetupSlackAndDependentTransitCosts() const;
2768  void CloseModel(bool use_light_propagation);
2769 
2770  void SetOffsetForGlobalOptimizer(int64 offset) {
2771  global_optimizer_offset_ = std::max(Zero(), offset);
2772  }
2774  void SetVehicleOffsetsForLocalOptimizer(std::vector<int64> offsets) {
2776  std::transform(offsets.begin(), offsets.end(), offsets.begin(),
2777  [](int64 offset) { return std::max(Zero(), offset); });
2778  local_optimizer_offset_for_vehicle_ = std::move(offsets);
2779  }
2780 
2781  std::vector<IntVar*> cumuls_;
2782  std::vector<SortedDisjointIntervalList> forbidden_intervals_;
2783  std::vector<IntVar*> capacity_vars_;
2784  const std::vector<int64> vehicle_capacities_;
2785  std::vector<IntVar*> transits_;
2786  std::vector<IntVar*> fixed_transits_;
2789  std::vector<int> class_evaluators_;
2790  std::vector<int64> vehicle_to_class_;
2791 #ifndef SWIG
2792  ReverseArcListGraph<int, int> path_precedence_graph_;
2793 #endif
2794  // For every {first_node, second_node, offset} element in node_precedences_,
2795  // if both first_node and second_node are performed, then
2796  // cumuls_[second_node] must be greater than (or equal to)
2797  // cumuls_[first_node] + offset.
2798  std::vector<NodePrecedence> node_precedences_;
2799 
2800  // The transits of a dimension may depend on its cumuls or the cumuls of
2801  // another dimension. There can be no cycles, except for self loops, a
2802  // typical example for this is a time dimension.
2803  const RoutingDimension* const base_dimension_;
2804 
2805  // Values in state_dependent_class_evaluators_ correspond to the evaluators
2806  // in RoutingModel::state_dependent_transit_evaluators_ for each vehicle
2807  // class.
2808  std::vector<int> state_dependent_class_evaluators_;
2809  std::vector<int64> state_dependent_vehicle_to_class_;
2810 
2811  // For each pickup/delivery pair_index for which limits have been set,
2812  // pickup_to_delivery_limits_per_pair_index_[pair_index] contains the
2813  // PickupToDeliveryLimitFunction for the pickup and deliveries in this pair.
2814  std::vector<PickupToDeliveryLimitFunction>
2815  pickup_to_delivery_limits_per_pair_index_;
2816 
2817  // Used if some vehicle has breaks in this dimension, typically time.
2818  bool break_constraints_are_initialized_ = false;
2819  // clang-format off
2820  std::vector<std::vector<IntervalVar*> > vehicle_break_intervals_;
2821  std::vector<std::vector<std::pair<int64, int64> > >
2822  vehicle_break_distance_duration_;
2823  // clang-format on
2824  // For each vehicle, stores the part of travel that is made directly
2825  // after (before) the departure (arrival) node of the travel.
2826  // These parts of the travel are non-interruptible, in particular by a break.
2827  std::vector<int> vehicle_pre_travel_evaluators_;
2828  std::vector<int> vehicle_post_travel_evaluators_;
2829 
2830  std::vector<IntVar*> slacks_;
2831  std::vector<IntVar*> dependent_transits_;
2832  std::vector<int64> vehicle_span_upper_bounds_;
2833  int64 global_span_cost_coefficient_;
2834  std::vector<int64> vehicle_span_cost_coefficients_;
2835  std::vector<SoftBound> cumul_var_soft_upper_bound_;
2836  std::vector<SoftBound> cumul_var_soft_lower_bound_;
2837  std::vector<PiecewiseLinearCost> cumul_var_piecewise_linear_cost_;
2838  RoutingModel* const model_;
2839  const std::string name_;
2840  int64 global_optimizer_offset_;
2841  std::vector<int64> local_optimizer_offset_for_vehicle_;
2843  std::unique_ptr<SimpleBoundCosts> vehicle_soft_span_upper_bound_;
2844  std::unique_ptr<SimpleBoundCosts>
2845  vehicle_quadratic_cost_soft_span_upper_bound_;
2846  friend class RoutingModel;
2848  friend void AppendDimensionCumulFilters(
2849  const std::vector<RoutingDimension*>& dimensions,
2850  const RoutingSearchParameters& parameters, bool filter_objective_cost,
2851  std::vector<LocalSearchFilterManager::FilterEvent>* filters);
2852 
2854 };
2855 
2856 #ifndef SWIG
2860  public:
2861  explicit SweepArranger(const std::vector<std::pair<int64, int64>>& points);
2862  virtual ~SweepArranger() {}
2863  void ArrangeIndices(std::vector<int64>* indices);
2864  void SetSectors(int sectors) { sectors_ = sectors; }
2865 
2866  private:
2867  std::vector<int> coordinates_;
2868  int sectors_;
2869 
2871 };
2872 #endif
2873 
2876 DecisionBuilder* MakeSetValuesFromTargets(Solver* solver,
2877  std::vector<IntVar*> variables,
2878  std::vector<int64> targets);
2879 
2880 #ifndef SWIG
2885  public:
2887  const RoutingModel::VehicleTypeContainer& vehicle_type_container)
2888  : vehicle_type_container_(&vehicle_type_container) {}
2889 
2890  int NumTypes() const { return vehicle_type_container_->NumTypes(); }
2891 
2892  int Type(int vehicle) const { return vehicle_type_container_->Type(vehicle); }
2893 
2896  void Reset(const std::function<bool(int)>& store_vehicle);
2897 
2900  void Update(const std::function<bool(int)>& remove_vehicle);
2901 
2902  int GetLowestFixedCostVehicleOfType(int type) const {
2903  DCHECK_LT(type, NumTypes());
2904  const std::set<VehicleClassEntry>& vehicle_classes =
2905  sorted_vehicle_classes_per_type_[type];
2906  if (vehicle_classes.empty()) {
2907  return -1;
2908  }
2909  const int vehicle_class = (vehicle_classes.begin())->vehicle_class;
2910  DCHECK(!vehicles_per_vehicle_class_[vehicle_class].empty());
2911  return vehicles_per_vehicle_class_[vehicle_class][0];
2912  }
2913 
2914  void ReinjectVehicleOfClass(int vehicle, int vehicle_class,
2915  int64 fixed_cost) {
2916  std::vector<int>& vehicles = vehicles_per_vehicle_class_[vehicle_class];
2917  if (vehicles.empty()) {
2920  std::set<VehicleClassEntry>& vehicle_classes =
2921  sorted_vehicle_classes_per_type_[Type(vehicle)];
2922  const auto& insertion =
2923  vehicle_classes.insert({vehicle_class, fixed_cost});
2924  DCHECK(insertion.second);
2925  }
2926  vehicles.push_back(vehicle);
2927  }
2928 
2937  std::pair<int, int> GetCompatibleVehicleOfType(
2938  int type, std::function<bool(int)> vehicle_is_compatible,
2939  std::function<bool(int)> stop_and_return_vehicle);
2940 
2941  private:
2942  using VehicleClassEntry =
2944  const RoutingModel::VehicleTypeContainer* const vehicle_type_container_;
2945  // clang-format off
2946  std::vector<std::set<VehicleClassEntry> > sorted_vehicle_classes_per_type_;
2947  std::vector<std::vector<int> > vehicles_per_vehicle_class_;
2948  // clang-format on
2949 };
2950 
2963 
2965 // TODO(user): Eventually move this to the core CP solver library
2968  public:
2970  std::unique_ptr<IntVarFilteredHeuristic> heuristic);
2971 
2973 
2974  Decision* Next(Solver* solver) override;
2975 
2976  std::string DebugString() const override;
2977 
2979  int64 number_of_decisions() const;
2980  int64 number_of_rejects() const;
2981 
2982  private:
2983  const std::unique_ptr<IntVarFilteredHeuristic> heuristic_;
2984 };
2985 
2988  public:
2989  IntVarFilteredHeuristic(Solver* solver, const std::vector<IntVar*>& vars,
2990  LocalSearchFilterManager* filter_manager);
2991 
2993 
2996  Assignment* const BuildSolution();
2997 
3000  int64 number_of_decisions() const { return number_of_decisions_; }
3001  int64 number_of_rejects() const { return number_of_rejects_; }
3002 
3003  virtual std::string DebugString() const { return "IntVarFilteredHeuristic"; }
3004 
3005  protected:
3007  void ResetSolution();
3009  virtual bool InitializeSolution() { return true; }
3011  virtual bool BuildSolutionInternal() = 0;
3015  bool Commit();
3017  virtual bool StopSearch() { return false; }
3021  if (!is_in_delta_[index]) {
3022  delta_->FastAdd(vars_[index])->SetValue(value);
3023  delta_indices_.push_back(index);
3024  is_in_delta_[index] = true;
3025  } else {
3026  delta_->SetValue(vars_[index], value);
3027  }
3028  }
3032  return assignment_->IntVarContainer().Element(index).Value();
3033  }
3035  bool Contains(int64 index) const {
3036  return assignment_->IntVarContainer().Element(index).Var() != nullptr;
3037  }
3040  int Size() const { return vars_.size(); }
3042  IntVar* Var(int64 index) const { return vars_[index]; }
3044  void SynchronizeFilters();
3045 
3047 
3048  private:
3051  bool FilterAccept();
3052 
3053  Solver* solver_;
3054  const std::vector<IntVar*> vars_;
3055  Assignment* const delta_;
3056  std::vector<int> delta_indices_;
3057  std::vector<bool> is_in_delta_;
3058  Assignment* const empty_;
3059  LocalSearchFilterManager* filter_manager_;
3061  int64 number_of_decisions_;
3062  int64 number_of_rejects_;
3063 };
3064 
3067  public:
3069  LocalSearchFilterManager* filter_manager);
3072  const Assignment* BuildSolutionFromRoutes(
3073  const std::function<int64(int64)>& next_accessor);
3074  RoutingModel* model() const { return model_; }
3076  int GetStartChainEnd(int vehicle) const { return start_chain_ends_[vehicle]; }
3078  int GetEndChainStart(int vehicle) const { return end_chain_starts_[vehicle]; }
3081  void MakeDisjunctionNodesUnperformed(int64 node);
3083  void MakeUnassignedNodesUnperformed();
3088  void MakePartiallyPerformedPairsUnperformed();
3089 
3090  protected:
3091  bool StopSearch() override { return model_->CheckLimit(); }
3092  virtual void SetVehicleIndex(int64 node, int vehicle) {}
3093  virtual void ResetVehicleIndices() {}
3094  bool VehicleIsEmpty(int vehicle) const {
3095  return Value(model()->Start(vehicle)) == model()->End(vehicle);
3096  }
3097 
3098  private:
3100  bool InitializeSolution() override;
3101 
3102  RoutingModel* const model_;
3103  std::vector<int64> start_chain_ends_;
3104  std::vector<int64> end_chain_starts_;
3105 };
3106 
3108  public:
3111  RoutingModel* model, std::function<int64(int64, int64, int64)> evaluator,
3112  std::function<int64(int64)> penalty_evaluator,
3113  LocalSearchFilterManager* filter_manager);
3115 
3116  protected:
3117  typedef std::pair<int64, int64> ValuedPosition;
3118  struct StartEndValue {
3120  int vehicle;
3121 
3122  bool operator<(const StartEndValue& other) const {
3123  return std::tie(distance, vehicle) <
3124  std::tie(other.distance, other.vehicle);
3125  }
3126  };
3127  typedef std::pair<StartEndValue, /*seed_node*/ int> Seed;
3128 
3134  // clang-format off
3135  std::vector<std::vector<StartEndValue> >
3136  ComputeStartEndDistanceForVehicles(const std::vector<int>& vehicles);
3137 
3142  template <class Queue>
3144  std::vector<std::vector<StartEndValue> >* start_end_distances_per_node,
3145  Queue* priority_queue);
3146  // clang-format on
3147 
3152  void InsertBetween(int64 node, int64 predecessor, int64 successor);
3157  void AppendEvaluatedPositionsAfter(
3158  int64 node_to_insert, int64 start, int64 next_after_start, int64 vehicle,
3159  std::vector<ValuedPosition>* valued_positions);
3164  // TODO(user): Replace 'insert_before' and 'insert_after' by 'predecessor'
3165  // and 'successor' in the code.
3166  int64 GetInsertionCostForNodeAtPosition(int64 node_to_insert,
3167  int64 insert_after,
3168  int64 insert_before,
3169  int vehicle) const;
3172  int64 GetUnperformedValue(int64 node_to_insert) const;
3173 
3174  std::function<int64(int64, int64, int64)> evaluator_;
3175  std::function<int64(int64)> penalty_evaluator_;
3176 };
3177 
3187  public:
3210  };
3211 
3214  RoutingModel* model, std::function<int64(int64, int64, int64)> evaluator,
3215  std::function<int64(int64)> penalty_evaluator,
3216  LocalSearchFilterManager* filter_manager,
3219  bool BuildSolutionInternal() override;
3220  std::string DebugString() const override {
3221  return "GlobalCheapestInsertionFilteredHeuristic";
3222  }
3223 
3224  private:
3225  class PairEntry;
3226  class NodeEntry;
3227  typedef absl::flat_hash_set<PairEntry*> PairEntries;
3228  typedef absl::flat_hash_set<NodeEntry*> NodeEntries;
3229 
3236  void InsertPairsAndNodesByRequirementTopologicalOrder();
3237 
3244  void InsertPairs(const std::vector<int>& pair_indices);
3245 
3252  bool InsertPairEntryUsingEmptyVehicleTypeCurator(
3253  const std::vector<int>& pair_indices, PairEntry* const pair_entry,
3254  AdjustablePriorityQueue<PairEntry>* priority_queue,
3255  std::vector<PairEntries>* pickup_to_entries,
3256  std::vector<PairEntries>* delivery_to_entries);
3257 
3265  void InsertNodesOnRoutes(const std::vector<int>& nodes,
3266  const absl::flat_hash_set<int>& vehicles);
3267 
3275  bool InsertNodeEntryUsingEmptyVehicleTypeCurator(
3276  const std::vector<int>& nodes, bool all_vehicles,
3277  NodeEntry* const node_entry,
3278  AdjustablePriorityQueue<NodeEntry>* priority_queue,
3279  std::vector<NodeEntries>* position_to_node_entries);
3280 
3286  void SequentialInsertNodes(const std::vector<int>& nodes);
3287 
3291  void DetectUsedVehicles(std::vector<bool>* is_vehicle_used,
3292  std::vector<int>* unused_vehicles,
3293  absl::flat_hash_set<int>* used_vehicles);
3294 
3298  void InsertFarthestNodesAsSeeds();
3299 
3308  template <class Queue>
3309  int InsertSeedNode(
3310  std::vector<std::vector<StartEndValue>>* start_end_distances_per_node,
3311  Queue* priority_queue, std::vector<bool>* is_vehicle_used);
3312  // clang-format on
3313 
3316  void InitializePairPositions(
3317  const std::vector<int>& pair_indices,
3318  AdjustablePriorityQueue<PairEntry>* priority_queue,
3319  std::vector<PairEntries>* pickup_to_entries,
3320  std::vector<PairEntries>* delivery_to_entries);
3326  void InitializeInsertionEntriesPerformingPair(
3327  int64 pickup, int64 delivery,
3328  AdjustablePriorityQueue<PairEntry>* priority_queue,
3329  std::vector<PairEntries>* pickup_to_entries,
3330  std::vector<PairEntries>* delivery_to_entries);
3334  void UpdateAfterPairInsertion(
3335  const std::vector<int>& pair_indices, int vehicle, int64 pickup,
3336  int64 pickup_position, int64 delivery, int64 delivery_position,
3337  AdjustablePriorityQueue<PairEntry>* priority_queue,
3338  std::vector<PairEntries>* pickup_to_entries,
3339  std::vector<PairEntries>* delivery_to_entries);
3342  void UpdatePairPositions(const std::vector<int>& pair_indices, int vehicle,
3343  int64 insert_after,
3344  AdjustablePriorityQueue<PairEntry>* priority_queue,
3345  std::vector<PairEntries>* pickup_to_entries,
3346  std::vector<PairEntries>* delivery_to_entries) {
3347  UpdatePickupPositions(pair_indices, vehicle, insert_after, priority_queue,
3348  pickup_to_entries, delivery_to_entries);
3349  UpdateDeliveryPositions(pair_indices, vehicle, insert_after, priority_queue,
3350  pickup_to_entries, delivery_to_entries);
3351  }
3354  void UpdatePickupPositions(const std::vector<int>& pair_indices, int vehicle,
3355  int64 pickup_insert_after,
3356  AdjustablePriorityQueue<PairEntry>* priority_queue,
3357  std::vector<PairEntries>* pickup_to_entries,
3358  std::vector<PairEntries>* delivery_to_entries);
3361  void UpdateDeliveryPositions(
3362  const std::vector<int>& pair_indices, int vehicle,
3363  int64 delivery_insert_after,
3364  AdjustablePriorityQueue<PairEntry>* priority_queue,
3365  std::vector<PairEntries>* pickup_to_entries,
3366  std::vector<PairEntries>* delivery_to_entries);
3369  void DeletePairEntry(PairEntry* entry,
3370  AdjustablePriorityQueue<PairEntry>* priority_queue,
3371  std::vector<PairEntries>* pickup_to_entries,
3372  std::vector<PairEntries>* delivery_to_entries);
3377  void AddPairEntry(int64 pickup, int64 pickup_insert_after, int64 delivery,
3378  int64 delivery_insert_after, int vehicle,
3379  AdjustablePriorityQueue<PairEntry>* priority_queue,
3380  std::vector<PairEntries>* pickup_entries,
3381  std::vector<PairEntries>* delivery_entries) const;
3384  void UpdatePairEntry(
3385  PairEntry* const pair_entry,
3386  AdjustablePriorityQueue<PairEntry>* priority_queue) const;
3390  int64 GetInsertionValueForPairAtPositions(int64 pickup,
3391  int64 pickup_insert_after,
3392  int64 delivery,
3393  int64 delivery_insert_after,
3394  int vehicle) const;
3395 
3398  void InitializePositions(const std::vector<int>& nodes,
3399  const absl::flat_hash_set<int>& vehicles,
3400  AdjustablePriorityQueue<NodeEntry>* priority_queue,
3401  std::vector<NodeEntries>* position_to_node_entries);
3407  void InitializeInsertionEntriesPerformingNode(
3408  int64 node, const absl::flat_hash_set<int>& vehicles,
3409  AdjustablePriorityQueue<NodeEntry>* priority_queue,
3410  std::vector<NodeEntries>* position_to_node_entries);
3413  void UpdatePositions(const std::vector<int>& nodes, int vehicle,
3414  int64 insert_after, bool all_vehicles,
3415  AdjustablePriorityQueue<NodeEntry>* priority_queue,
3416  std::vector<NodeEntries>* node_entries);
3419  void DeleteNodeEntry(NodeEntry* entry,
3420  AdjustablePriorityQueue<NodeEntry>* priority_queue,
3421  std::vector<NodeEntries>* node_entries);
3422 
3426  void AddNodeEntry(int64 node, int64 insert_after, int vehicle,
3427  bool all_vehicles,
3428  AdjustablePriorityQueue<NodeEntry>* priority_queue,
3429  std::vector<NodeEntries>* node_entries) const;
3432  void UpdateNodeEntry(
3433  NodeEntry* const node_entry,
3434  AdjustablePriorityQueue<NodeEntry>* priority_queue) const;
3435 
3438  void ComputeNeighborhoods();
3439 
3442  bool IsNeighborForCostClass(int cost_class, int64 node_index,
3443  int64 neighbor_index) const;
3444 
3446  const std::vector<int64>& GetNeighborsOfNodeForCostClass(
3447  int cost_class, int64 node_index) const {
3448  return gci_params_.neighbors_ratio == 1
3449  ? all_nodes_
3450  : node_index_to_neighbors_by_cost_class_[node_index][cost_class]
3451  ->PositionsSetAtLeastOnce();
3452  }
3453 
3454  int64 NumNonStartEndNodes() const {
3455  return model()->Size() - model()->vehicles();
3456  }
3457 
3458  int64 NumNeighbors() const {
3459  return std::max(gci_params_.min_neighbors,
3460  MathUtil::FastInt64Round(gci_params_.neighbors_ratio *
3461  NumNonStartEndNodes()));
3462  }
3463 
3464  void ResetVehicleIndices() override {
3465  node_index_to_vehicle_.assign(node_index_to_vehicle_.size(), -1);
3466  }
3467 
3468  void SetVehicleIndex(int64 node, int vehicle) override {
3469  DCHECK_LT(node, node_index_to_vehicle_.size());
3470  node_index_to_vehicle_[node] = vehicle;
3471  }
3472 
3475  bool CheckVehicleIndices() const;
3476 
3477  GlobalCheapestInsertionParameters gci_params_;
3479  std::vector<int> node_index_to_vehicle_;
3480 
3481  // clang-format off
3482  std::vector<std::vector<std::unique_ptr<SparseBitset<int64> > > >
3483  node_index_to_neighbors_by_cost_class_;
3484  // clang-format on
3485 
3486  std::unique_ptr<VehicleTypeCurator> empty_vehicle_type_curator_;
3487 
3491  std::vector<int64> all_nodes_;
3492 };
3493 
3501  public:
3504  RoutingModel* model, std::function<int64(int64, int64, int64)> evaluator,
3505  LocalSearchFilterManager* filter_manager);
3507  bool BuildSolutionInternal() override;
3508  std::string DebugString() const override {
3509  return "LocalCheapestInsertionFilteredHeuristic";
3510  }
3511 
3512  private:
3518  void ComputeEvaluatorSortedPositions(int64 node,
3519  std::vector<int64>* sorted_positions);
3524  void ComputeEvaluatorSortedPositionsOnRouteAfter(
3525  int64 node, int64 start, int64 next_after_start,
3526  std::vector<int64>* sorted_positions);
3527 
3528  std::vector<std::vector<StartEndValue>> start_end_distances_per_node_;
3529 };
3530 
3534  public:
3536  LocalSearchFilterManager* filter_manager);
3538  bool BuildSolutionInternal() override;
3539 
3540  private:
3541  class PartialRoutesAndLargeVehicleIndicesFirst {
3542  public:
3543  explicit PartialRoutesAndLargeVehicleIndicesFirst(
3544  const CheapestAdditionFilteredHeuristic& builder)
3545  : builder_(builder) {}
3546  bool operator()(int vehicle1, int vehicle2) const;
3547 
3548  private:
3549  const CheapestAdditionFilteredHeuristic& builder_;
3550  };
3552  template <typename Iterator>
3553  std::vector<int64> GetPossibleNextsFromIterator(int64 node, Iterator start,
3554  Iterator end) const {
3555  const int size = model()->Size();
3556  std::vector<int64> nexts;
3557  for (Iterator it = start; it != end; ++it) {
3558  const int64 next = *it;
3559  if (next != node && (next >= size || !Contains(next))) {
3560  nexts.push_back(next);
3561  }
3562  }
3563  return nexts;
3564  }
3566  virtual void SortSuccessors(int64 node, std::vector<int64>* successors) = 0;
3567  virtual int64 FindTopSuccessor(int64 node,
3568  const std::vector<int64>& successors) = 0;
3569 };
3570 
3575  public:
3578  RoutingModel* model, std::function<int64(int64, int64)> evaluator,
3579  LocalSearchFilterManager* filter_manager);
3581  std::string DebugString() const override {
3582  return "EvaluatorCheapestAdditionFilteredHeuristic";
3583  }
3584 
3585  private:
3587  void SortSuccessors(int64 node, std::vector<int64>* successors) override;
3588  int64 FindTopSuccessor(int64 node,
3589  const std::vector<int64>& successors) override;
3590 
3591  std::function<int64(int64, int64)> evaluator_;
3592 };
3593 
3598  public:
3602  LocalSearchFilterManager* filter_manager);
3604  std::string DebugString() const override {
3605  return "ComparatorCheapestAdditionFilteredHeuristic";
3606  }
3607 
3608  private:
3610  void SortSuccessors(int64 node, std::vector<int64>* successors) override;
3611  int64 FindTopSuccessor(int64 node,
3612  const std::vector<int64>& successors) override;
3613 
3614  Solver::VariableValueComparator comparator_;
3615 };
3616 
3626  public:
3630  double neighbors_ratio = 1.0;
3633  double max_memory_usage_bytes = 6e9;
3636  bool add_reverse_arcs = false;
3639  double arc_coefficient = 1.0;
3640  };
3641 
3643  const RoutingIndexManager* manager,
3645  LocalSearchFilterManager* filter_manager);
3646  ~SavingsFilteredHeuristic() override;
3647  bool BuildSolutionInternal() override;
3648 
3649  protected:
3650  typedef std::pair</*saving*/ int64, /*saving index*/ int64> Saving;
3651 
3652  template <typename S>
3653  class SavingsContainer;
3654 
3655  virtual double ExtraSavingsMemoryMultiplicativeFactor() const = 0;
3656 
3657  virtual void BuildRoutesFromSavings() = 0;
3658 
3660  int64 GetVehicleTypeFromSaving(const Saving& saving) const {
3661  return saving.second / size_squared_;
3662  }
3664  int64 GetBeforeNodeFromSaving(const Saving& saving) const {
3665  return (saving.second % size_squared_) / Size();
3666  }
3668  int64 GetAfterNodeFromSaving(const Saving& saving) const {
3669  return (saving.second % size_squared_) % Size();
3670  }
3672  int64 GetSavingValue(const Saving& saving) const { return saving.first; }
3673 
3683  int StartNewRouteWithBestVehicleOfType(int type, int64 before_node,
3684  int64 after_node);
3685 
3686  // clang-format off
3687  std::unique_ptr<SavingsContainer<Saving> > savings_container_;
3688  // clang-format on
3689  std::unique_ptr<VehicleTypeCurator> vehicle_type_curator_;
3690 
3691  private:
3696  // clang-format off
3697  void AddSymmetricArcsToAdjacencyLists(
3698  std::vector<std::vector<int64> >* adjacency_lists);
3699  // clang-format on
3700 
3707  void ComputeSavings();
3709  Saving BuildSaving(int64 saving, int vehicle_type, int before_node,
3710  int after_node) const {
3711  return std::make_pair(saving, vehicle_type * size_squared_ +
3712  before_node * Size() + after_node);
3713  }
3714 
3718  int64 MaxNumNeighborsPerNode(int num_vehicle_types) const;
3719 
3720  const RoutingIndexManager* const manager_;
3721  const SavingsParameters savings_params_;
3722  int64 size_squared_;
3723 
3724  friend class SavingsFilteredHeuristicTestPeer;
3725 };
3726 
3728  public:
3730  const RoutingIndexManager* manager,
3732  LocalSearchFilterManager* filter_manager)
3733  : SavingsFilteredHeuristic(model, manager, parameters, filter_manager) {}
3735  std::string DebugString() const override {
3736  return "SequentialSavingsFilteredHeuristic";
3737  }
3738 
3739  private:
3744  void BuildRoutesFromSavings() override;
3745  double ExtraSavingsMemoryMultiplicativeFactor() const override { return 1.0; }
3746 };
3747 
3749  public:
3751  const RoutingIndexManager* manager,
3753  LocalSearchFilterManager* filter_manager)
3754  : SavingsFilteredHeuristic(model, manager, parameters, filter_manager) {}
3756  std::string DebugString() const override {
3757  return "ParallelSavingsFilteredHeuristic";
3758  }
3759 
3760  private:
3771  void BuildRoutesFromSavings() override;
3772 
3773  double ExtraSavingsMemoryMultiplicativeFactor() const override { return 2.0; }
3774 
3779  void MergeRoutes(int first_vehicle, int second_vehicle, int64 before_node,
3780  int64 after_node);
3781 
3783  std::vector<int64> first_node_on_route_;
3784  std::vector<int64> last_node_on_route_;
3788  std::vector<int> vehicle_of_first_or_last_node_;
3789 };
3790 
3794 
3796  public:
3798  LocalSearchFilterManager* filter_manager,
3799  bool use_minimum_matching);
3801  bool BuildSolutionInternal() override;
3802  std::string DebugString() const override {
3803  return "ChristofidesFilteredHeuristic";
3804  }
3805 
3806  private:
3807  const bool use_minimum_matching_;
3808 };
3809 #endif // SWIG
3810 
3815 bool SolveModelWithSat(const RoutingModel& model,
3816  const RoutingSearchParameters& search_parameters,
3817  const Assignment* initial_solution,
3818  Assignment* solution);
3819 
3821 
3823  public:
3824  BasePathFilter(const std::vector<IntVar*>& nexts, int next_domain_size);
3825  ~BasePathFilter() override {}
3826  bool Accept(const Assignment* delta, const Assignment* deltadelta,
3827  int64 objective_min, int64 objective_max) override;
3828  void OnSynchronize(const Assignment* delta) override;
3829 
3830  protected:
3831  static const int64 kUnassigned;
3832 
3833  int64 GetNext(int64 node) const {
3834  return (new_nexts_[node] == kUnassigned)
3835  ? (IsVarSynced(node) ? Value(node) : kUnassigned)
3836  : new_nexts_[node];
3837  }
3838  int NumPaths() const { return starts_.size(); }
3839  int64 Start(int i) const { return starts_[i]; }
3840  int GetPath(int64 node) const { return paths_[node]; }
3841  int Rank(int64 node) const { return ranks_[node]; }
3842  bool IsDisabled() const { return status_ == DISABLED; }
3843  const std::vector<int64>& GetTouchedPathStarts() const {
3844  return touched_paths_.PositionsSetAtLeastOnce();
3845  }
3846  const std::vector<int64>& GetNewSynchronizedUnperformedNodes() const {
3847  return new_synchronized_unperformed_nodes_.PositionsSetAtLeastOnce();
3848  }
3849 
3850  private:
3851  enum Status { UNKNOWN, ENABLED, DISABLED };
3852 
3853  virtual bool DisableFiltering() const { return false; }
3854  virtual void OnBeforeSynchronizePaths() {}
3855  virtual void OnAfterSynchronizePaths() {}
3856  virtual void OnSynchronizePathFromStart(int64 start) {}
3857  virtual void InitializeAcceptPath() {}
3858  virtual bool AcceptPath(int64 path_start, int64 chain_start,
3859  int64 chain_end) = 0;
3860  virtual bool FinalizeAcceptPath(const Assignment* delta, int64 objective_min,
3861  int64 objective_max) {
3862  return true;
3863  }
3865  void ComputePathStarts(std::vector<int64>* path_starts,
3866  std::vector<int>* index_to_path);
3867  bool HavePathsChanged();
3868  void SynchronizeFullAssignment();
3869  void UpdateAllRanks();
3870  void UpdatePathRanksFromStart(int start);
3871 
3872  std::vector<int64> node_path_starts_;
3873  std::vector<int64> starts_;
3874  std::vector<int> paths_;
3875  SparseBitset<int64> new_synchronized_unperformed_nodes_;
3876  std::vector<int64> new_nexts_;
3877  std::vector<int> delta_touched_;
3878  SparseBitset<> touched_paths_;
3879  // clang-format off
3880  std::vector<std::pair<int64, int64> > touched_path_chain_start_ends_;
3881  // clang-format on
3882  std::vector<int> ranks_;
3883 
3884  Status status_;
3885 };
3886 
3891 // TODO(user): Also call the solution finalizer on variables, with the
3897 // TODO(user): Avoid such false negatives.
3899  public:
3900  explicit CPFeasibilityFilter(RoutingModel* routing_model);
3901  ~CPFeasibilityFilter() override {}
3902  std::string DebugString() const override { return "CPFeasibilityFilter"; }
3903  bool Accept(const Assignment* delta, const Assignment* deltadelta,
3904  int64 objective_min, int64 objective_max) override;
3905  void OnSynchronize(const Assignment* delta) override;
3906 
3907  private:
3908  void AddDeltaToAssignment(const Assignment* delta, Assignment* assignment);
3909 
3910  static const int64 kUnassigned;
3911  const RoutingModel* const model_;
3912  Solver* const solver_;
3913  Assignment* const assignment_;
3914  Assignment* const temp_assignment_;
3915  DecisionBuilder* const restore_;
3916  SearchLimit* const limit_;
3917 };
3918 
3919 #if !defined(SWIG)
3920 IntVarLocalSearchFilter* MakeMaxActiveVehiclesFilter(
3921  const RoutingModel& routing_model);
3922 IntVarLocalSearchFilter* MakeNodeDisjunctionFilter(
3923  const RoutingModel& routing_model);
3924 IntVarLocalSearchFilter* MakeVehicleAmortizedCostFilter(
3925  const RoutingModel& routing_model);
3926 IntVarLocalSearchFilter* MakeTypeRegulationsFilter(
3927  const RoutingModel& routing_model);
3929  const std::vector<RoutingDimension*>& dimensions,
3930  const RoutingSearchParameters& parameters, bool filter_objective_cost,
3931  std::vector<LocalSearchFilterManager::FilterEvent>* filters);
3933  const PathState* path_state,
3934  const std::vector<RoutingDimension*>& dimensions,
3935  std::vector<LocalSearchFilterManager::FilterEvent>* filters);
3936 IntVarLocalSearchFilter* MakePathCumulFilter(
3937  const RoutingDimension& dimension,
3938  const RoutingSearchParameters& parameters,
3939  bool propagate_own_objective_value, bool filter_objective_cost,
3940  bool can_use_lp = true);
3941 IntVarLocalSearchFilter* MakeCumulBoundsPropagatorFilter(
3942  const RoutingDimension& dimension);
3943 IntVarLocalSearchFilter* MakeGlobalLPCumulFilter(
3944  GlobalDimensionCumulOptimizer* optimizer, bool filter_objective_cost);
3945 IntVarLocalSearchFilter* MakePickupDeliveryFilter(
3946  const RoutingModel& routing_model, const RoutingModel::IndexPairs& pairs,
3947  const std::vector<RoutingModel::PickupAndDeliveryPolicy>& vehicle_policies);
3948 IntVarLocalSearchFilter* MakeVehicleVarFilter(
3949  const RoutingModel& routing_model);
3950 IntVarLocalSearchFilter* MakeVehicleBreaksFilter(
3951  const RoutingModel& routing_model, const RoutingDimension& dimension);
3952 IntVarLocalSearchFilter* MakeCPFeasibilityFilter(RoutingModel* routing_model);
3953 #endif
3954 
3955 } // namespace operations_research
3956 #endif // OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_H_
const std::vector< IntVar * > vars_
Definition: alldiff_cst.cc:43
int64 max
Definition: alldiff_cst.cc:139
#define CHECK(condition)
Definition: base/logging.h:495
#define CHECK_LT(val1, val2)
Definition: base/logging.h:700
#define DCHECK_GE(val1, val2)
Definition: base/logging.h:889
#define DCHECK_LT(val1, val2)
Definition: base/logging.h:888
#define LOG(severity)
Definition: base/logging.h:420
#define DCHECK(condition)
Definition: base/logging.h:884
An Assignment is a variable -> domains mapping, used to report solutions to the user.
A BaseObject is the root of all reversibly allocated objects.
Generic path-based filter class.
Definition: routing.h:3822
const std::vector< int64 > & GetTouchedPathStarts() const
Definition: routing.h:3843
static const int64 kUnassigned
Definition: routing.h:3831
const std::vector< int64 > & GetNewSynchronizedUnperformedNodes() const
Definition: routing.h:3846
int Rank(int64 node) const
Definition: routing.h:3841
int64 GetNext(int64 node) const
Definition: routing.h:3833
int GetPath(int64 node) const
Definition: routing.h:3840
This filter accepts deltas for which the assignment satisfies the constraints of the Solver.
Definition: routing.h:3898
std::string DebugString() const override
Definition: routing.h:3902
Filtered-base decision builder based on the addition heuristic, extending a path from its start node ...
Definition: routing.h:3533
std::function< int64(int64, int64, int64)> evaluator_
Definition: routing.h:3174
void InitializePriorityQueue(std::vector< std::vector< StartEndValue > > *start_end_distances_per_node, Queue *priority_queue)
Initializes the priority_queue by inserting the best entry corresponding to each node,...
Christofides addition heuristic.
Definition: routing.h:3795
std::string DebugString() const override
Definition: routing.h:3802
A CheapestAdditionFilteredHeuristic where the notion of 'cheapest arc' comes from an arc comparator.
Definition: routing.h:3597
A constraint is the main modeling object.
A DecisionBuilder is responsible for creating the search tree.
A Decision represents a choice point in 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:1943
A CheapestAdditionFilteredHeuristic where the notion of 'cheapest arc' comes from an arc evaluator.
Definition: routing.h:3574
Filter-based decision builder which builds a solution by inserting nodes at their cheapest position o...
Definition: routing.h:3186
GlobalVehicleBreaksConstraint ensures breaks constraints are enforced on all vehicles in the dimensio...
Definition: routing.h:2051
std::string DebugString() const override
Definition: routing.h:2054
Decision builder building a solution using heuristics with local search filters to evaluate its feasi...
Definition: routing.h:2967
Generic filter-based heuristic applied to IntVars.
Definition: routing.h:2987
virtual bool BuildSolutionInternal()=0
Virtual method to redefine how to build a solution.
int Size() const
Returns the number of variables the decision builder is trying to instantiate.
Definition: routing.h:3040
bool Contains(int64 index) const
Returns true if the variable of index 'index' is in the current solution.
Definition: routing.h:3035
int64 Value(int64 index) const
Returns the value of the variable of index 'index' in the last committed solution.
Definition: routing.h:3031
IntVar * Var(int64 index) const
Returns the variable of index 'index'.
Definition: routing.h:3042
virtual bool StopSearch()
Returns true if the search must be stopped.
Definition: routing.h:3017
virtual std::string DebugString() const
Definition: routing.h:3003
virtual bool InitializeSolution()
Virtual method to initialize the solution.
Definition: routing.h:3009
int64 number_of_decisions() const
Returns statistics on search, number of decisions sent to filters, number of decisions rejected by fi...
Definition: routing.h:3000
void SetValue(int64 index, int64 value)
Modifies the current solution by setting the variable of index 'index' to value 'value'.
Definition: routing.h:3020
The class IntVar is a subset of IntExpr.
Interval variables are often used in scheduling.
Filter-base decision builder which builds a solution by inserting nodes at their cheapest position.
Definition: routing.h:3500
Local Search Filters are used for fast neighbor pruning.
Filter manager: when a move is made, filters are executed to decide whether the solution is feasible ...
The base class for all local search operators.
ParallelSavingsFilteredHeuristic(RoutingModel *model, const RoutingIndexManager *manager, SavingsParameters parameters, LocalSearchFilterManager *filter_manager)
Definition: routing.h:3750
Dimensions represent quantities accumulated at nodes along the routes.
Definition: routing.h:2357
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:2707
SimpleBoundCosts::BoundCost GetSoftSpanUpperBoundForVehicle(int vehicle) const
Definition: routing.h:2700
void AddNodePrecedence(int64 first_node, int64 second_node, int64 offset)
Definition: routing.h:2651
int64 GetTransitValueFromClass(int64 from_index, int64 to_index, int64 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:2368
const std::vector< IntVar * > & cumuls() const
Like CumulVar(), TransitVar(), SlackVar() but return the whole variable vectors instead (indexed by i...
Definition: routing.h:2383
int64 global_span_cost_coefficient() const
Definition: routing.h:2671
int64 GetSpanCostCoefficientForVehicle(int vehicle) const
Definition: routing.h:2663
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:2689
RoutingModel * model() const
Returns the model on which the dimension was created.
Definition: routing.h:2361
IntVar * CumulVar(int64 index) const
Get the cumul, transit and slack variables for the given node (given as int64 var index).
Definition: routing.h:2375
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:2445
IntVar * FixedTransitVar(int64 index) const
Definition: routing.h:2377
const std::vector< int64 > & vehicle_capacities() const
Returns the capacities for all vehicles.
Definition: routing.h:2433
std::function< int64(int, int)> PickupToDeliveryLimitFunction
Limits, in terms of maximum difference between the cumul variables, between the pickup and delivery a...
Definition: routing.h:2627
bool AreVehicleTransitsPositive(int vehicle) const
Returns true iff the transit evaluator of 'vehicle' is positive for all arcs.
Definition: routing.h:2452
const std::vector< IntVar * > & fixed_transits() const
Definition: routing.h:2384
const std::vector< IntVar * > & transits() const
Definition: routing.h:2385
const RoutingDimension * base_dimension() const
Returns the parent in the dependency tree if any or nullptr otherwise.
Definition: routing.h:2598
void AddNodePrecedence(NodePrecedence precedence)
Definition: routing.h:2643
int64 GetLocalOptimizerOffsetForVehicle(int vehicle) const
Definition: routing.h:2679
const std::vector< int64 > & vehicle_span_upper_bounds() const
Definition: routing.h:2659
bool HasQuadraticCostSoftSpanUpperBounds() const
Definition: routing.h:2717
int64 GetFirstPossibleGreaterOrEqualValueForNode(int64 index, int64 min_value) const
Returns the smallest value outside the forbidden intervals of node 'index' that is greater than or eq...
Definition: routing.h:2398
int vehicle_to_class(int vehicle) const
Definition: routing.h:2456
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:2438
int64 GetLastPossibleLessOrEqualValueForNode(int64 index, int64 max_value) const
Returns the largest value outside the forbidden intervals of node 'index' that is less than or equal ...
Definition: routing.h:2417
IntVar * TransitVar(int64 index) const
Definition: routing.h:2376
IntVar * SlackVar(int64 index) const
Definition: routing.h:2378
const std::vector< int64 > & vehicle_span_cost_coefficients() const
Definition: routing.h:2667
const ReverseArcListGraph< int, int > & GetPathPrecedenceGraph() const
Accessors.
Definition: routing.h:2613
const std::string & name() const
Returns the name of the dimension.
Definition: routing.h:2609
const std::vector< IntVar * > & slacks() const
Definition: routing.h:2386
const std::vector< NodePrecedence > & GetNodePrecedences() const
Definition: routing.h:2646
SimpleBoundCosts::BoundCost GetQuadraticCostSoftSpanUpperBoundForVehicle(int vehicle) const
Definition: routing.h:2720
const std::vector< SortedDisjointIntervalList > & forbidden_intervals() const
Returns forbidden intervals for each node.
Definition: routing.h:2389
int64 GetSpanUpperBoundForVehicle(int vehicle) const
Definition: routing.h:2655
Filter-based heuristic dedicated to routing.
Definition: routing.h:3066
int GetStartChainEnd(int vehicle) const
Returns the end of the start chain of vehicle,.
Definition: routing.h:3076
int GetEndChainStart(int vehicle) const
Returns the start of the end chain of vehicle,.
Definition: routing.h:3078
virtual void SetVehicleIndex(int64 node, int vehicle)
Definition: routing.h:3092
bool StopSearch() override
Returns true if the search must be stopped.
Definition: routing.h:3091
bool VehicleIsEmpty(int vehicle) const
Definition: routing.h:3094
Manager for any NodeIndex <-> variable index conversion.
bool AddDimensionWithVehicleTransitAndCapacity(const std::vector< int > &evaluator_indices, int64 slack_max, std::vector< int64 > vehicle_capacities, bool fix_start_cumul_to_zero, const std::string &name)
Definition: routing.cc:855
const std::vector< std::pair< DisjunctionIndex, DisjunctionIndex > > & GetPickupAndDeliveryDisjunctions() const
Definition: routing.h:739
const std::string & GetPrimaryConstrainedDimension() const
Get the primary constrained dimension, or an empty string if it is unset.
Definition: routing.h:597
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:1357
int nodes() const
Sizes and indices Returns the number of nodes in the model.
Definition: routing.h:1332
const std::vector< int > & GetSameVehicleIndicesOfIndex(int node) const
Returns variable indices of nodes constrained to be on the same route.
Definition: routing.h:1269
int64 GetDisjunctionMaxCardinality(DisjunctionIndex index) const
Returns the maximum number of possible active nodes of the node disjunction of index 'index'.
Definition: routing.h:652
RoutingIndexPair IndexPair
Definition: routing.h:247
IntVar * ActiveVehicleVar(int vehicle) const
Returns the active variable of the vehicle.
Definition: routing.h:1201
int64 End(int vehicle) const
Returns the variable index of the ending node of a vehicle route.
Definition: routing.h:1171
RoutingTransitCallback1 TransitCallback1
Definition: routing.h:242
const std::vector< std::vector< int > > & GetTopologicallySortedVisitTypes() const
Definition: routing.h:792
void ForEachNodeInDisjunctionWithMaxCardinalityFromIndex(int64 index, int64 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:628
CostClassIndex GetCostClassIndexOfVehicle(int64 vehicle) const
Get the cost class index of the given vehicle.
Definition: routing.h:1240
int GetVehicleClassesCount() const
Returns the number of different vehicle classes in the model.
Definition: routing.h:1267
int64 Size() const
Returns the number of next variables in the model.
Definition: routing.h:1336
Assignment * MutablePreAssignment()
Definition: routing.h:1056
bool CheckLimit()
Returns true if the search limit has been crossed.
Definition: routing.h:1319
int RegisterStateDependentTransitCallback(VariableIndexEvaluator2 callback)
Definition: routing.cc:803
bool IsVehicleAllowedForIndex(int vehicle, int64 index)
Returns true if a vehicle is allowed to visit a given node.
Definition: routing.h:683
const std::vector< std::unique_ptr< LocalDimensionCumulOptimizer > > & GetLocalDimensionCumulOptimizers() const
Definition: routing.h:561
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:762
@ TYPE_ADDED_TO_VEHICLE
When visited, the number of types 'T' on the vehicle increases by one.
Definition: routing.h:764
@ ADDED_TYPE_REMOVED_FROM_VEHICLE
When visited, one instance of type 'T' previously added to the route (TYPE_ADDED_TO_VEHICLE),...
Definition: routing.h:769
@ 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:772
bool AddDimensionDependentDimensionWithVehicleCapacity(const std::vector< int > &pure_transits, const std::vector< int > &dependent_transits, const RoutingDimension *base_dimension, int64 slack_max, std::vector< int64 > 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:499
static RoutingModel::StateDependentTransit MakeStateDependentTransit(const std::function< int64(int64)> &f, int64 domain_start, int64 domain_end)
Creates a cached StateDependentTransit from an std::function.
Definition: routing.cc:1098
Constraint * MakePathSpansAndTotalSlacks(const RoutingDimension *dimension, std::vector< IntVar * > spans, std::vector< IntVar * > total_slacks)
For every vehicle of the routing model:
Definition: routing.cc:5914
LocalDimensionCumulOptimizer * GetMutableLocalCumulOptimizer(const RoutingDimension &dimension) const
Definition: routing.cc:1129
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:1158
RoutingDimension * GetMutableDimension(const std::string &dimension_name) const
Returns a dimension from its name.
Definition: routing.cc:1168
bool HasTemporalTypeRequirements() const
Definition: routing.h:859
Solver * solver() const
Returns the underlying constraint solver.
Definition: routing.h:1316
RoutingTransitCallback2 TransitCallback2
Definition: routing.h:243
const std::vector< RoutingDimension * > & GetDimensions() const
Returns all dimensions of the model.
Definition: routing.h:548
std::vector< std::string > GetAllDimensionNames() const
Outputs the names of all dimensions added to the routing engine.
Definition: routing.cc:1108
const Solver::IndexEvaluator2 & first_solution_evaluator() const
Gets/sets the evaluator used during the search.
Definition: routing.h:952
bool AddDimensionWithVehicleTransits(const std::vector< int > &evaluator_indices, int64 slack_max, int64 capacity, bool fix_start_cumul_to_zero, const std::string &name)
Definition: routing.cc:837
IntVar * NextVar(int64 index) const
!defined(SWIGPYTHON)
Definition: routing.h:1196
std::function< StateDependentTransit(int64, int64)> VariableIndexEvaluator2
Definition: routing.h:269
Status
Status of the search.
Definition: routing.h:216
@ ROUTING_SUCCESS
Problem solved successfully after calling RoutingModel::Solve().
Definition: routing.h:220
@ ROUTING_FAIL
No solution found to the problem after calling RoutingModel::Solve().
Definition: routing.h:222
@ ROUTING_NOT_SOLVED
Problem not solved yet (before calling RoutingModel::Solve()).
Definition: routing.h:218
@ ROUTING_INVALID
Model, model parameters or flags are not valid.
Definition: routing.h:226
@ ROUTING_FAIL_TIMEOUT
Time limit reached before finding a solution with RoutingModel::Solve().
Definition: routing.h:224
bool HasVehicleWithCostClassIndex(CostClassIndex cost_class_index) const
Returns true iff the model contains a vehicle with the given cost_class_index.
Definition: routing.h:1249
std::vector< RoutingDimension * > GetDimensionsWithSoftOrSpanCosts() const
Returns dimensions with soft or vehicle span costs.
Definition: routing.cc:4983
void SetSweepArranger(SweepArranger *sweep_arranger)
Definition: routing.h:1147
SweepArranger * sweep_arranger() const
Returns the sweep arranger to be used by routing heuristics.
Definition: routing.h:1151
RoutingIndexPairs IndexPairs
Definition: routing.h:248
VehicleClassIndex GetVehicleClassIndexOfVehicle(int64 vehicle) const
Definition: routing.h:1262
IntVar * VehicleCostsConsideredVar(int vehicle) const
Returns the variable specifying whether or not costs are considered for vehicle.
Definition: routing.h:1206
void ConsiderEmptyRouteCostsForVehicle(bool consider_costs, int vehicle)
Definition: routing.h:939
int RegisterPositiveUnaryTransitCallback(TransitCallback1 callback)
Definition: routing.cc:762
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:1192
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:889
const IndexPairs & GetImplicitUniquePickupAndDeliveryPairs() const
Returns implicit pickup and delivery pairs currently in the model.
Definition: routing.h:746
const std::vector< DisjunctionIndex > & GetDisjunctionIndices(int64 index) const
Returns the indices of the disjunctions to which an index belongs.
Definition: routing.h:620
static const int64 kNoPenalty
Constant used to express a hard constraint instead of a soft penalty.
Definition: routing.h:384
int RegisterTransitCallback(TransitCallback2 callback)
Definition: routing.cc:770
IntVar * VehicleVar(int64 index) const
Returns the vehicle variable of the node corresponding to index.
Definition: routing.h:1211
const std::vector< std::unique_ptr< LocalDimensionCumulOptimizer > > & GetLocalDimensionCumulMPOptimizers() const
Definition: routing.h:565
int GetMaximumNumberOfActiveVehicles() const
Returns the maximum number of active vehicles.
Definition: routing.h:893
bool AddConstantDimensionWithSlack(int64 value, int64 capacity, int64 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:922
RoutingDimensionIndex DimensionIndex
Definition: routing.h:239
DisjunctionIndex AddDisjunction(const std::vector< int64 > &indices, int64 penalty=kNoPenalty, int64 max_cardinality=1)
Adds a disjunction constraint on the indices: exactly 'max_cardinality' of the indices are active.
Definition: routing.cc:1562
LocalDimensionCumulOptimizer * GetMutableLocalCumulMPOptimizer(const RoutingDimension &dimension) const
Definition: routing.cc:1141
bool HasHardTypeIncompatibilities() const
Returns true iff any hard (resp.
Definition: routing.h:811
bool AddMatrixDimension(std::vector< std::vector< int64 > > values, int64 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:946
const IndexPairs & GetPickupAndDeliveryPairs() const
Returns pickup and delivery pairs currently in the model.
Definition: routing.h:735
bool AddConstantDimension(int64 value, int64 capacity, bool fix_start_cumul_to_zero, const std::string &name)
Definition: routing.h:467
const std::vector< int64 > & GetAmortizedLinearCostFactorOfVehicles() const
Definition: routing.h:932
int64 GetHomogeneousCost(int64 from_index, int64 to_index) const
Returns the cost of the segment between two nodes supposing all vehicle costs are the same (returns t...
Definition: routing.h:1225
int RegisterPositiveTransitCallback(TransitCallback2 callback)
Definition: routing.cc:796
PickupAndDeliveryPolicy
Types of precedence policy applied to pickup and delivery pairs.
Definition: routing.h:230
@ PICKUP_AND_DELIVERY_LIFO
Deliveries must be performed in reverse order of pickups.
Definition: routing.h:234
@ PICKUP_AND_DELIVERY_NO_ORDER
Any precedence is accepted.
Definition: routing.h:232
@ PICKUP_AND_DELIVERY_FIFO
Deliveries must be performed in the same order as pickups.
Definition: routing.h:236
int vehicles() const
Returns the number of vehicle routes in the model.
Definition: routing.h:1334
int GetNumberOfDisjunctions() const
Returns the number of node disjunctions in the model.
Definition: routing.h:656
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:1189
const std::vector< int64 > & GetAmortizedQuadraticCostFactorOfVehicles() const
Definition: routing.h:935
int VehicleIndex(int64 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:1178
bool HasTypeRegulations() const
Returns true iff the model has any incompatibilities or requirements set on node types.
Definition: routing.h:865
void SetFirstSolutionEvaluator(Solver::IndexEvaluator2 evaluator)
Takes ownership of evaluator.
Definition: routing.h:957
RoutingVehicleClassIndex VehicleClassIndex
Definition: routing.h:241
bool AddDimension(int evaluator_index, int64 slack_max, int64 capacity, bool fix_start_cumul_to_zero, const std::string &name)
Model creation.
Definition: routing.cc:827
int GetNonZeroCostClassesCount() const
Ditto, minus the 'always zero', built-in cost class.
Definition: routing.h:1259
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:1117
bool HasSameVehicleTypeRequirements() const
Returns true iff any same-route (resp.
Definition: routing.h:856
IntVar * CostVar() const
Returns the global cost variable which is being minimized.
Definition: routing.h:1213
void SetPrimaryConstrainedDimension(const std::string &dimension_name)
Set the given dimension as "primary constrained".
Definition: routing.h:592
const VariableIndexEvaluator2 & StateDependentTransitCallback(int callback_index) const
Definition: routing.h:416
bool AddDimensionWithVehicleCapacity(int evaluator_index, int64 slack_max, std::vector< int64 > vehicle_capacities, bool fix_start_cumul_to_zero, const std::string &name)
Definition: routing.cc:846
int RegisterUnaryTransitCallback(TransitCallback1 callback)
Registers 'callback' and returns its index.
Definition: routing.cc:754
int64 Start(int vehicle) const
Model inspection.
Definition: routing.h:1169
RoutingCostClassIndex CostClassIndex
Definition: routing.h:238
bool HasTemporalTypeIncompatibilities() const
Definition: routing.h:814
int GetCostClassesCount() const
Returns the number of different cost classes in the model.
Definition: routing.h:1257
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:557
operations_research::FirstSolutionStrategy::Value GetAutomaticFirstSolutionStrategy() const
Returns the automatic first solution strategy selected.
Definition: routing.h:1346
absl::Duration RemainingTime() const
Returns the time left in the search limit.
Definition: routing.h:1325
Status status() const
Returns the current status of the routing model.
Definition: routing.h:1031
const std::vector< int64 > & GetDisjunctionIndices(DisjunctionIndex index) const
Returns the variable indices of the nodes in the disjunction of index 'index'.
Definition: routing.h:641
static const DimensionIndex kNoDimension
Constant used to express the "no dimension" index, returned when a dimension name does not correspond...
Definition: routing.h:392
const Assignment *const PreAssignment() const
Returns an assignment used to fix some of the variables of the problem.
Definition: routing.h:1055
bool CostsAreHomogeneousAcrossVehicles() const
Whether costs are homogeneous across all vehicles.
Definition: routing.h:1220
bool IsEnd(int64 index) const
Returns true if 'index' represents the last node of a route.
Definition: routing.h:1175
const VehicleTypeContainer & GetVehicleTypeContainer() const
Definition: routing.h:1274
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:388
bool HasDimension(const std::string &dimension_name) const
Returns true if a dimension exists for a given dimension name.
Definition: routing.cc:1153
bool AreEmptyRouteCostsConsideredForVehicle(int vehicle) const
Definition: routing.h:944
bool AddVectorDimension(std::vector< int64 > values, int64 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:931
RoutingModel(const RoutingIndexManager &index_manager)
Constructor taking an index manager.
Definition: routing.cc:645
RoutingDisjunctionIndex DisjunctionIndex
Definition: routing.h:240
IntVar * ActiveVar(int64 index) const
Returns the active variable of the node corresponding to index.
Definition: routing.h:1198
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:1163
Filter-based decision builder which builds a solution by using Clarke & Wright's Savings heuristic.
Definition: routing.h:3625
std::unique_ptr< VehicleTypeCurator > vehicle_type_curator_
Definition: routing.h:3689
int64 GetVehicleTypeFromSaving(const Saving &saving) const
Returns the cost class from a saving.
Definition: routing.h:3660
std::unique_ptr< SavingsContainer< Saving > > savings_container_
Definition: routing.h:3687
int64 GetSavingValue(const Saving &saving) const
Returns the saving value from a saving.
Definition: routing.h:3672
virtual double ExtraSavingsMemoryMultiplicativeFactor() const =0
int64 GetBeforeNodeFromSaving(const Saving &saving) const
Returns the "before node" from a saving.
Definition: routing.h:3664
int64 GetAfterNodeFromSaving(const Saving &saving) const
Returns the "after node" from a saving.
Definition: routing.h:3668
Base class of all search limits.
A search monitor is a simple set of callbacks to monitor all search events.
SequentialSavingsFilteredHeuristic(RoutingModel *model, const RoutingIndexManager *manager, SavingsParameters parameters, LocalSearchFilterManager *filter_manager)
Definition: routing.h:3729
A structure meant to store soft bounds and associated violation constants.
Definition: routing.h:2318
BoundCost & bound_cost(int element)
Definition: routing.h:2326
SimpleBoundCosts(int num_bounds, BoundCost default_bound_cost)
Definition: routing.h:2324
BoundCost bound_cost(int element) const
Definition: routing.h:2327
SimpleBoundCosts(const SimpleBoundCosts &)=delete
SimpleBoundCosts operator=(const SimpleBoundCosts &)=delete
std::function< bool(int64, int64, int64)> VariableValueComparator
std::function< int64(int64, int64)> IndexEvaluator2
This class represents a sorted list of disjoint, closed intervals.
Iterator FirstIntervalGreaterOrEqual(int64 value) const
Returns an iterator to either:
Class to arrange indices by by their distance and their angles from the depot.
Definition: routing.h:2859
void SetSectors(int sectors)
Definition: routing.h:2864
Checker for type incompatibilities.
Definition: routing.h:2209
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:2289
Checker for type requirements.
Definition: routing.h:2225
TypeRequirementChecker(const RoutingModel &model)
Definition: routing.h:2227
Helper class that manages vehicles.
Definition: routing.h:2884
VehicleTypeCurator(const RoutingModel::VehicleTypeContainer &vehicle_type_container)
Definition: routing.h:2886
void ReinjectVehicleOfClass(int vehicle, int vehicle_class, int64 fixed_cost)
Definition: routing.h:2914
int GetLowestFixedCostVehicleOfType(int type) const
Definition: routing.h:2902
Block * next
SatParameters parameters
const std::string name
int64 value
IntVar * var
Definition: expr_array.cc:1858
const int64 limit_
const std::vector< IntVar * > cumuls_
GRBmodel * model
MPCallback * callback
static const int64 kint64max
int64_t int64
uint64_t uint64
const int WARNING
Definition: log_severity.h:31
#define DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition: macros.h:29
std::function< int64(const Model &)> Value(IntegerVariable v)
Definition: integer.h:1487
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.
The vehicle routing library lets one model and solve generic vehicle routing problems ranging from th...
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:505
void AppendDimensionCumulFilters(const std::vector< RoutingDimension * > &dimensions, const RoutingSearchParameters &parameters, bool filter_objective_cost, std::vector< LocalSearchFilterManager::FilterEvent > *filters)
std::pair< std::vector< int64 >, std::vector< int64 > > RoutingIndexPair
Definition: routing_types.h:44
IntVarLocalSearchFilter * MakePathCumulFilter(const RoutingDimension &dimension, const RoutingSearchParameters &parameters, bool propagate_own_objective_value, bool filter_objective_cost, bool can_use_lp=true)
IntVarLocalSearchFilter * MakeCumulBoundsPropagatorFilter(const RoutingDimension &dimension)
int64 CapSub(int64 x, int64 y)
void AppendTasksFromPath(const std::vector< int64 > &path, const TravelBounds &travel_bounds, const RoutingDimension &dimension, DisjunctivePropagator::Tasks *tasks)
IntVarLocalSearchFilter * MakeGlobalLPCumulFilter(GlobalDimensionCumulOptimizer *optimizer, bool filter_objective_cost)
IntVarLocalSearchFilter * MakeVehicleBreaksFilter(const RoutingModel &routing_model, const RoutingDimension &dimension)
IntVarLocalSearchFilter * MakeVehicleAmortizedCostFilter(const RoutingModel &routing_model)
void FillTravelBoundsOfVehicle(int vehicle, const std::vector< int64 > &path, const RoutingDimension &dimension, TravelBounds *travel_bounds)
IntVarLocalSearchFilter * MakeCPFeasibilityFilter(RoutingModel *routing_model)
void AppendTasksFromIntervals(const std::vector< IntervalVar * > &intervals, DisjunctivePropagator::Tasks *tasks)
int64 CapAdd(int64 x, int64 y)
IntVarLocalSearchFilter * MakeMaxActiveVehiclesFilter(const RoutingModel &routing_model)
std::function< int64(int64, int64)> RoutingTransitCallback2
Definition: routing_types.h:42
IntVarLocalSearchFilter * MakeVehicleVarFilter(const RoutingModel &routing_model)
std::function< int64(int64)> RoutingTransitCallback1
Definition: routing_types.h:41
IntVarLocalSearchFilter * MakePickupDeliveryFilter(const RoutingModel &routing_model, const RoutingModel::IndexPairs &pairs, const std::vector< RoutingModel::PickupAndDeliveryPolicy > &vehicle_policies)
void FillPathEvaluation(const std::vector< int64 > &path, const RoutingModel::TransitCallback2 &evaluator, std::vector< int64 > *values)
Definition: routing.cc:6202
IntVarLocalSearchFilter * MakeTypeRegulationsFilter(const RoutingModel &routing_model)
static const int kUnassigned
Definition: routing.cc:638
void AppendLightWeightDimensionFilters(const PathState *path_state, const std::vector< RoutingDimension * > &dimensions, std::vector< LocalSearchFilterManager::FilterEvent > *filters)
IntVarLocalSearchFilter * MakeNodeDisjunctionFilter(const RoutingModel &routing_model)
std::vector< RoutingIndexPair > RoutingIndexPairs
Definition: routing_types.h:45
DecisionBuilder * MakeSetValuesFromTargets(Solver *solver, std::vector< IntVar * > variables, std::vector< int64 > targets)
A decision builder which tries to assign values to variables as close as possible to target values fi...
Definition: routing.cc:143
int index
Definition: pack.cc:508
int64 delta
Definition: resource.cc:1684
IntervalVar * interval
Definition: resource.cc:98
int64 cost
int64 capacity
int64 bound
int64 coefficient
Rev< int64 > end_min
Rev< int64 > end_max
Rev< int64 > start_max
Rev< int64 > start_min
std::function< int64(int64, int64)> evaluator_
Definition: search.cc:1361
A structure to hold tasks described by their features.
Definition: routing.h:1950
std::vector< const SortedDisjointIntervalList * > forbidden_intervals
Definition: routing.h:1959
std::vector< std::pair< int64, int64 > > distance_duration
Definition: routing.h:1960
double neighbors_ratio
If neighbors_ratio < 1 then for each node only this ratio of its neighbors leading to the smallest ar...
Definition: routing.h:3199
bool is_sequential
Whether the routes are constructed sequentially or in parallel.
Definition: routing.h:3190
double farthest_seeds_ratio
The ratio of routes on which to insert farthest nodes as seeds before starting the cheapest insertion...
Definition: routing.h:3193
bool use_neighbors_ratio_for_initialization
If true, only closest neighbors (see neighbors_ratio and min_neighbors) are considered as insertion p...
Definition: routing.h:3204
bool add_unperformed_entries
If true, entries are created for making the nodes/pairs unperformed, and when the cost of making a no...
Definition: routing.h:3209
SUBTLE: The vehicle's fixed cost is skipped on purpose here, because we can afford to do so:
Definition: routing.h:297
bool operator<(const DimensionCost &cost) const
Definition: routing.h:301
int evaluator_index
Index of the arc cost evaluator, registered in the RoutingModel class.
Definition: routing.h:275
static bool LessThan(const CostClass &a, const CostClass &b)
Comparator for STL containers and algorithms.
Definition: routing.h:315
std::vector< DimensionCost > dimension_transit_evaluator_class_and_cost_coefficient
Definition: routing.h:309
What follows is relevant for models with time/state dependent transits.
Definition: routing.h:264
RangeMinMaxIndexFunction * transit_plus_identity
f(x)
Definition: routing.h:266
int64 fixed_cost
Contrarily to CostClass, here we need strict equivalence.
Definition: routing.h:328
absl::StrongVector< DimensionIndex, int64 > dimension_capacities
Definition: routing.h:343
absl::StrongVector< DimensionIndex, int64 > dimension_evaluator_classes
dimension_evaluators[d]->Run(from, to) is the transit value of arc from->to for a dimension d.
Definition: routing.h:346
int start_equivalence_class
Vehicle start and end equivalence classes.
Definition: routing.h:335
absl::StrongVector< DimensionIndex, int64 > dimension_start_cumuls_min
Bounds of cumul variables at start and end vehicle nodes.
Definition: routing.h:339
absl::StrongVector< DimensionIndex, int64 > dimension_end_cumuls_min
Definition: routing.h:341
absl::StrongVector< DimensionIndex, int64 > dimension_end_cumuls_max
Definition: routing.h:342
uint64 unvisitable_nodes_fprint
Fingerprint of unvisitable non-start/end nodes.
Definition: routing.h:348
static bool LessThan(const VehicleClass &a, const VehicleClass &b)
Comparator for STL containers and algorithms.
Definition: routing.cc:1311
absl::StrongVector< DimensionIndex, int64 > dimension_start_cumuls_max
Definition: routing.h:340
CostClassIndex cost_class_index
The cost class of the vehicle.
Definition: routing.h:326
Definition: routing.h:359
int64 fixed_cost
Definition: routing.h:361
bool operator<(const VehicleClassEntry &other) const
Definition: routing.h:363
int vehicle_class
Definition: routing.h:360
Struct used to sort and store vehicles by their type.
Definition: routing.h:358
std::vector< std::set< VehicleClassEntry > > sorted_vehicle_classes_per_type
Definition: routing.h:378
std::vector< std::deque< int > > vehicles_per_vehicle_class
Definition: routing.h:379
std::vector< int64 > max_travels
Definition: routing.h:2022
std::vector< int64 > min_travels
Definition: routing.h:2021
std::vector< int64 > post_travels
Definition: routing.h:2024
std::vector< int64 > pre_travels
Definition: routing.h:2023