C++ Reference

C++ Reference: Routing

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