C++ Reference

C++ Reference: Routing

routing.h
Go to the documentation of this file.
1// Copyright 2010-2021 Google LLC
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
68// TODO(user): Add a section on costs (vehicle arc costs, span costs,
69// disjunctions costs).
70//
156
157#ifndef OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_H_
158#define OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_H_
159
160#include <algorithm>
161#include <deque>
162#include <functional>
163#include <memory>
164#include <set>
165#include <string>
166#include <tuple>
167#include <utility>
168#include <vector>
169
170#include "absl/container/flat_hash_map.h"
171#include "absl/container/flat_hash_set.h"
172#include "absl/functional/bind_front.h"
173#include "absl/memory/memory.h"
174#include "absl/time/time.h"
175#include "ortools/base/int_type.h"
176#include "ortools/base/integral_types.h"
177#include "ortools/base/logging.h"
178#include "ortools/base/macros.h"
179#include "ortools/base/map_util.h"
180#include "ortools/base/strong_vector.h"
187#include "ortools/graph/graph.h"
188#include "ortools/sat/theta_tree.h"
189#include "ortools/util/piecewise_linear_function.h"
190#include "ortools/util/range_query_function.h"
191#include "ortools/util/saturated_arithmetic.h"
192#include "ortools/util/sorted_interval_list.h"
193
194namespace operations_research {
195
196class GlobalDimensionCumulOptimizer;
197class LocalDimensionCumulOptimizer;
198class LocalSearchPhaseParameters;
199#ifndef SWIG
200class IndexNeighborFinder;
201class IntVarFilteredDecisionBuilder;
202#endif
203class RoutingDimension;
204#ifndef SWIG
205using util::ReverseArcListGraph;
206class SweepArranger;
207#endif
208
210 public:
212 enum Status {
223 };
224
233 };
234 typedef RoutingCostClassIndex CostClassIndex;
235 typedef RoutingDimensionIndex DimensionIndex;
236 typedef RoutingDisjunctionIndex DisjunctionIndex;
237 typedef RoutingVehicleClassIndex VehicleClassIndex;
240
241// TODO(user): Remove all SWIG guards by adding the @ignore in .i.
242#if !defined(SWIG)
245#endif // SWIG
246
247#if !defined(SWIG)
261 RangeIntToIntFunction* transit;
262 RangeMinMaxIndexFunction* transit_plus_identity;
263 };
264 typedef std::function<StateDependentTransit(int64_t, int64_t)>
266#endif // SWIG
267
268#if !defined(SWIG)
269 struct CostClass {
272
287
297 bool operator<(const DimensionCost& cost) const {
300 }
302 }
303 };
304 std::vector<DimensionCost>
306
309
311 static bool LessThan(const CostClass& a, const CostClass& b) {
312 if (a.evaluator_index != b.evaluator_index) {
313 return a.evaluator_index < b.evaluator_index;
314 }
317 }
318 };
319
324 int64_t fixed_cost;
329 // TODO(user): Find equivalent start/end nodes wrt dimensions and
330 // callbacks.
335 absl::StrongVector<DimensionIndex, int64_t> dimension_start_cumuls_min;
336 absl::StrongVector<DimensionIndex, int64_t> dimension_start_cumuls_max;
337 absl::StrongVector<DimensionIndex, int64_t> dimension_end_cumuls_min;
338 absl::StrongVector<DimensionIndex, int64_t> dimension_end_cumuls_max;
339 absl::StrongVector<DimensionIndex, int64_t> dimension_capacities;
342 absl::StrongVector<DimensionIndex, int64_t> dimension_evaluator_classes;
345
347 static bool LessThan(const VehicleClass& a, const VehicleClass& b);
348 };
349#endif // defined(SWIG)
350
357 int64_t fixed_cost;
358
359 bool operator<(const VehicleClassEntry& other) const {
360 return std::tie(fixed_cost, vehicle_class) <
361 std::tie(other.fixed_cost, other.vehicle_class);
362 }
363 };
364
365 int NumTypes() const { return sorted_vehicle_classes_per_type.size(); }
366
367 int Type(int vehicle) const {
368 DCHECK_LT(vehicle, type_index_of_vehicle.size());
369 return type_index_of_vehicle[vehicle];
370 }
371
372 std::vector<int> type_index_of_vehicle;
373 // clang-format off
374 std::vector<std::set<VehicleClassEntry> > sorted_vehicle_classes_per_type;
375 std::vector<std::deque<int> > vehicles_per_vehicle_class;
376 // clang-format on
377 };
378
379#ifndef SWIG
391 public:
394 public:
397
398 const Domain& start_domain() const { return start_domain_; }
399 const Domain& end_domain() const { return end_domain_; }
400
401 private:
405 Domain start_domain_;
407 Domain end_domain_;
408 };
409
411 class Resource {
412 public:
414 const RoutingDimension* dimension) const;
415
416 private:
417 explicit Resource(const RoutingModel* model) : model_(model) {}
418
419 void SetDimensionAttributes(Attributes attributes,
420 const RoutingDimension* dimension);
421 const Attributes& GetDefaultAttributes() const;
422
423 const RoutingModel* const model_;
424 absl::flat_hash_map<DimensionIndex, Attributes> dimension_attributes_;
425
426 friend class ResourceGroup;
427 };
428
429 explicit ResourceGroup(const RoutingModel* model) : model_(model) {}
430
433 void AddResource(Attributes attributes, const RoutingDimension* dimension);
434
435 const std::vector<Resource>& GetResources() const { return resources_; }
436 const absl::flat_hash_set<DimensionIndex>& GetAffectedDimensionIndices()
437 const {
438 return affected_dimension_indices_;
439 }
440 int Size() const { return resources_.size(); }
441
442 private:
443 const RoutingModel* const model_;
444 std::vector<Resource> resources_;
446 absl::flat_hash_set<DimensionIndex> affected_dimension_indices_;
447 };
448#endif // SWIG
449
451 static const int64_t kNoPenalty;
452
456
460
464 explicit RoutingModel(const RoutingIndexManager& index_manager);
465 RoutingModel(const RoutingIndexManager& index_manager,
466 const RoutingModelParameters& parameters);
468
470 int RegisterUnaryTransitVector(std::vector<int64_t> values);
473
475 std::vector<std::vector<int64_t> /*needed_for_swig*/> values);
478
480 const TransitCallback2& TransitCallback(int callback_index) const {
481 CHECK_LT(callback_index, transit_evaluators_.size());
482 return transit_evaluators_[callback_index];
483 }
484 const TransitCallback1& UnaryTransitCallbackOrNull(int callback_index) const {
485 CHECK_LT(callback_index, unary_transit_evaluators_.size());
486 return unary_transit_evaluators_[callback_index];
487 }
489 int callback_index) const {
490 CHECK_LT(callback_index, state_dependent_transit_evaluators_.size());
491 return state_dependent_transit_evaluators_[callback_index];
492 }
493
495
507
516 bool AddDimension(int evaluator_index, int64_t slack_max, int64_t capacity,
517 bool fix_start_cumul_to_zero, const std::string& name);
519 const std::vector<int>& evaluator_indices, int64_t slack_max,
520 int64_t capacity, bool fix_start_cumul_to_zero, const std::string& name);
521 bool AddDimensionWithVehicleCapacity(int evaluator_index, int64_t slack_max,
522 std::vector<int64_t> vehicle_capacities,
523 bool fix_start_cumul_to_zero,
524 const std::string& name);
526 const std::vector<int>& evaluator_indices, int64_t slack_max,
527 std::vector<int64_t> vehicle_capacities, bool fix_start_cumul_to_zero,
528 const std::string& name);
537 std::pair<int, bool> AddConstantDimensionWithSlack(
538 int64_t value, int64_t capacity, int64_t slack_max,
539 bool fix_start_cumul_to_zero, const std::string& name);
540 std::pair<int, bool> AddConstantDimension(int64_t value, int64_t capacity,
541 bool fix_start_cumul_to_zero,
542 const std::string& name) {
543 return AddConstantDimensionWithSlack(value, capacity, 0,
544 fix_start_cumul_to_zero, name);
545 }
555 std::pair<int, bool> AddVectorDimension(std::vector<int64_t> values,
556 int64_t capacity,
557 bool fix_start_cumul_to_zero,
558 const std::string& name);
568 std::pair<int, bool> AddMatrixDimension(
569 std::vector<std::vector<int64_t> /*needed_for_swig*/> values,
570 int64_t capacity, bool fix_start_cumul_to_zero, const std::string& name);
578 const std::vector<int>& pure_transits,
579 const std::vector<int>& dependent_transits,
580 const RoutingDimension* base_dimension, int64_t slack_max,
581 std::vector<int64_t> vehicle_capacities, bool fix_start_cumul_to_zero,
582 const std::string& name) {
583 return AddDimensionDependentDimensionWithVehicleCapacityInternal(
584 pure_transits, dependent_transits, base_dimension, slack_max,
585 std::move(vehicle_capacities), fix_start_cumul_to_zero, name);
586 }
587
590 const std::vector<int>& transits, const RoutingDimension* base_dimension,
591 int64_t slack_max, std::vector<int64_t> vehicle_capacities,
592 bool fix_start_cumul_to_zero, const std::string& name);
595 int transit, const RoutingDimension* base_dimension, int64_t slack_max,
596 int64_t vehicle_capacity, bool fix_start_cumul_to_zero,
597 const std::string& name);
599 int pure_transit, int dependent_transit,
600 const RoutingDimension* base_dimension, int64_t slack_max,
601 int64_t vehicle_capacity, bool fix_start_cumul_to_zero,
602 const std::string& name);
603
606 const std::function<int64_t(int64_t)>& f, int64_t domain_start,
607 int64_t domain_end);
608
619 std::vector<IntVar*> spans,
620 std::vector<IntVar*> total_slacks);
621
623 // TODO(user): rename.
624 std::vector<std::string> GetAllDimensionNames() const;
626 const std::vector<RoutingDimension*>& GetDimensions() const {
627 return dimensions_.get();
628 }
630 std::vector<RoutingDimension*> GetDimensionsWithSoftOrSpanCosts() const;
631 // clang-format off
634 const std::vector<std::unique_ptr<GlobalDimensionCumulOptimizer> >&
636 return global_dimension_optimizers_;
637 }
638 const std::vector<std::unique_ptr<GlobalDimensionCumulOptimizer> >&
640 return global_dimension_mp_optimizers_;
641 }
642 const std::vector<std::unique_ptr<LocalDimensionCumulOptimizer> >&
644 return local_dimension_optimizers_;
645 }
646 const std::vector<std::unique_ptr<LocalDimensionCumulOptimizer> >&
648 return local_dimension_mp_optimizers_;
649 }
650 // clang-format on
651
655 const RoutingDimension& dimension) const;
657 const RoutingDimension& dimension) const;
659 const RoutingDimension& dimension) const;
661 const RoutingDimension& dimension) const;
662
664 bool HasDimension(const std::string& dimension_name) const;
667 const std::string& dimension_name) const;
671 const std::string& dimension_name) const;
676 void SetPrimaryConstrainedDimension(const std::string& dimension_name) {
677 DCHECK(dimension_name.empty() || HasDimension(dimension_name));
678 primary_constrained_dimension_ = dimension_name;
679 }
681 const std::string& GetPrimaryConstrainedDimension() const {
682 return primary_constrained_dimension_;
683 }
684
685#ifndef SWIG
687 // clang-format off
688 const std::vector<std::unique_ptr<ResourceGroup> >& GetResourceGroups()
689 const {
690 return resource_groups_;
691 }
692#endif // SWIG
693 // clang-format on
696 const std::vector<int>& GetDimensionResourceGroupIndices(
697 const RoutingDimension* dimension) const;
698
715 DisjunctionIndex AddDisjunction(const std::vector<int64_t>& indices,
716 int64_t penalty = kNoPenalty,
717 int64_t max_cardinality = 1);
719 const std::vector<DisjunctionIndex>& GetDisjunctionIndices(
720 int64_t index) const {
721 return index_to_disjunctions_[index];
722 }
726 template <typename F>
728 int64_t index, int64_t max_cardinality, F f) const {
729 for (const DisjunctionIndex disjunction : GetDisjunctionIndices(index)) {
730 if (disjunctions_[disjunction].value.max_cardinality == max_cardinality) {
731 for (const int64_t d_index : disjunctions_[disjunction].indices) {
732 f(d_index);
733 }
734 }
735 }
736 }
737#if !defined(SWIGPYTHON)
740 const std::vector<int64_t>& GetDisjunctionNodeIndices(
741 DisjunctionIndex index) const {
742 return disjunctions_[index].indices;
743 }
744#endif // !defined(SWIGPYTHON)
746 int64_t GetDisjunctionPenalty(DisjunctionIndex index) const {
747 return disjunctions_[index].value.penalty;
748 }
752 return disjunctions_[index].value.max_cardinality;
753 }
755 int GetNumberOfDisjunctions() const { return disjunctions_.size(); }
760 std::vector<std::pair<int64_t, int64_t>> GetPerfectBinaryDisjunctions() const;
767
771 void AddSoftSameVehicleConstraint(const std::vector<int64_t>& indices,
772 int64_t cost);
773
778 void SetAllowedVehiclesForIndex(const std::vector<int>& vehicles,
779 int64_t index);
780
782 bool IsVehicleAllowedForIndex(int vehicle, int64_t index) {
783 return allowed_vehicles_[index].empty() ||
784 allowed_vehicles_[index].find(vehicle) !=
785 allowed_vehicles_[index].end();
786 }
787
802 // TODO(user): Remove this when model introspection detects linked nodes.
803 void AddPickupAndDelivery(int64_t pickup, int64_t delivery);
808 DisjunctionIndex delivery_disjunction);
809 // clang-format off
813 const std::vector<std::pair<int, int> >&
814 GetPickupIndexPairs(int64_t node_index) const;
816 const std::vector<std::pair<int, int> >&
817 GetDeliveryIndexPairs(int64_t node_index) const;
818 // clang-format on
819
824 int vehicle);
826 int vehicle) const;
829
831
832#ifndef SWIG
835 return pickup_delivery_pairs_;
836 }
837 const std::vector<std::pair<DisjunctionIndex, DisjunctionIndex>>&
839 return pickup_delivery_disjunctions_;
840 }
846 DCHECK(closed_);
847 return implicit_pickup_delivery_pairs_without_alternatives_;
848 }
849#endif // SWIG
861 enum VisitTypePolicy {
876 TYPE_SIMULTANEOUSLY_ADDED_AND_REMOVED
877 };
878 // TODO(user): Support multiple visit types per node?
879 void SetVisitType(int64_t index, int type, VisitTypePolicy type_policy);
880 int GetVisitType(int64_t index) const;
881 const std::vector<int>& GetSingleNodesOfType(int type) const;
882 const std::vector<int>& GetPairIndicesOfType(int type) const;
886 // TODO(user): Reconsider the logic and potentially remove the need to
889 int GetNumberOfVisitTypes() const { return num_visit_types_; }
890#ifndef SWIG
891 const std::vector<std::vector<int>>& GetTopologicallySortedVisitTypes()
892 const {
893 DCHECK(closed_);
894 return topologically_sorted_visit_types_;
895 }
896#endif // SWIG
901 void AddHardTypeIncompatibility(int type1, int type2);
902 void AddTemporalTypeIncompatibility(int type1, int type2);
904 const absl::flat_hash_set<int>& GetHardTypeIncompatibilitiesOfType(
905 int type) const;
906 const absl::flat_hash_set<int>& GetTemporalTypeIncompatibilitiesOfType(
907 int type) const;
911 return has_hard_type_incompatibilities_;
912 }
914 return has_temporal_type_incompatibilities_;
915 }
927 int dependent_type, absl::flat_hash_set<int> required_type_alternatives);
933 int dependent_type, absl::flat_hash_set<int> required_type_alternatives);
940 int dependent_type, absl::flat_hash_set<int> required_type_alternatives);
941 // clang-format off
944 const std::vector<absl::flat_hash_set<int> >&
947 const std::vector<absl::flat_hash_set<int> >&
950 const std::vector<absl::flat_hash_set<int> >&
952 // clang-format on
956 return has_same_vehicle_type_requirements_;
957 }
959 return has_temporal_type_requirements_;
960 }
961
964 bool HasTypeRegulations() const {
965 return HasTemporalTypeIncompatibilities() ||
966 HasHardTypeIncompatibilities() || HasSameVehicleTypeRequirements() ||
967 HasTemporalTypeRequirements();
968 }
969
974 int64_t UnperformedPenalty(int64_t var_index) const;
978 int64_t UnperformedPenaltyOrValue(int64_t default_value,
979 int64_t var_index) const;
983 int64_t GetDepot() const;
984
989 void SetMaximumNumberOfActiveVehicles(int max_active_vehicles) {
990 max_active_vehicles_ = max_active_vehicles;
991 }
993 int GetMaximumNumberOfActiveVehicles() const { return max_active_vehicles_; }
997 void SetArcCostEvaluatorOfAllVehicles(int evaluator_index);
999 void SetArcCostEvaluatorOfVehicle(int evaluator_index, int vehicle);
1002 void SetFixedCostOfAllVehicles(int64_t cost);
1004 void SetFixedCostOfVehicle(int64_t cost, int vehicle);
1008 int64_t GetFixedCostOfVehicle(int vehicle) const;
1009
1025 void SetAmortizedCostFactorsOfAllVehicles(int64_t linear_cost_factor,
1026 int64_t quadratic_cost_factor);
1028 void SetAmortizedCostFactorsOfVehicle(int64_t linear_cost_factor,
1029 int64_t quadratic_cost_factor,
1030 int vehicle);
1031
1032 const std::vector<int64_t>& GetAmortizedLinearCostFactorOfVehicles() const {
1033 return linear_cost_factor_of_vehicle_;
1034 }
1035 const std::vector<int64_t>& GetAmortizedQuadraticCostFactorOfVehicles()
1036 const {
1037 return quadratic_cost_factor_of_vehicle_;
1038 }
1039
1040 void ConsiderEmptyRouteCostsForVehicle(bool consider_costs, int vehicle) {
1041 DCHECK_LT(vehicle, vehicles_);
1042 consider_empty_route_costs_[vehicle] = consider_costs;
1043 }
1044
1046 DCHECK_LT(vehicle, vehicles_);
1047 return consider_empty_route_costs_[vehicle];
1048 }
1049
1052#ifndef SWIG
1054 return first_solution_evaluator_;
1055 }
1056#endif
1059 first_solution_evaluator_ = std::move(evaluator);
1060 }
1065 void AddSearchMonitor(SearchMonitor* const monitor);
1069 void AddAtSolutionCallback(std::function<void()> callback);
1083 void AddVariableTargetToFinalizer(IntVar* var, int64_t target);
1094 const RoutingSearchParameters& search_parameters);
1101 const Assignment* Solve(const Assignment* assignment = nullptr);
1110 const RoutingSearchParameters& search_parameters,
1111 std::vector<const Assignment*>* solutions = nullptr);
1115 const Assignment* assignment,
1116 const RoutingSearchParameters& search_parameters,
1117 std::vector<const Assignment*>* solutions = nullptr);
1121 const std::vector<const Assignment*>& assignments,
1122 const RoutingSearchParameters& search_parameters,
1123 std::vector<const Assignment*>* solutions = nullptr);
1130 Assignment* target_assignment, const RoutingModel* source_model,
1131 const Assignment* source_assignment);
1137 // TODO(user): Add support for non-homogeneous costs and disjunctions.
1140 Status status() const { return status_; }
1149 IntVar* ApplyLocks(const std::vector<int64_t>& locks);
1158 bool ApplyLocksToAllVehicles(const std::vector<std::vector<int64_t>>& locks,
1159 bool close_routes);
1164 const Assignment* const PreAssignment() const { return preassignment_; }
1165 Assignment* MutablePreAssignment() { return preassignment_; }
1169 bool WriteAssignment(const std::string& file_name) const;
1173 Assignment* ReadAssignment(const std::string& file_name);
1183 const std::vector<std::vector<int64_t>>& routes,
1184 bool ignore_inactive_indices);
1201 bool RoutesToAssignment(const std::vector<std::vector<int64_t>>& routes,
1202 bool ignore_inactive_indices, bool close_routes,
1203 Assignment* const assignment) const;
1208 const Assignment& assignment,
1209 std::vector<std::vector<int64_t>>* const routes) const;
1214#ifndef SWIG
1215 std::vector<std::vector<int64_t>> GetRoutesFromAssignment(
1216 const Assignment& assignment);
1217#endif
1235 Assignment* CompactAssignment(const Assignment& assignment) const;
1241 void AddToAssignment(IntVar* const var);
1254 const Assignment* original_assignment, absl::Duration duration_limit);
1255#ifndef SWIG
1256 // TODO(user): Revisit if coordinates are added to the RoutingModel class.
1257 void SetSweepArranger(SweepArranger* sweep_arranger);
1259 SweepArranger* sweep_arranger() const;
1260#endif
1267 CHECK(filter != nullptr);
1268 if (closed_) {
1269 LOG(WARNING) << "Model is closed, filter addition will be ignored.";
1270 }
1271 extra_filters_.push_back({filter, LocalSearchFilterManager::kRelax});
1272 extra_filters_.push_back({filter, LocalSearchFilterManager::kAccept});
1273 }
1274
1277 int64_t Start(int vehicle) const { return starts_[vehicle]; }
1279 int64_t End(int vehicle) const { return ends_[vehicle]; }
1281 bool IsStart(int64_t index) const;
1283 bool IsEnd(int64_t index) const { return index >= Size(); }
1286 int VehicleIndex(int64_t index) const { return index_to_vehicle_[index]; }
1290 int64_t Next(const Assignment& assignment, int64_t index) const;
1292 bool IsVehicleUsed(const Assignment& assignment, int vehicle) const;
1293
1294#if !defined(SWIGPYTHON)
1297 const std::vector<IntVar*>& Nexts() const { return nexts_; }
1300 const std::vector<IntVar*>& VehicleVars() const { return vehicle_vars_; }
1301#endif
1304 IntVar* NextVar(int64_t index) const { return nexts_[index]; }
1306 IntVar* ActiveVar(int64_t index) const { return active_[index]; }
1309 IntVar* ActiveVehicleVar(int vehicle) const {
1310 return vehicle_active_[vehicle];
1311 }
1314 IntVar* VehicleCostsConsideredVar(int vehicle) const {
1315 return vehicle_costs_considered_[vehicle];
1316 }
1319 IntVar* VehicleVar(int64_t index) const { return vehicle_vars_[index]; }
1321 IntVar* CostVar() const { return cost_; }
1322
1325 int64_t GetArcCostForVehicle(int64_t from_index, int64_t to_index,
1326 int64_t vehicle) const;
1329 return costs_are_homogeneous_across_vehicles_;
1330 }
1333 int64_t GetHomogeneousCost(int64_t from_index, int64_t to_index) const {
1334 return GetArcCostForVehicle(from_index, to_index, /*vehicle=*/0);
1335 }
1338 int64_t GetArcCostForFirstSolution(int64_t from_index,
1339 int64_t to_index) const;
1346 int64_t GetArcCostForClass(int64_t from_index, int64_t to_index,
1347 int64_t /*CostClassIndex*/ cost_class_index) const;
1350 DCHECK(closed_);
1351 DCHECK_GE(vehicle, 0);
1352 DCHECK_LT(vehicle, cost_class_index_of_vehicle_.size());
1353 DCHECK_GE(cost_class_index_of_vehicle_[vehicle], 0);
1354 return cost_class_index_of_vehicle_[vehicle];
1355 }
1358 bool HasVehicleWithCostClassIndex(CostClassIndex cost_class_index) const {
1359 DCHECK(closed_);
1360 if (cost_class_index == kCostClassIndexOfZeroCost) {
1361 return has_vehicle_with_zero_cost_class_;
1362 }
1363 return cost_class_index < cost_classes_.size();
1364 }
1366 int GetCostClassesCount() const { return cost_classes_.size(); }
1369 return std::max(0, GetCostClassesCount() - 1);
1370 }
1372 DCHECK(closed_);
1373 return vehicle_class_index_of_vehicle_[vehicle];
1374 }
1377 int GetVehicleOfClass(VehicleClassIndex vehicle_class) const {
1378 DCHECK(closed_);
1379 const RoutingModel::VehicleTypeContainer& vehicle_type_container =
1380 GetVehicleTypeContainer();
1381 if (vehicle_class.value() >= GetVehicleClassesCount() ||
1382 vehicle_type_container.vehicles_per_vehicle_class[vehicle_class.value()]
1383 .empty()) {
1384 return -1;
1385 }
1386 return vehicle_type_container
1387 .vehicles_per_vehicle_class[vehicle_class.value()]
1388 .front();
1389 }
1391 int GetVehicleClassesCount() const { return vehicle_classes_.size(); }
1393 const std::vector<int>& GetSameVehicleIndicesOfIndex(int node) const {
1394 DCHECK(closed_);
1395 return same_vehicle_groups_[same_vehicle_group_[node]];
1396 }
1397
1399 DCHECK(closed_);
1400 return vehicle_type_container_;
1401 }
1402
1421 bool ArcIsMoreConstrainedThanArc(int64_t from, int64_t to1, int64_t to2);
1427 const Assignment& solution_assignment,
1428 const std::string& dimension_to_print) const;
1434#ifndef SWIG
1435 std::vector<std::vector<std::pair<int64_t, int64_t>>> GetCumulBounds(
1436 const Assignment& solution_assignment, const RoutingDimension& dimension);
1437#endif
1440 Solver* solver() const { return solver_.get(); }
1441
1443 bool CheckLimit() {
1444 DCHECK(limit_ != nullptr);
1445 return limit_->Check();
1446 }
1447
1449 absl::Duration RemainingTime() const {
1450 DCHECK(limit_ != nullptr);
1451 return limit_->AbsoluteSolverDeadline() - solver_->Now();
1452 }
1453
1456 int nodes() const { return nodes_; }
1458 int vehicles() const { return vehicles_; }
1460 int64_t Size() const { return nodes_ + vehicles_ - start_end_count_; }
1461
1465 const RoutingSearchParameters& search_parameters) const;
1467 const RoutingSearchParameters& search_parameters) const;
1471 return automatic_first_solution_strategy_;
1472 }
1473
1475 bool IsMatchingModel() const;
1476
1477#ifndef SWIG
1481 std::function<std::vector<operations_research::IntVar*>(RoutingModel*)>;
1482
1484#endif // SWIG
1485
1487 // TODO(user): Find a way to test and restrict the access at the same time.
1500 const RoutingDimension* dimension,
1501 std::function<int64_t(int64_t)> initializer);
1502#ifndef SWIG
1503 // TODO(user): MakeGreedyDescentLSOperator is too general for routing.h.
1508 static std::unique_ptr<LocalSearchOperator> MakeGreedyDescentLSOperator(
1509 std::vector<IntVar*> variables);
1510#endif
1525 const RoutingDimension* dimension);
1526
1527 private:
1529 enum RoutingLocalSearchOperator {
1530 RELOCATE = 0,
1531 RELOCATE_PAIR,
1532 LIGHT_RELOCATE_PAIR,
1533 RELOCATE_NEIGHBORS,
1534 EXCHANGE,
1535 EXCHANGE_PAIR,
1536 CROSS,
1537 CROSS_EXCHANGE,
1538 TWO_OPT,
1539 OR_OPT,
1540 GLOBAL_CHEAPEST_INSERTION_CLOSE_NODES_LNS,
1541 LOCAL_CHEAPEST_INSERTION_CLOSE_NODES_LNS,
1542 GLOBAL_CHEAPEST_INSERTION_PATH_LNS,
1543 LOCAL_CHEAPEST_INSERTION_PATH_LNS,
1544 RELOCATE_PATH_GLOBAL_CHEAPEST_INSERTION_INSERT_UNPERFORMED,
1545 GLOBAL_CHEAPEST_INSERTION_EXPENSIVE_CHAIN_LNS,
1546 LOCAL_CHEAPEST_INSERTION_EXPENSIVE_CHAIN_LNS,
1547 RELOCATE_EXPENSIVE_CHAIN,
1548 LIN_KERNIGHAN,
1549 TSP_OPT,
1550 MAKE_ACTIVE,
1551 RELOCATE_AND_MAKE_ACTIVE,
1552 MAKE_ACTIVE_AND_RELOCATE,
1553 MAKE_INACTIVE,
1554 MAKE_CHAIN_INACTIVE,
1555 SWAP_ACTIVE,
1556 EXTENDED_SWAP_ACTIVE,
1557 NODE_PAIR_SWAP,
1558 PATH_LNS,
1559 FULL_PATH_LNS,
1560 TSP_LNS,
1561 INACTIVE_LNS,
1562 EXCHANGE_RELOCATE_PAIR,
1563 RELOCATE_SUBTRIP,
1564 EXCHANGE_SUBTRIP,
1565 LOCAL_SEARCH_OPERATOR_COUNTER
1566 };
1567
1571 template <typename T>
1572 struct ValuedNodes {
1573 std::vector<int64_t> indices;
1574 T value;
1575 };
1576 struct DisjunctionValues {
1577 int64_t penalty;
1578 int64_t max_cardinality;
1579 };
1580 typedef ValuedNodes<DisjunctionValues> Disjunction;
1581
1584 struct CostCacheElement {
1590 int index;
1591 CostClassIndex cost_class_index;
1592 int64_t cost;
1593 };
1594
1596 void Initialize();
1597 void AddNoCycleConstraintInternal();
1598 bool AddDimensionWithCapacityInternal(
1599 const std::vector<int>& evaluator_indices, int64_t slack_max,
1600 std::vector<int64_t> vehicle_capacities, bool fix_start_cumul_to_zero,
1601 const std::string& name);
1602 bool AddDimensionDependentDimensionWithVehicleCapacityInternal(
1603 const std::vector<int>& pure_transits,
1604 const std::vector<int>& dependent_transits,
1605 const RoutingDimension* base_dimension, int64_t slack_max,
1606 std::vector<int64_t> vehicle_capacities, bool fix_start_cumul_to_zero,
1607 const std::string& name);
1608 bool InitializeDimensionInternal(
1609 const std::vector<int>& evaluator_indices,
1610 const std::vector<int>& state_dependent_evaluator_indices,
1611 int64_t slack_max, bool fix_start_cumul_to_zero,
1612 RoutingDimension* dimension);
1613 DimensionIndex GetDimensionIndex(const std::string& dimension_name) const;
1614
1642 void StoreDimensionCumulOptimizers(const RoutingSearchParameters& parameters);
1643
1644 void ComputeCostClasses(const RoutingSearchParameters& parameters);
1645 void ComputeVehicleClasses();
1653 void ComputeVehicleTypes();
1663 void FinalizeVisitTypes();
1664 // Called by FinalizeVisitTypes() to setup topologically_sorted_visit_types_.
1665 void TopologicallySortVisitTypes();
1666 int64_t GetArcCostForClassInternal(int64_t from_index, int64_t to_index,
1667 CostClassIndex cost_class_index) const;
1668 void AppendHomogeneousArcCosts(const RoutingSearchParameters& parameters,
1669 int node_index,
1670 std::vector<IntVar*>* cost_elements);
1671 void AppendArcCosts(const RoutingSearchParameters& parameters, int node_index,
1672 std::vector<IntVar*>* cost_elements);
1673 Assignment* DoRestoreAssignment();
1674 static const CostClassIndex kCostClassIndexOfZeroCost;
1675 int64_t SafeGetCostClassInt64OfVehicle(int64_t vehicle) const {
1676 DCHECK_LT(0, vehicles_);
1677 return (vehicle >= 0 ? GetCostClassIndexOfVehicle(vehicle)
1678 : kCostClassIndexOfZeroCost)
1679 .value();
1680 }
1681 int64_t GetDimensionTransitCostSum(int64_t i, int64_t j,
1682 const CostClass& cost_class) const;
1684 IntVar* CreateDisjunction(DisjunctionIndex disjunction);
1686 void AddPickupAndDeliverySetsInternal(const std::vector<int64_t>& pickups,
1687 const std::vector<int64_t>& deliveries);
1690 IntVar* CreateSameVehicleCost(int vehicle_index);
1693 int FindNextActive(int index, const std::vector<int64_t>& indices) const;
1694
1697 bool RouteCanBeUsedByVehicle(const Assignment& assignment, int start_index,
1698 int vehicle) const;
1706 bool ReplaceUnusedVehicle(int unused_vehicle, int active_vehicle,
1707 Assignment* compact_assignment) const;
1708
1709 void QuietCloseModel();
1710 void QuietCloseModelWithParameters(
1711 const RoutingSearchParameters& parameters) {
1712 if (!closed_) {
1713 CloseModelWithParameters(parameters);
1714 }
1715 }
1716
1718 bool SolveMatchingModel(Assignment* assignment,
1719 const RoutingSearchParameters& parameters);
1720#ifndef SWIG
1722 bool AppendAssignmentIfFeasible(
1723 const Assignment& assignment,
1724 std::vector<std::unique_ptr<Assignment>>* assignments);
1725#endif
1727 void LogSolution(const RoutingSearchParameters& parameters,
1728 const std::string& description, int64_t solution_cost,
1729 int64_t start_time_ms);
1732 Assignment* CompactAssignmentInternal(const Assignment& assignment,
1733 bool check_compact_assignment) const;
1738 std::string FindErrorInSearchParametersForModel(
1739 const RoutingSearchParameters& search_parameters) const;
1741 void SetupSearch(const RoutingSearchParameters& search_parameters);
1743 // TODO(user): Document each auxiliary method.
1744 Assignment* GetOrCreateAssignment();
1745 Assignment* GetOrCreateTmpAssignment();
1746 RegularLimit* GetOrCreateLimit();
1747 RegularLimit* GetOrCreateLocalSearchLimit();
1748 RegularLimit* GetOrCreateLargeNeighborhoodSearchLimit();
1749 RegularLimit* GetOrCreateFirstSolutionLargeNeighborhoodSearchLimit();
1750 LocalSearchOperator* CreateInsertionOperator();
1751 LocalSearchOperator* CreateMakeInactiveOperator();
1752 template <class T>
1753 LocalSearchOperator* CreateCPOperator(const T& operator_factory) {
1754 return operator_factory(solver_.get(), nexts_,
1755 CostsAreHomogeneousAcrossVehicles()
1756 ? std::vector<IntVar*>()
1757 : vehicle_vars_,
1758 vehicle_start_class_callback_);
1759 }
1760 template <class T>
1761 LocalSearchOperator* CreateCPOperator() {
1762 return CreateCPOperator(absl::bind_front(MakeLocalSearchOperator<T>));
1763 }
1764 template <class T, class Arg>
1765 LocalSearchOperator* CreateOperator(const Arg& arg) {
1766 return solver_->RevAlloc(new T(nexts_,
1767 CostsAreHomogeneousAcrossVehicles()
1768 ? std::vector<IntVar*>()
1769 : vehicle_vars_,
1770 vehicle_start_class_callback_, arg));
1771 }
1772 template <class T>
1773 LocalSearchOperator* CreatePairOperator() {
1774 return CreateOperator<T>(pickup_delivery_pairs_);
1775 }
1776 void CreateNeighborhoodOperators(const RoutingSearchParameters& parameters);
1777 LocalSearchOperator* ConcatenateOperators(
1778 const RoutingSearchParameters& search_parameters,
1779 const std::vector<LocalSearchOperator*>& operators) const;
1780 LocalSearchOperator* GetNeighborhoodOperators(
1781 const RoutingSearchParameters& search_parameters) const;
1782 std::vector<LocalSearchFilterManager::FilterEvent>
1783 GetOrCreateLocalSearchFilters(const RoutingSearchParameters& parameters,
1784 bool filter_cost = true);
1785 LocalSearchFilterManager* GetOrCreateLocalSearchFilterManager(
1786 const RoutingSearchParameters& parameters);
1787 std::vector<LocalSearchFilterManager::FilterEvent>
1788 GetOrCreateFeasibilityFilters(const RoutingSearchParameters& parameters);
1789 LocalSearchFilterManager* GetOrCreateFeasibilityFilterManager(
1790 const RoutingSearchParameters& parameters);
1791 LocalSearchFilterManager* GetOrCreateStrongFeasibilityFilterManager(
1792 const RoutingSearchParameters& parameters);
1793 DecisionBuilder* CreateSolutionFinalizer(SearchLimit* lns_limit);
1794 DecisionBuilder* CreateFinalizerForMinimizedAndMaximizedVariables();
1795 void CreateFirstSolutionDecisionBuilders(
1796 const RoutingSearchParameters& search_parameters);
1797 DecisionBuilder* GetFirstSolutionDecisionBuilder(
1798 const RoutingSearchParameters& search_parameters) const;
1799 IntVarFilteredDecisionBuilder* GetFilteredFirstSolutionDecisionBuilderOrNull(
1800 const RoutingSearchParameters& parameters) const;
1801 LocalSearchPhaseParameters* CreateLocalSearchParameters(
1802 const RoutingSearchParameters& search_parameters);
1803 DecisionBuilder* CreateLocalSearchDecisionBuilder(
1804 const RoutingSearchParameters& search_parameters);
1805 void SetupDecisionBuilders(const RoutingSearchParameters& search_parameters);
1806 void SetupMetaheuristics(const RoutingSearchParameters& search_parameters);
1807 void SetupAssignmentCollector(
1808 const RoutingSearchParameters& search_parameters);
1809 void SetupTrace(const RoutingSearchParameters& search_parameters);
1810 void SetupImprovementLimit(const RoutingSearchParameters& search_parameters);
1811 void SetupSearchMonitors(const RoutingSearchParameters& search_parameters);
1812 bool UsesLightPropagation(
1813 const RoutingSearchParameters& search_parameters) const;
1814 GetTabuVarsCallback tabu_var_callback_;
1815
1816 // Detects implicit pickup delivery pairs. These pairs are
1817 // non-pickup/delivery pairs for which there exists a unary dimension such
1818 // that the demand d of the implicit pickup is positive and the demand of the
1819 // implicit delivery is equal to -d.
1820 void DetectImplicitPickupAndDeliveries();
1821
1822 int GetVehicleStartClass(int64_t start) const;
1823
1824 void InitSameVehicleGroups(int number_of_groups) {
1825 same_vehicle_group_.assign(Size(), 0);
1826 same_vehicle_groups_.assign(number_of_groups, {});
1827 }
1828 void SetSameVehicleGroup(int index, int group) {
1829 same_vehicle_group_[index] = group;
1830 same_vehicle_groups_[group].push_back(index);
1831 }
1832
1834 std::unique_ptr<Solver> solver_;
1835 int nodes_;
1836 int vehicles_;
1837 int max_active_vehicles_;
1838 Constraint* no_cycle_constraint_ = nullptr;
1840 std::vector<IntVar*> nexts_;
1841 std::vector<IntVar*> vehicle_vars_;
1842 std::vector<IntVar*> active_;
1843 // The following vectors are indexed by vehicle index.
1844 std::vector<IntVar*> vehicle_active_;
1845 std::vector<IntVar*> vehicle_costs_considered_;
1850 std::vector<IntVar*> is_bound_to_end_;
1851 mutable RevSwitch is_bound_to_end_ct_added_;
1853 absl::flat_hash_map<std::string, DimensionIndex> dimension_name_to_index_;
1854 absl::StrongVector<DimensionIndex, RoutingDimension*> dimensions_;
1859 // clang-format off
1860 std::vector<std::unique_ptr<ResourceGroup> > resource_groups_;
1862 absl::StrongVector<DimensionIndex, std::vector<int> >
1863 dimension_resource_group_indices_;
1864
1868 std::vector<std::unique_ptr<GlobalDimensionCumulOptimizer> >
1869 global_dimension_optimizers_;
1870 std::vector<std::unique_ptr<GlobalDimensionCumulOptimizer> >
1871 global_dimension_mp_optimizers_;
1872 absl::StrongVector<DimensionIndex, int> global_optimizer_index_;
1873 std::vector<std::unique_ptr<LocalDimensionCumulOptimizer> >
1874 local_dimension_optimizers_;
1875 std::vector<std::unique_ptr<LocalDimensionCumulOptimizer> >
1876 local_dimension_mp_optimizers_;
1877 // clang-format off
1878 absl::StrongVector<DimensionIndex, int> local_optimizer_index_;
1879 std::string primary_constrained_dimension_;
1881 IntVar* cost_ = nullptr;
1882 std::vector<int> vehicle_to_transit_cost_;
1883 std::vector<int64_t> fixed_cost_of_vehicle_;
1884 std::vector<CostClassIndex> cost_class_index_of_vehicle_;
1885 bool has_vehicle_with_zero_cost_class_;
1886 std::vector<int64_t> linear_cost_factor_of_vehicle_;
1887 std::vector<int64_t> quadratic_cost_factor_of_vehicle_;
1888 bool vehicle_amortized_cost_factors_set_;
1899 std::vector<bool> consider_empty_route_costs_;
1900#ifndef SWIG
1901 absl::StrongVector<CostClassIndex, CostClass> cost_classes_;
1902#endif // SWIG
1903 bool costs_are_homogeneous_across_vehicles_;
1904 bool cache_callbacks_;
1905 mutable std::vector<CostCacheElement> cost_cache_;
1906 std::vector<VehicleClassIndex> vehicle_class_index_of_vehicle_;
1907#ifndef SWIG
1908 absl::StrongVector<VehicleClassIndex, VehicleClass> vehicle_classes_;
1909#endif // SWIG
1910 VehicleTypeContainer vehicle_type_container_;
1911 std::function<int(int64_t)> vehicle_start_class_callback_;
1913 absl::StrongVector<DisjunctionIndex, Disjunction> disjunctions_;
1914 std::vector<std::vector<DisjunctionIndex> > index_to_disjunctions_;
1916 std::vector<ValuedNodes<int64_t> > same_vehicle_costs_;
1918#ifndef SWIG
1919 std::vector<absl::flat_hash_set<int>> allowed_vehicles_;
1920#endif // SWIG
1922 IndexPairs pickup_delivery_pairs_;
1923 IndexPairs implicit_pickup_delivery_pairs_without_alternatives_;
1924 std::vector<std::pair<DisjunctionIndex, DisjunctionIndex> >
1925 pickup_delivery_disjunctions_;
1926 // clang-format off
1927 // If node_index is a pickup, index_to_pickup_index_pairs_[node_index] is the
1928 // vector of pairs {pair_index, pickup_index} such that
1929 // (pickup_delivery_pairs_[pair_index].first)[pickup_index] == node_index
1930 std::vector<std::vector<std::pair<int, int> > > index_to_pickup_index_pairs_;
1931 // Same as above for deliveries.
1932 std::vector<std::vector<std::pair<int, int> > >
1933 index_to_delivery_index_pairs_;
1934 // clang-format on
1935 std::vector<PickupAndDeliveryPolicy> vehicle_pickup_delivery_policy_;
1936 // Same vehicle group to which a node belongs.
1937 std::vector<int> same_vehicle_group_;
1938 // Same vehicle node groups.
1939 std::vector<std::vector<int>> same_vehicle_groups_;
1940 // Node visit types
1941 // Variable index to visit type index.
1942 std::vector<int> index_to_visit_type_;
1943 // Variable index to VisitTypePolicy.
1944 std::vector<VisitTypePolicy> index_to_type_policy_;
1945 // clang-format off
1946 std::vector<std::vector<int> > single_nodes_of_type_;
1947 std::vector<std::vector<int> > pair_indices_of_type_;
1948
1949 std::vector<absl::flat_hash_set<int> >
1950 hard_incompatible_types_per_type_index_;
1951 bool has_hard_type_incompatibilities_;
1952 std::vector<absl::flat_hash_set<int> >
1953 temporal_incompatible_types_per_type_index_;
1954 bool has_temporal_type_incompatibilities_;
1955
1956 std::vector<std::vector<absl::flat_hash_set<int> > >
1957 same_vehicle_required_type_alternatives_per_type_index_;
1958 bool has_same_vehicle_type_requirements_;
1959 std::vector<std::vector<absl::flat_hash_set<int> > >
1960 required_type_alternatives_when_adding_type_index_;
1961 std::vector<std::vector<absl::flat_hash_set<int> > >
1962 required_type_alternatives_when_removing_type_index_;
1963 bool has_temporal_type_requirements_;
1964 absl::flat_hash_map</*type*/int, absl::flat_hash_set<VisitTypePolicy> >
1965 trivially_infeasible_visit_types_to_policies_;
1966
1967 // Visit types sorted topologically based on required-->dependent requirement
1968 // arcs between the types (if the requirement/dependency graph is acyclic).
1969 // Visit types of the same topological level are sorted in each sub-vector
1970 // by decreasing requirement "tightness", computed as the pair of the two
1971 // following criteria:
1972 //
1973 // 1) How highly *dependent* this type is, determined by
1974 // (total number of required alternative sets for that type)
1975 // / (average number of types in the required alternative sets)
1976 // 2) How highly *required* this type t is, computed as
1977 // SUM_{S required set containing t} ( 1 / |S| ),
1978 // i.e. the sum of reverse number of elements of all required sets
1979 // containing the type t.
1980 //
1981 // The higher these two numbers, the tighter the type is wrt requirements.
1982 std::vector<std::vector<int> > topologically_sorted_visit_types_;
1983 // clang-format on
1984 int num_visit_types_;
1985 // Two indices are equivalent if they correspond to the same node (as given
1986 // to the constructors taking a RoutingIndexManager).
1987 std::vector<int> index_to_equivalence_class_;
1988 std::vector<int> index_to_vehicle_;
1989 std::vector<int64_t> starts_;
1990 std::vector<int64_t> ends_;
1991 // TODO(user): b/62478706 Once the port is done, this shouldn't be needed
1992 // anymore.
1993 RoutingIndexManager manager_;
1994 int start_end_count_;
1995 // Model status
1996 bool closed_ = false;
1997 Status status_ = ROUTING_NOT_SOLVED;
1998 bool enable_deep_serialization_ = true;
1999
2000 // Search data
2001 std::vector<DecisionBuilder*> first_solution_decision_builders_;
2002 std::vector<IntVarFilteredDecisionBuilder*>
2003 first_solution_filtered_decision_builders_;
2004 Solver::IndexEvaluator2 first_solution_evaluator_;
2005 FirstSolutionStrategy::Value automatic_first_solution_strategy_ =
2006 FirstSolutionStrategy::UNSET;
2007 std::vector<LocalSearchOperator*> local_search_operators_;
2008 std::vector<SearchMonitor*> monitors_;
2009 SolutionCollector* collect_assignments_ = nullptr;
2010 SolutionCollector* collect_one_assignment_ = nullptr;
2011 SolutionCollector* packed_dimensions_assignment_collector_ = nullptr;
2012 DecisionBuilder* solve_db_ = nullptr;
2013 DecisionBuilder* improve_db_ = nullptr;
2014 DecisionBuilder* restore_assignment_ = nullptr;
2015 DecisionBuilder* restore_tmp_assignment_ = nullptr;
2016 Assignment* assignment_ = nullptr;
2017 Assignment* preassignment_ = nullptr;
2018 Assignment* tmp_assignment_ = nullptr;
2019 std::vector<IntVar*> extra_vars_;
2020 std::vector<IntervalVar*> extra_intervals_;
2021 std::vector<LocalSearchOperator*> extra_operators_;
2022 LocalSearchFilterManager* local_search_filter_manager_ = nullptr;
2023 LocalSearchFilterManager* feasibility_filter_manager_ = nullptr;
2024 LocalSearchFilterManager* strong_feasibility_filter_manager_ = nullptr;
2025 std::vector<LocalSearchFilterManager::FilterEvent> extra_filters_;
2026#ifndef SWIG
2027 std::vector<std::pair<IntVar*, int64_t>> finalizer_variable_cost_pairs_;
2028 std::vector<std::pair<IntVar*, int64_t>> finalizer_variable_target_pairs_;
2029 absl::flat_hash_map<IntVar*, int> finalizer_variable_cost_index_;
2030 absl::flat_hash_set<IntVar*> finalizer_variable_target_set_;
2031 std::unique_ptr<SweepArranger> sweep_arranger_;
2032#endif
2033
2034 RegularLimit* limit_ = nullptr;
2035 RegularLimit* ls_limit_ = nullptr;
2036 RegularLimit* lns_limit_ = nullptr;
2037 RegularLimit* first_solution_lns_limit_ = nullptr;
2038
2039 typedef std::pair<int64_t, int64_t> CacheKey;
2040 typedef absl::flat_hash_map<CacheKey, int64_t> TransitCallbackCache;
2041 typedef absl::flat_hash_map<CacheKey, StateDependentTransit>
2042 StateDependentTransitCallbackCache;
2043
2044 std::vector<TransitCallback1> unary_transit_evaluators_;
2045 std::vector<TransitCallback2> transit_evaluators_;
2046 // The following vector stores a boolean per transit_evaluator_, indicating
2047 // whether the transits are all positive.
2048 // is_transit_evaluator_positive_ will be set to true only when registering a
2049 // callback via RegisterPositiveTransitCallback(), and to false otherwise.
2050 // The actual positivity of the transit values will only be checked in debug
2051 // mode, when calling RegisterPositiveTransitCallback().
2052 // Therefore, RegisterPositiveTransitCallback() should only be called when the
2053 // transits are known to be positive, as the positivity of a callback will
2054 // allow some improvements in the solver, but will entail in errors if the
2055 // transits are falsely assumed positive.
2056 std::vector<bool> is_transit_evaluator_positive_;
2057 std::vector<VariableIndexEvaluator2> state_dependent_transit_evaluators_;
2058 std::vector<std::unique_ptr<StateDependentTransitCallbackCache>>
2059 state_dependent_transit_evaluators_cache_;
2060
2061 friend class RoutingDimension;
2062 friend class RoutingModelInspector;
2064
2065 DISALLOW_COPY_AND_ASSIGN(RoutingModel);
2066};
2067
2070 public:
2072 static const char kLightElement[];
2073 static const char kLightElement2[];
2074 static const char kRemoveValues[];
2075};
2076
2077#if !defined(SWIG)
2081 public:
2087 struct Tasks {
2088 int num_chain_tasks = 0;
2089 std::vector<int64_t> start_min;
2090 std::vector<int64_t> start_max;
2091 std::vector<int64_t> duration_min;
2092 std::vector<int64_t> duration_max;
2093 std::vector<int64_t> end_min;
2094 std::vector<int64_t> end_max;
2095 std::vector<bool> is_preemptible;
2096 std::vector<const SortedDisjointIntervalList*> forbidden_intervals;
2097 std::vector<std::pair<int64_t, int64_t>> distance_duration;
2098 int64_t span_min = 0;
2099 int64_t span_max = kint64max;
2100
2101 void Clear() {
2102 start_min.clear();
2103 start_max.clear();
2104 duration_min.clear();
2105 duration_max.clear();
2106 end_min.clear();
2107 end_max.clear();
2108 is_preemptible.clear();
2109 forbidden_intervals.clear();
2110 distance_duration.clear();
2111 span_min = 0;
2112 span_max = kint64max;
2113 num_chain_tasks = 0;
2114 }
2115 };
2116
2119 bool Propagate(Tasks* tasks);
2120
2122 bool Precedences(Tasks* tasks);
2125 bool MirrorTasks(Tasks* tasks);
2127 bool EdgeFinding(Tasks* tasks);
2137 bool ChainSpanMin(Tasks* tasks);
2143
2144 private:
2147 sat::ThetaLambdaTree<int64_t> theta_lambda_tree_;
2149 std::vector<int> tasks_by_start_min_;
2150 std::vector<int> tasks_by_end_max_;
2151 std::vector<int> event_of_task_;
2152 std::vector<int> nonchain_tasks_by_start_max_;
2154 std::vector<int64_t> total_duration_before_;
2155};
2156
2158 std::vector<int64_t> min_travels;
2159 std::vector<int64_t> max_travels;
2160 std::vector<int64_t> pre_travels;
2161 std::vector<int64_t> post_travels;
2162};
2163
2164void AppendTasksFromPath(const std::vector<int64_t>& path,
2165 const TravelBounds& travel_bounds,
2166 const RoutingDimension& dimension,
2168void AppendTasksFromIntervals(const std::vector<IntervalVar*>& intervals,
2170void FillPathEvaluation(const std::vector<int64_t>& path,
2171 const RoutingModel::TransitCallback2& evaluator,
2172 std::vector<int64_t>* values);
2173void FillTravelBoundsOfVehicle(int vehicle, const std::vector<int64_t>& path,
2174 const RoutingDimension& dimension,
2175 TravelBounds* travel_bounds);
2176#endif // !defined(SWIG)
2177
2189 public:
2191 std::string DebugString() const override {
2192 return "GlobalVehicleBreaksConstraint";
2193 }
2194
2195 void Post() override;
2196 void InitialPropagate() override;
2197
2198 private:
2199 void PropagateNode(int node);
2200 void PropagateVehicle(int vehicle);
2201 void PropagateMaxBreakDistance(int vehicle);
2202
2203 const RoutingModel* model_;
2204 const RoutingDimension* const dimension_;
2205 std::vector<Demon*> vehicle_demons_;
2206 std::vector<int64_t> path_;
2207
2212 void FillPartialPathOfVehicle(int vehicle);
2213 void FillPathTravels(const std::vector<int64_t>& path);
2214
2225 class TaskTranslator {
2226 public:
2227 TaskTranslator(IntVar* start, int64_t before_start, int64_t after_start)
2228 : start_(start),
2229 before_start_(before_start),
2230 after_start_(after_start) {}
2231 explicit TaskTranslator(IntervalVar* interval) : interval_(interval) {}
2232 TaskTranslator() {}
2233
2234 void SetStartMin(int64_t value) {
2235 if (start_ != nullptr) {
2236 start_->SetMin(CapAdd(before_start_, value));
2237 } else if (interval_ != nullptr) {
2238 interval_->SetStartMin(value);
2239 }
2240 }
2241 void SetStartMax(int64_t value) {
2242 if (start_ != nullptr) {
2243 start_->SetMax(CapAdd(before_start_, value));
2244 } else if (interval_ != nullptr) {
2245 interval_->SetStartMax(value);
2246 }
2247 }
2248 void SetDurationMin(int64_t value) {
2249 if (interval_ != nullptr) {
2250 interval_->SetDurationMin(value);
2251 }
2252 }
2253 void SetEndMin(int64_t value) {
2254 if (start_ != nullptr) {
2255 start_->SetMin(CapSub(value, after_start_));
2256 } else if (interval_ != nullptr) {
2257 interval_->SetEndMin(value);
2258 }
2259 }
2260 void SetEndMax(int64_t value) {
2261 if (start_ != nullptr) {
2262 start_->SetMax(CapSub(value, after_start_));
2263 } else if (interval_ != nullptr) {
2264 interval_->SetEndMax(value);
2265 }
2266 }
2267
2268 private:
2269 IntVar* start_ = nullptr;
2270 int64_t before_start_;
2271 int64_t after_start_;
2272 IntervalVar* interval_ = nullptr;
2273 };
2274
2276 std::vector<TaskTranslator> task_translators_;
2277
2279 DisjunctivePropagator disjunctive_propagator_;
2280 DisjunctivePropagator::Tasks tasks_;
2281
2283 TravelBounds travel_bounds_;
2284};
2285
2287 public:
2288 explicit TypeRegulationsChecker(const RoutingModel& model);
2290
2291 bool CheckVehicle(int vehicle,
2292 const std::function<int64_t(int64_t)>& next_accessor);
2293
2294 protected:
2295#ifndef SWIG
2297#endif // SWIG
2298
2303 int num_type_added_to_vehicle = 0;
2309 int num_type_removed_from_vehicle = 0;
2314 int position_of_last_type_on_vehicle_up_to_visit = -1;
2315 };
2316
2321 bool TypeOccursOnRoute(int type) const;
2328 bool TypeCurrentlyOnRoute(int type, int pos) const;
2329
2330 void InitializeCheck(int vehicle,
2331 const std::function<int64_t(int64_t)>& next_accessor);
2332 virtual void OnInitializeCheck() {}
2333 virtual bool HasRegulationsToCheck() const = 0;
2334 virtual bool CheckTypeRegulations(int type, VisitTypePolicy policy,
2335 int pos) = 0;
2336 virtual bool FinalizeCheck() const { return true; }
2337
2339
2340 private:
2341 std::vector<TypePolicyOccurrence> occurrences_of_type_;
2342 std::vector<int64_t> current_route_visits_;
2343};
2344
2347 public:
2349 bool check_hard_incompatibilities);
2351
2352 private:
2353 bool HasRegulationsToCheck() const override;
2354 bool CheckTypeRegulations(int type, VisitTypePolicy policy, int pos) override;
2358 bool check_hard_incompatibilities_;
2359};
2360
2363 public:
2365 : TypeRegulationsChecker(model) {}
2367
2368 private:
2369 bool HasRegulationsToCheck() const override;
2370 void OnInitializeCheck() override {
2371 types_with_same_vehicle_requirements_on_route_.clear();
2372 }
2373 // clang-format off
2376 bool CheckRequiredTypesCurrentlyOnRoute(
2377 const std::vector<absl::flat_hash_set<int> >& required_type_alternatives,
2378 int pos);
2379 // clang-format on
2380 bool CheckTypeRegulations(int type, VisitTypePolicy policy, int pos) override;
2381 bool FinalizeCheck() const override;
2382
2383 absl::flat_hash_set<int> types_with_same_vehicle_requirements_on_route_;
2384};
2385
2427 public:
2429
2430 void Post() override;
2431 void InitialPropagate() override;
2432
2433 private:
2434 void PropagateNodeRegulations(int node);
2435 void CheckRegulationsOnVehicle(int vehicle);
2436
2437 const RoutingModel& model_;
2438 TypeIncompatibilityChecker incompatibility_checker_;
2439 TypeRequirementChecker requirement_checker_;
2440 std::vector<Demon*> vehicle_demons_;
2441};
2442#if !defined SWIG
2456 public:
2457 struct BoundCost {
2458 int64_t bound;
2459 int64_t cost;
2460 };
2461 SimpleBoundCosts(int num_bounds, BoundCost default_bound_cost)
2462 : bound_costs_(num_bounds, default_bound_cost) {}
2463 BoundCost& bound_cost(int element) { return bound_costs_[element]; }
2464 BoundCost bound_cost(int element) const { return bound_costs_[element]; }
2465 int Size() { return bound_costs_.size(); }
2468
2469 private:
2470 std::vector<BoundCost> bound_costs_;
2471};
2472#endif // !defined SWIG
2473
2491// TODO(user): Break constraints need to know the service time of nodes
2495 public:
2498 RoutingModel* model() const { return model_; }
2502 int64_t GetTransitValue(int64_t from_index, int64_t to_index,
2503 int64_t vehicle) const;
2506 int64_t GetTransitValueFromClass(int64_t from_index, int64_t to_index,
2507 int64_t vehicle_class) const {
2508 return model_->TransitCallback(class_evaluators_[vehicle_class])(from_index,
2509 to_index);
2510 }
2513 IntVar* CumulVar(int64_t index) const { return cumuls_[index]; }
2514 IntVar* TransitVar(int64_t index) const { return transits_[index]; }
2515 IntVar* FixedTransitVar(int64_t index) const {
2516 return fixed_transits_[index];
2517 }
2518 IntVar* SlackVar(int64_t index) const { return slacks_[index]; }
2519
2520#if !defined(SWIGPYTHON)
2523 const std::vector<IntVar*>& cumuls() const { return cumuls_; }
2524 const std::vector<IntVar*>& fixed_transits() const { return fixed_transits_; }
2525 const std::vector<IntVar*>& transits() const { return transits_; }
2526 const std::vector<IntVar*>& slacks() const { return slacks_; }
2527#if !defined(SWIGCSHARP) && !defined(SWIGJAVA)
2529 const std::vector<SortedDisjointIntervalList>& forbidden_intervals() const {
2530 return forbidden_intervals_;
2531 }
2533 SortedDisjointIntervalList GetAllowedIntervalsInRange(
2534 int64_t index, int64_t min_value, int64_t max_value) const;
2538 int64_t min_value) const {
2539 DCHECK_LT(index, forbidden_intervals_.size());
2540 const SortedDisjointIntervalList& forbidden_intervals =
2541 forbidden_intervals_[index];
2542 const auto first_forbidden_interval_it =
2543 forbidden_intervals.FirstIntervalGreaterOrEqual(min_value);
2544 if (first_forbidden_interval_it != forbidden_intervals.end() &&
2545 min_value >= first_forbidden_interval_it->start) {
2547 return CapAdd(first_forbidden_interval_it->end, 1);
2548 }
2550 return min_value;
2551 }
2557 int64_t max_value) const {
2558 DCHECK_LT(index, forbidden_intervals_.size());
2559 const SortedDisjointIntervalList& forbidden_intervals =
2560 forbidden_intervals_[index];
2561 const auto last_forbidden_interval_it =
2562 forbidden_intervals.LastIntervalLessOrEqual(max_value);
2563 if (last_forbidden_interval_it != forbidden_intervals.end() &&
2564 max_value <= last_forbidden_interval_it->end) {
2566 return CapSub(last_forbidden_interval_it->start, 1);
2567 }
2569 return max_value;
2570 }
2572 const std::vector<int64_t>& vehicle_capacities() const {
2573 return vehicle_capacities_;
2574 }
2578 return model_->TransitCallback(
2579 class_evaluators_[vehicle_to_class_[vehicle]]);
2580 }
2581
2585 RoutingVehicleClassIndex vehicle_class) const {
2586 const int vehicle = model_->GetVehicleOfClass(vehicle_class);
2587 DCHECK_NE(vehicle, -1);
2588 return transit_evaluator(vehicle);
2589 }
2590
2595 int vehicle) const {
2596 return model_->UnaryTransitCallbackOrNull(
2597 class_evaluators_[vehicle_to_class_[vehicle]]);
2598 }
2601 bool AreVehicleTransitsPositive(int vehicle) const {
2602 return model()->is_transit_evaluator_positive_
2603 [class_evaluators_[vehicle_to_class_[vehicle]]];
2604 }
2605 int vehicle_to_class(int vehicle) const { return vehicle_to_class_[vehicle]; }
2606#endif
2607#endif
2611 void SetSpanUpperBoundForVehicle(int64_t upper_bound, int vehicle);
2618 void SetSpanCostCoefficientForVehicle(int64_t coefficient, int vehicle);
2619 void SetSpanCostCoefficientForAllVehicles(int64_t coefficient);
2626 void SetGlobalSpanCostCoefficient(int64_t coefficient);
2627
2628#ifndef SWIG
2634 const PiecewiseLinearFunction& cost);
2637 bool HasCumulVarPiecewiseLinearCost(int64_t index) const;
2640 const PiecewiseLinearFunction* GetCumulVarPiecewiseLinearCost(
2641 int64_t index) const;
2642#endif
2643
2652 void SetCumulVarSoftUpperBound(int64_t index, int64_t upper_bound,
2653 int64_t coefficient);
2656 bool HasCumulVarSoftUpperBound(int64_t index) const;
2660 int64_t GetCumulVarSoftUpperBound(int64_t index) const;
2664 int64_t GetCumulVarSoftUpperBoundCoefficient(int64_t index) const;
2665
2675 void SetCumulVarSoftLowerBound(int64_t index, int64_t lower_bound,
2676 int64_t coefficient);
2679 bool HasCumulVarSoftLowerBound(int64_t index) const;
2683 int64_t GetCumulVarSoftLowerBound(int64_t index) const;
2687 int64_t GetCumulVarSoftLowerBoundCoefficient(int64_t index) const;
2703 // TODO(user): Remove if !defined when routing.i is repaired.
2704#if !defined(SWIGPYTHON)
2705 void SetBreakIntervalsOfVehicle(std::vector<IntervalVar*> breaks, int vehicle,
2706 int pre_travel_evaluator,
2707 int post_travel_evaluator);
2708#endif // !defined(SWIGPYTHON)
2709
2711 void SetBreakIntervalsOfVehicle(std::vector<IntervalVar*> breaks, int vehicle,
2712 std::vector<int64_t> node_visit_transits);
2713
2718 void SetBreakDistanceDurationOfVehicle(int64_t distance, int64_t duration,
2719 int vehicle);
2725#if !defined(SWIGPYTHON)
2729 std::vector<IntervalVar*> breaks, int vehicle,
2730 std::vector<int64_t> node_visit_transits,
2731 std::function<int64_t(int64_t, int64_t)> delays);
2732
2734 const std::vector<IntervalVar*>& GetBreakIntervalsOfVehicle(
2735 int vehicle) const;
2738 // clang-format off
2739 const std::vector<std::pair<int64_t, int64_t> >&
2741 // clang-format on
2742#endif
2743 int GetPreTravelEvaluatorOfVehicle(int vehicle) const;
2744 int GetPostTravelEvaluatorOfVehicle(int vehicle) const;
2745
2747 const RoutingDimension* base_dimension() const { return base_dimension_; }
2755 int64_t ShortestTransitionSlack(int64_t node) const;
2756
2758 const std::string& name() const { return name_; }
2759
2761#ifndef SWIG
2762 const ReverseArcListGraph<int, int>& GetPathPrecedenceGraph() const {
2763 return path_precedence_graph_;
2764 }
2765#endif // SWIG
2766
2776 typedef std::function<int64_t(int, int)> PickupToDeliveryLimitFunction;
2777
2779 PickupToDeliveryLimitFunction limit_function, int pair_index);
2780
2782#ifndef SWIG
2783 int64_t GetPickupToDeliveryLimitForPair(int pair_index, int pickup,
2784 int delivery) const;
2785
2787 int64_t first_node;
2789 int64_t offset;
2790 };
2791
2793 node_precedences_.push_back(precedence);
2794 }
2795 const std::vector<NodePrecedence>& GetNodePrecedences() const {
2796 return node_precedences_;
2797 }
2798#endif // SWIG
2799
2800 void AddNodePrecedence(int64_t first_node, int64_t second_node,
2801 int64_t offset) {
2802 AddNodePrecedence({first_node, second_node, offset});
2803 }
2804
2805 int64_t GetSpanUpperBoundForVehicle(int vehicle) const {
2806 return vehicle_span_upper_bounds_[vehicle];
2807 }
2808#ifndef SWIG
2809 const std::vector<int64_t>& vehicle_span_upper_bounds() const {
2810 return vehicle_span_upper_bounds_;
2811 }
2812#endif // SWIG
2813 int64_t GetSpanCostCoefficientForVehicle(int vehicle) const {
2814 return vehicle_span_cost_coefficients_[vehicle];
2815 }
2816#ifndef SWIG
2818 RoutingVehicleClassIndex vehicle_class) const {
2819 const int vehicle = model_->GetVehicleOfClass(vehicle_class);
2820 DCHECK_NE(vehicle, -1);
2821 return GetSpanCostCoefficientForVehicle(vehicle);
2822 }
2823#endif // SWIG
2824#ifndef SWIG
2825 const std::vector<int64_t>& vehicle_span_cost_coefficients() const {
2826 return vehicle_span_cost_coefficients_;
2827 }
2828#endif // SWIG
2830 return global_span_cost_coefficient_;
2831 }
2832
2834 DCHECK_GE(global_optimizer_offset_, 0);
2835 return global_optimizer_offset_;
2836 }
2837 int64_t GetLocalOptimizerOffsetForVehicle(int vehicle) const {
2838 if (vehicle >= local_optimizer_offset_for_vehicle_.size()) {
2839 return 0;
2840 }
2841 DCHECK_GE(local_optimizer_offset_for_vehicle_[vehicle], 0);
2842 return local_optimizer_offset_for_vehicle_[vehicle];
2843 }
2844#if !defined SWIG
2848 int vehicle) {
2849 if (!HasSoftSpanUpperBounds()) {
2850 vehicle_soft_span_upper_bound_ = absl::make_unique<SimpleBoundCosts>(
2851 model_->vehicles(), SimpleBoundCosts::BoundCost{kint64max, 0});
2852 }
2853 vehicle_soft_span_upper_bound_->bound_cost(vehicle) = bound_cost;
2854 }
2856 return vehicle_soft_span_upper_bound_ != nullptr;
2857 }
2859 int vehicle) const {
2860 DCHECK(HasSoftSpanUpperBounds());
2861 return vehicle_soft_span_upper_bound_->bound_cost(vehicle);
2862 }
2866 SimpleBoundCosts::BoundCost bound_cost, int vehicle) {
2867 if (!HasQuadraticCostSoftSpanUpperBounds()) {
2868 vehicle_quadratic_cost_soft_span_upper_bound_ =
2869 absl::make_unique<SimpleBoundCosts>(
2870 model_->vehicles(), SimpleBoundCosts::BoundCost{kint64max, 0});
2871 }
2872 vehicle_quadratic_cost_soft_span_upper_bound_->bound_cost(vehicle) =
2873 bound_cost;
2874 }
2876 return vehicle_quadratic_cost_soft_span_upper_bound_ != nullptr;
2877 }
2879 int vehicle) const {
2880 DCHECK(HasQuadraticCostSoftSpanUpperBounds());
2881 return vehicle_quadratic_cost_soft_span_upper_bound_->bound_cost(vehicle);
2882 }
2883#endif
2884
2885 private:
2886 struct SoftBound {
2887 IntVar* var;
2888 int64_t bound;
2889 int64_t coefficient;
2890 };
2891
2892 struct PiecewiseLinearCost {
2893 PiecewiseLinearCost() : var(nullptr), cost(nullptr) {}
2894 IntVar* var;
2895 std::unique_ptr<PiecewiseLinearFunction> cost;
2896 };
2897
2898 class SelfBased {};
2899 RoutingDimension(RoutingModel* model, std::vector<int64_t> vehicle_capacities,
2900 const std::string& name,
2901 const RoutingDimension* base_dimension);
2902 RoutingDimension(RoutingModel* model, std::vector<int64_t> vehicle_capacities,
2903 const std::string& name, SelfBased);
2904 void Initialize(const std::vector<int>& transit_evaluators,
2905 const std::vector<int>& state_dependent_transit_evaluators,
2906 int64_t slack_max);
2907 void InitializeCumuls();
2908 void InitializeTransits(
2909 const std::vector<int>& transit_evaluators,
2910 const std::vector<int>& state_dependent_transit_evaluators,
2911 int64_t slack_max);
2912 void InitializeTransitVariables(int64_t slack_max);
2914 void SetupCumulVarSoftUpperBoundCosts(
2915 std::vector<IntVar*>* cost_elements) const;
2917 void SetupCumulVarSoftLowerBoundCosts(
2918 std::vector<IntVar*>* cost_elements) const;
2919 void SetupCumulVarPiecewiseLinearCosts(
2920 std::vector<IntVar*>* cost_elements) const;
2923 void SetupGlobalSpanCost(std::vector<IntVar*>* cost_elements) const;
2924 void SetupSlackAndDependentTransitCosts() const;
2926 void CloseModel(bool use_light_propagation);
2927
2928 void SetOffsetForGlobalOptimizer(int64_t offset) {
2929 global_optimizer_offset_ = std::max(Zero(), offset);
2930 }
2932 void SetVehicleOffsetsForLocalOptimizer(std::vector<int64_t> offsets) {
2934 std::transform(offsets.begin(), offsets.end(), offsets.begin(),
2935 [](int64_t offset) { return std::max(Zero(), offset); });
2936 local_optimizer_offset_for_vehicle_ = std::move(offsets);
2937 }
2938
2939 std::vector<IntVar*> cumuls_;
2940 std::vector<SortedDisjointIntervalList> forbidden_intervals_;
2941 std::vector<IntVar*> capacity_vars_;
2942 const std::vector<int64_t> vehicle_capacities_;
2943 std::vector<IntVar*> transits_;
2944 std::vector<IntVar*> fixed_transits_;
2947 std::vector<int> class_evaluators_;
2948 std::vector<int64_t> vehicle_to_class_;
2949#ifndef SWIG
2950 ReverseArcListGraph<int, int> path_precedence_graph_;
2951#endif
2952 // For every {first_node, second_node, offset} element in node_precedences_,
2953 // if both first_node and second_node are performed, then
2954 // cumuls_[second_node] must be greater than (or equal to)
2955 // cumuls_[first_node] + offset.
2956 std::vector<NodePrecedence> node_precedences_;
2957
2958 // The transits of a dimension may depend on its cumuls or the cumuls of
2959 // another dimension. There can be no cycles, except for self loops, a
2960 // typical example for this is a time dimension.
2961 const RoutingDimension* const base_dimension_;
2962
2963 // Values in state_dependent_class_evaluators_ correspond to the evaluators
2964 // in RoutingModel::state_dependent_transit_evaluators_ for each vehicle
2965 // class.
2966 std::vector<int> state_dependent_class_evaluators_;
2967 std::vector<int64_t> state_dependent_vehicle_to_class_;
2968
2969 // For each pickup/delivery pair_index for which limits have been set,
2970 // pickup_to_delivery_limits_per_pair_index_[pair_index] contains the
2971 // PickupToDeliveryLimitFunction for the pickup and deliveries in this pair.
2972 std::vector<PickupToDeliveryLimitFunction>
2973 pickup_to_delivery_limits_per_pair_index_;
2974
2975 // Used if some vehicle has breaks in this dimension, typically time.
2976 bool break_constraints_are_initialized_ = false;
2977 // clang-format off
2978 std::vector<std::vector<IntervalVar*> > vehicle_break_intervals_;
2979 std::vector<std::vector<std::pair<int64_t, int64_t> > >
2980 vehicle_break_distance_duration_;
2981 // clang-format on
2982 // For each vehicle, stores the part of travel that is made directly
2983 // after (before) the departure (arrival) node of the travel.
2984 // These parts of the travel are non-interruptible, in particular by a break.
2985 std::vector<int> vehicle_pre_travel_evaluators_;
2986 std::vector<int> vehicle_post_travel_evaluators_;
2987
2988 std::vector<IntVar*> slacks_;
2989 std::vector<IntVar*> dependent_transits_;
2990 std::vector<int64_t> vehicle_span_upper_bounds_;
2991 int64_t global_span_cost_coefficient_;
2992 std::vector<int64_t> vehicle_span_cost_coefficients_;
2993 std::vector<SoftBound> cumul_var_soft_upper_bound_;
2994 std::vector<SoftBound> cumul_var_soft_lower_bound_;
2995 std::vector<PiecewiseLinearCost> cumul_var_piecewise_linear_cost_;
2996 RoutingModel* const model_;
2997 const std::string name_;
2998 int64_t global_optimizer_offset_;
2999 std::vector<int64_t> local_optimizer_offset_for_vehicle_;
3001 std::unique_ptr<SimpleBoundCosts> vehicle_soft_span_upper_bound_;
3002 std::unique_ptr<SimpleBoundCosts>
3003 vehicle_quadratic_cost_soft_span_upper_bound_;
3004 friend class RoutingModel;
3005 friend class RoutingModelInspector;
3007 const std::vector<RoutingDimension*>& dimensions,
3008 const RoutingSearchParameters& parameters, bool filter_objective_cost,
3009 std::vector<LocalSearchFilterManager::FilterEvent>* filters);
3010
3011 DISALLOW_COPY_AND_ASSIGN(RoutingDimension);
3012};
3013
3017 std::vector<IntVar*> variables,
3018 std::vector<int64_t> targets);
3019
3025 const RoutingSearchParameters& search_parameters,
3026 const Assignment* initial_solution,
3027 Assignment* solution);
3028
3029#if !defined(SWIG)
3031 const RoutingModel& routing_model, const RoutingDimension& dimension);
3032#endif
3033
3034} // namespace operations_research
3035#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:2080
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:2188
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:2191
The class IntVar is a subset of IntExpr.
Interval variables are often used in scheduling.
Local Search Filters are used for fast neighbor pruning.
The base class for all local search operators.
Dimensions represent quantities accumulated at nodes along the routes.
Definition: routing.h:2494
void SetQuadraticCostSoftSpanUpperBoundForVehicle(SimpleBoundCosts::BoundCost bound_cost, int vehicle)
If the span of vehicle on this dimension is larger than bound, the cost will be increased by cost * (...
Definition: routing.h:2865
SimpleBoundCosts::BoundCost GetSoftSpanUpperBoundForVehicle(int vehicle) const
Definition: routing.h:2858
const std::vector< IntVar * > & transits() const
Definition: routing.h:2525
IntVar * TransitVar(int64_t index) const
Definition: routing.h:2514
friend void AppendDimensionCumulFilters(const std::vector< RoutingDimension * > &dimensions, const RoutingSearchParameters &parameters, bool filter_objective_cost, std::vector< LocalSearchFilterManager::FilterEvent > *filters)
void SetSpanCostCoefficientForAllVehicles(int64_t coefficient)
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< int64_t > & vehicle_span_upper_bounds() const
Definition: routing.h:2809
const std::string & name() const
Returns the name of the dimension.
Definition: routing.h:2758
int64_t GetSpanCostCoefficientForVehicleClass(RoutingVehicleClassIndex vehicle_class) const
Definition: routing.h:2817
const std::vector< IntVar * > & cumuls() const
Like CumulVar(), TransitVar(), SlackVar() but return the whole variable vectors instead (indexed by i...
Definition: routing.h:2523
void SetSoftSpanUpperBoundForVehicle(SimpleBoundCosts::BoundCost bound_cost, int vehicle)
If the span of vehicle on this dimension is larger than bound, the cost will be increased by cost * (...
Definition: routing.h:2847
const std::vector< int64_t > & vehicle_capacities() const
Returns the capacities for all vehicles.
Definition: routing.h:2572
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.
int64_t GetGlobalOptimizerOffset() const
Definition: routing.h:2833
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:2513
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.
IntVar * SlackVar(int64_t index) const
Definition: routing.h:2518
int64_t GetSpanCostCoefficientForVehicle(int vehicle) const
Definition: routing.h:2813
int64_t global_span_cost_coefficient() const
Definition: routing.h:2829
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...
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:2577
const std::vector< IntVar * > & slacks() const
Definition: routing.h:2526
int64_t GetSpanUpperBoundForVehicle(int vehicle) const
Definition: routing.h:2805
const std::vector< int64_t > & vehicle_span_cost_coefficients() const
Definition: routing.h:2825
bool AreVehicleTransitsPositive(int vehicle) const
Returns true iff the transit evaluator of 'vehicle' is positive for all arcs.
Definition: routing.h:2601
void AddNodePrecedence(int64_t first_node, int64_t second_node, int64_t offset)
Definition: routing.h:2800
IntVar * FixedTransitVar(int64_t index) const
Definition: routing.h:2515
bool HasBreakConstraints() const
Returns true if any break interval or break distance was defined.
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.
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:2776
void AddNodePrecedence(NodePrecedence precedence)
Definition: routing.h:2792
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:2537
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:2594
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.
bool HasQuadraticCostSoftSpanUpperBounds() const
Definition: routing.h:2875
RoutingModel * model() const
Returns the model on which the dimension was created.
Definition: routing.h:2498
const std::vector< IntervalVar * > & GetBreakIntervalsOfVehicle(int vehicle) const
Returns the break intervals set by SetBreakIntervalsOfVehicle().
const std::vector< NodePrecedence > & GetNodePrecedences() const
Definition: routing.h:2795
const std::vector< SortedDisjointIntervalList > & forbidden_intervals() const
Returns forbidden intervals for each node.
Definition: routing.h:2529
const ReverseArcListGraph< int, int > & GetPathPrecedenceGraph() const
Accessors.
Definition: routing.h:2762
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:2584
void SetPickupToDeliveryLimitFunctionForPair(PickupToDeliveryLimitFunction limit_function, int pair_index)
int vehicle_to_class(int vehicle) const
Definition: routing.h:2605
const PiecewiseLinearFunction * GetCumulVarPiecewiseLinearCost(int64_t index) const
Returns the piecewise linear cost of a cumul variable for a given variable index.
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,...
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...
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:2506
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:2556
int64_t GetLocalOptimizerOffsetForVehicle(int vehicle) const
Definition: routing.h:2837
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 std::vector< IntVar * > & fixed_transits() const
Definition: routing.h:2524
const RoutingDimension * base_dimension() const
Returns the parent in the dependency tree if any or nullptr otherwise.
Definition: routing.h:2747
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.
void SetBreakIntervalsOfVehicle(std::vector< IntervalVar * > breaks, int vehicle, int pre_travel_evaluator, int post_travel_evaluator)
Sets the breaks for a given vehicle.
int64_t GetCumulVarSoftUpperBound(int64_t index) const
Returns the soft upper bound of a cumul variable for a given variable index.
const std::vector< std::pair< int64_t, int64_t > > & GetBreakDistanceDurationOfVehicle(int vehicle) const
Returns the pairs (distance, duration) specified by break distance constraints.
void SetSpanUpperBoundForVehicle(int64_t upper_bound, int vehicle)
!defined(SWIGCSHARP) && !defined(SWIGJAVA) !defined(SWIGPYTHON)
void SetGlobalSpanCostCoefficient(int64_t coefficient)
Sets a cost proportional to the global dimension span, that is the difference between the largest val...
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.
SimpleBoundCosts::BoundCost GetQuadraticCostSoftSpanUpperBoundForVehicle(int vehicle) const
Definition: routing.h:2878
int64_t GetCumulVarSoftLowerBound(int64_t index) const
Returns the soft lower bound of a cumul variable for a given variable index.
Manager for any NodeIndex <-> variable index conversion.
Attributes(Domain start_domain, Domain end_domain)
A Resource sets attributes (costs/constraints) for a set of dimensions.
Definition: routing.h:411
const Attributes & GetDimensionAttributes(const RoutingDimension *dimension) const
A ResourceGroup defines a set of available Resources with attributes on one or multiple dimensions.
Definition: routing.h:390
const std::vector< Resource > & GetResources() const
Definition: routing.h:435
void AddResource(Attributes attributes, const RoutingDimension *dimension)
Add a Resource with the given attributes for the corresponding dimension.
ResourceGroup(const RoutingModel *model)
Definition: routing.h:429
const absl::flat_hash_set< DimensionIndex > & GetAffectedDimensionIndices() const
Definition: routing.h:436
int64_t ComputeLowerBound()
Computes a lower bound to the routing problem solving a linear assignment problem.
void AddAtSolutionCallback(std::function< void()> callback)
Adds a callback called each time a solution is found during the search.
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.
const Solver::IndexEvaluator2 & first_solution_evaluator() const
Gets/sets the evaluator used during the search.
Definition: routing.h:1053
Solver * solver() const
Returns the underlying constraint solver.
Definition: routing.h:1440
const TransitCallback2 & TransitCallback(int callback_index) const
Definition: routing.h:480
Assignment * RestoreAssignment(const Assignment &solution)
Restores an assignment as a solution in the routing model and returns the new solution.
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:1481
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:1456
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:577
VehicleClassIndex GetVehicleClassIndexOfVehicle(int64_t vehicle) const
Definition: routing.h:1371
void AddLocalSearchOperator(LocalSearchOperator *ls_operator)
Adds a local search operator to the set of operators used to solve the vehicle routing problem.
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:727
RoutingIndexPair IndexPair
Definition: routing.h:243
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...
const std::vector< int > & GetPairIndicesOfType(int type) const
RoutingTransitCallback1 TransitCallback1
Definition: routing.h:238
const absl::flat_hash_set< int > & GetTemporalTypeIncompatibilitiesOfType(int type) const
const std::vector< int > & GetDimensionResourceGroupIndices(const RoutingDimension *dimension) const
Returns the indices of resource groups for this dimension.
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:1300
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.
const IndexPairs & GetPickupAndDeliveryPairs() const
Returns pickup and delivery pairs currently in the model.
Definition: routing.h:834
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 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.
const std::vector< absl::flat_hash_set< int > > & GetRequiredTypeAlternativesWhenRemovingType(int type) const
Returns the set of requirement alternatives when removing the given type.
const std::vector< std::pair< DisjunctionIndex, DisjunctionIndex > > & GetPickupAndDeliveryDisjunctions() const
Definition: routing.h:838
RoutingModel(const RoutingIndexManager &index_manager, const RoutingModelParameters &parameters)
int GetVehicleClassesCount() const
Returns the number of different vehicle classes in the model.
Definition: routing.h:1391
int64_t GetFixedCostOfVehicle(int vehicle) const
Returns the route fixed cost taken into account if the route of the vehicle is not empty,...
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; ...
bool IsStart(int64_t index) const
Returns true if 'index' represents the first node of a route.
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.
const std::vector< std::unique_ptr< LocalDimensionCumulOptimizer > > & GetLocalDimensionCumulMPOptimizers() const
Definition: routing.h:647
Assignment * ReadAssignment(const std::string &file_name)
Reads an assignment from a file and returns the current solution.
Assignment * CompactAssignment(const Assignment &assignment) const
Returns a compacted version of the given assignment, in which all vehicles with id lower or equal to ...
static std::unique_ptr< LocalSearchOperator > MakeGreedyDescentLSOperator(std::vector< IntVar * > variables)
Perhaps move it to constraint_solver.h.
bool CheckLimit()
Returns true if the search limit has been crossed.
Definition: routing.h:1443
const IndexPairs & GetImplicitUniquePickupAndDeliveryPairs() const
Returns implicit pickup and delivery pairs currently in the model.
Definition: routing.h:845
int RegisterStateDependentTransitCallback(VariableIndexEvaluator2 callback)
const std::vector< std::pair< int, int > > & GetDeliveryIndexPairs(int64_t node_index) const
Same as above for deliveries.
void AddToAssignment(IntVar *const var)
Adds an extra variable to the vehicle routing assignment.
IntVar * VehicleVar(int64_t index) const
Returns the vehicle variable of the node corresponding to index.
Definition: routing.h:1319
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:861
@ TYPE_ADDED_TO_VEHICLE
When visited, the number of types 'T' on the vehicle increases by one.
Definition: routing.h:863
@ ADDED_TYPE_REMOVED_FROM_VEHICLE
When visited, one instance of type 'T' previously added to the route (TYPE_ADDED_TO_VEHICLE),...
Definition: routing.h:868
@ 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:871
GlobalDimensionCumulOptimizer * GetMutableGlobalCumulMPOptimizer(const RoutingDimension &dimension) const
Constraint * MakePathSpansAndTotalSlacks(const RoutingDimension *dimension, std::vector< IntVar * > spans, std::vector< IntVar * > total_slacks)
For every vehicle of the routing model:
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:1333
LocalDimensionCumulOptimizer * GetMutableLocalCumulOptimizer(const RoutingDimension &dimension) const
int RegisterUnaryTransitVector(std::vector< int64_t > values)
Registers 'callback' and returns its index.
void AddLocalSearchFilter(LocalSearchFilter *filter)
Adds a custom local search filter to the list of filters used to speed up local search by pruning unf...
Definition: routing.h:1266
const std::vector< absl::flat_hash_set< int > > & GetSameVehicleRequiredTypeAlternativesOfType(int type) const
Returns the set of same-vehicle requirement alternatives for the given type.
int64_t Size() const
Returns the number of next variables in the model.
Definition: routing.h:1460
RoutingDimension * GetMutableDimension(const std::string &dimension_name) const
Returns a dimension from its name.
int GetVisitType(int64_t index) const
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::unique_ptr< GlobalDimensionCumulOptimizer > > & GetGlobalDimensionCumulMPOptimizers() const
Definition: routing.h:639
bool HasTemporalTypeRequirements() const
Definition: routing.h:958
IntVar * NextVar(int64_t index) const
!defined(SWIGPYTHON)
Definition: routing.h:1304
static const int64_t kNoPenalty
Constant used to express a hard constraint instead of a soft penalty.
Definition: routing.h:451
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:239
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.
IntVar * ActiveVehicleVar(int vehicle) const
Returns the active variable of the vehicle.
Definition: routing.h:1309
int64_t GetDisjunctionMaxCardinality(DisjunctionIndex index) const
Returns the maximum number of possible active nodes of the node disjunction of index 'index'.
Definition: routing.h:751
SweepArranger * sweep_arranger() const
Returns the sweep arranger to be used by routing heuristics.
std::vector< std::string > GetAllDimensionNames() const
Outputs the names of all dimensions added to the routing engine.
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...
Assignment * ReadAssignmentFromRoutes(const std::vector< std::vector< int64_t > > &routes, bool ignore_inactive_indices)
Restores the routes as the current solution.
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.
Status
Status of the search.
Definition: routing.h:212
@ ROUTING_SUCCESS
Problem solved successfully after calling RoutingModel::Solve().
Definition: routing.h:216
@ ROUTING_FAIL
No solution found to the problem after calling RoutingModel::Solve().
Definition: routing.h:218
@ ROUTING_NOT_SOLVED
Problem not solved yet (before calling RoutingModel::Solve()).
Definition: routing.h:214
@ ROUTING_INVALID
Model, model parameters or flags are not valid.
Definition: routing.h:222
@ ROUTING_FAIL_TIMEOUT
Time limit reached before finding a solution with RoutingModel::Solve().
Definition: routing.h:220
bool HasVehicleWithCostClassIndex(CostClassIndex cost_class_index) const
Returns true iff the model contains a vehicle with the given cost_class_index.
Definition: routing.h:1358
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.
std::vector< RoutingDimension * > GetDimensionsWithSoftOrSpanCosts() const
Returns dimensions with soft or vehicle span costs.
void SetSweepArranger(SweepArranger *sweep_arranger)
void AddTemporalTypeIncompatibility(int type1, int type2)
const std::vector< int > & GetSingleNodesOfType(int type) const
RoutingIndexPairs IndexPairs
Definition: routing.h:244
void SetFixedCostOfVehicle(int64_t cost, int vehicle)
Sets the fixed cost of one vehicle route.
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...
const std::vector< absl::flat_hash_set< int > > & GetRequiredTypeAlternativesWhenAddingType(int type) const
Returns the set of requirement alternatives when adding the given type.
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
const TransitCallback1 & UnaryTransitCallbackOrNull(int callback_index) const
Definition: routing.h:484
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.
void ConsiderEmptyRouteCostsForVehicle(bool consider_costs, int vehicle)
Definition: routing.h:1040
bool IsVehicleAllowedForIndex(int vehicle, int64_t index)
Returns true if a vehicle is allowed to visit a given node.
Definition: routing.h:782
const VehicleTypeContainer & GetVehicleTypeContainer() const
Definition: routing.h:1398
int RegisterPositiveUnaryTransitCallback(TransitCallback1 callback)
void SetTabuVarsCallback(GetTabuVarsCallback tabu_var_callback)
IntVar * ApplyLocks(const std::vector< int64_t > &locks)
Applies a lock chain to the next search.
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.
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:989
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.
const std::vector< std::vector< int > > & GetTopologicallySortedVisitTypes() const
Definition: routing.h:891
const std::vector< RoutingDimension * > & GetDimensions() const
Returns all dimensions of the model.
Definition: routing.h:626
void IgnoreDisjunctionsAlreadyForcedToZero()
SPECIAL: Makes the solver ignore all the disjunctions whose active variables are all trivially zero (...
void SetPickupAndDeliveryPolicyOfVehicle(PickupAndDeliveryPolicy policy, int vehicle)
const Assignment * SolveWithParameters(const RoutingSearchParameters &search_parameters, std::vector< const Assignment * > *solutions=nullptr)
Solves the current routing model with the given parameters.
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.
const VariableIndexEvaluator2 & StateDependentTransitCallback(int callback_index) const
Definition: routing.h:488
const Assignment * PackCumulsOfOptimizerDimensionsFromAssignment(const Assignment *original_assignment, absl::Duration duration_limit)
For every dimension in the model with an optimizer in local/global_dimension_optimizers_,...
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:1297
const std::vector< DisjunctionIndex > & GetDisjunctionIndices(int64_t index) const
Returns the indices of the disjunctions to which an index belongs.
Definition: routing.h:719
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...
const std::vector< int64_t > & GetAmortizedLinearCostFactorOfVehicles() const
Definition: routing.h:1032
int GetMaximumNumberOfActiveVehicles() const
Returns the maximum number of active vehicles.
Definition: routing.h:993
RoutingDimensionIndex DimensionIndex
Definition: routing.h:235
Assignment * MutablePreAssignment()
Definition: routing.h:1165
const std::vector< std::unique_ptr< LocalDimensionCumulOptimizer > > & GetLocalDimensionCumulOptimizers() const
Definition: routing.h:643
Assignment * CompactAndCheckAssignment(const Assignment &assignment) const
Same as CompactAssignment() but also checks the validity of the final compact solution; if it is not ...
LocalDimensionCumulOptimizer * GetMutableLocalCumulMPOptimizer(const RoutingDimension &dimension) const
std::pair< int, bool > AddConstantDimension(int64_t value, int64_t capacity, bool fix_start_cumul_to_zero, const std::string &name)
Definition: routing.h:540
bool HasHardTypeIncompatibilities() const
Returns true iff any hard (resp.
Definition: routing.h:910
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,...
std::vector< std::vector< int64_t > > GetRoutesFromAssignment(const Assignment &assignment)
Converts the solution in the given assignment to routes for all vehicles.
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:226
@ PICKUP_AND_DELIVERY_LIFO
Deliveries must be performed in reverse order of pickups.
Definition: routing.h:230
@ PICKUP_AND_DELIVERY_NO_ORDER
Any precedence is accepted.
Definition: routing.h:228
@ PICKUP_AND_DELIVERY_FIFO
Deliveries must be performed in the same order as pickups.
Definition: routing.h:232
int64_t Start(int vehicle) const
Model inspection.
Definition: routing.h:1277
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:1458
int GetNumberOfDisjunctions() const
Returns the number of node disjunctions in the model.
Definition: routing.h:755
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...
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.
IntVar * ActiveVar(int64_t index) const
Returns the active variable of the node corresponding to index.
Definition: routing.h:1306
int64_t GetNumberOfDecisionsInFirstSolution(const RoutingSearchParameters &search_parameters) const
Returns statistics on first solution search, number of decisions sent to filters, number of decisions...
bool HasTypeRegulations() const
Returns true iff the model has any incompatibilities or requirements set on node types.
Definition: routing.h:964
void SetFirstSolutionEvaluator(Solver::IndexEvaluator2 evaluator)
Takes ownership of evaluator.
Definition: routing.h:1058
RoutingVehicleClassIndex VehicleClassIndex
Definition: routing.h:237
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...
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...
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 "...
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.
std::function< StateDependentTransit(int64_t, int64_t)> VariableIndexEvaluator2
Definition: routing.h:265
int GetNonZeroCostClassesCount() const
Ditto, minus the 'always zero', built-in cost class.
Definition: routing.h:1368
GlobalDimensionCumulOptimizer * GetMutableGlobalCumulOptimizer(const RoutingDimension &dimension) const
Returns the global/local dimension cumul optimizer for a given dimension, or nullptr if there is none...
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)
IntVar * CostVar() const
Returns the global cost variable which is being minimized.
Definition: routing.h:1321
bool HasSameVehicleTypeRequirements() const
Returns true iff any same-route (resp.
Definition: routing.h:955
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:676
ResourceGroup *const AddResourceGroup()
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,...
const absl::flat_hash_set< int > & GetHardTypeIncompatibilitiesOfType(int type) const
Returns visit types incompatible with a given type.
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...
bool IsMatchingModel() const
Returns true if a vehicle/node matching problem is detected.
DecisionBuilder * MakeSelfDependentDimensionFinalizer(const RoutingDimension *dimension)
SWIG
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:1283
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:234
bool HasTemporalTypeIncompatibilities() const
Definition: routing.h:913
int GetCostClassesCount() const
Returns the number of different cost classes in the model.
Definition: routing.h:1366
const std::vector< int64_t > & GetAmortizedQuadraticCostFactorOfVehicles() const
Definition: routing.h:1035
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:1470
absl::Duration RemainingTime() const
Returns the time left in the search limit.
Definition: routing.h:1449
Status status() const
Returns the current status of the routing model.
Definition: routing.h:1140
const std::vector< int > & GetSameVehicleIndicesOfIndex(int node) const
Returns variable indices of nodes constrained to be on the same route.
Definition: routing.h:1393
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:459
bool CostsAreHomogeneousAcrossVehicles() const
Whether costs are homogeneous across all vehicles.
Definition: routing.h:1328
PickupAndDeliveryPolicy GetPickupAndDeliveryPolicyOfVehicle(int vehicle) const
const std::vector< std::unique_ptr< ResourceGroup > > & GetResourceGroups() const
Definition: routing.h:688
CostClassIndex GetCostClassIndexOfVehicle(int64_t vehicle) const
Get the cost class index of the given vehicle.
Definition: routing.h:1349
const Assignment * Solve(const Assignment *assignment=nullptr)
Solves the current routing model; closes the current model.
IntVar * VehicleCostsConsideredVar(int vehicle) const
Returns the variable specifying whether or not costs are considered for vehicle.
Definition: routing.h:1314
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.
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:1286
const std::vector< std::unique_ptr< GlobalDimensionCumulOptimizer > > & GetGlobalDimensionCumulOptimizers() const
Returns [global|local]_dimension_optimizers_, which are empty if the model has not been closed.
Definition: routing.h:635
bool AreEmptyRouteCostsConsideredForVehicle(int vehicle) const
Definition: routing.h:1045
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:1377
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:455
const std::string & GetPrimaryConstrainedDimension() const
Get the primary constrained dimension, or an empty string if it is unset.
Definition: routing.h:681
RoutingModel(const RoutingIndexManager &index_manager)
Constructor taking an index manager.
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:236
int64_t End(int vehicle) const
Returns the variable index of the ending node of a vehicle route.
Definition: routing.h:1279
bool AddDimension(int evaluator_index, int64_t slack_max, int64_t capacity, bool fix_start_cumul_to_zero, const std::string &name)
Model creation.
const Assignment *const PreAssignment() const
Returns an assignment used to fix some of the variables of the problem.
Definition: routing.h:1164
const RoutingDimension & GetDimensionOrDie(const std::string &dimension_name) const
Returns a dimension from its name. Dies if the dimension does not exist.
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:740
A search monitor is a simple set of callbacks to monitor all search events.
A structure meant to store soft bounds and associated violation constants.
Definition: routing.h:2455
SimpleBoundCosts(int num_bounds, BoundCost default_bound_cost)
Definition: routing.h:2461
BoundCost & bound_cost(int element)
Definition: routing.h:2463
BoundCost bound_cost(int element) const
Definition: routing.h:2464
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:2346
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:2426
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:2362
TypeRequirementChecker(const RoutingModel &model)
Definition: routing.h:2364
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)
IntVarLocalSearchFilter * MakeVehicleBreaksFilter(const RoutingModel &routing_model, const RoutingDimension &dimension)
int64_t Zero()
NOLINT.
std::pair< std::vector< int64_t >, std::vector< int64_t > > RoutingIndexPair
Definition: routing_types.h:45
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)
void AppendTasksFromIntervals(const std::vector< IntervalVar * > &intervals, DisjunctivePropagator::Tasks *tasks)
std::vector< RoutingIndexPair > RoutingIndexPairs
Definition: routing_types.h:46
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...
A structure to hold tasks described by their features.
Definition: routing.h:2087
std::vector< std::pair< int64_t, int64_t > > distance_duration
Definition: routing.h:2097
std::vector< const SortedDisjointIntervalList * > forbidden_intervals
Definition: routing.h:2096
SUBTLE: The vehicle's fixed cost is skipped on purpose here, because we can afford to do so:
Definition: routing.h:293
bool operator<(const DimensionCost &cost) const
Definition: routing.h:297
int evaluator_index
Index of the arc cost evaluator, registered in the RoutingModel class.
Definition: routing.h:271
static bool LessThan(const CostClass &a, const CostClass &b)
Comparator for STL containers and algorithms.
Definition: routing.h:311
std::vector< DimensionCost > dimension_transit_evaluator_class_and_cost_coefficient
Definition: routing.h:305
What follows is relevant for models with time/state dependent transits.
Definition: routing.h:260
RangeMinMaxIndexFunction * transit_plus_identity
f(x)
Definition: routing.h:262
int64_t fixed_cost
Contrarily to CostClass, here we need strict equivalence.
Definition: routing.h:324
absl::StrongVector< DimensionIndex, int64_t > dimension_end_cumuls_max
Definition: routing.h:338
uint64_t unvisitable_nodes_fprint
Fingerprint of unvisitable non-start/end nodes.
Definition: routing.h:344
int start_equivalence_class
Vehicle start and end equivalence classes.
Definition: routing.h:331
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:339
absl::StrongVector< DimensionIndex, int64_t > dimension_end_cumuls_min
Definition: routing.h:337
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:342
absl::StrongVector< DimensionIndex, int64_t > dimension_start_cumuls_min
Bounds of cumul variables at start and end vehicle nodes.
Definition: routing.h:335
absl::StrongVector< DimensionIndex, int64_t > dimension_start_cumuls_max
Definition: routing.h:336
CostClassIndex cost_class_index
The cost class of the vehicle.
Definition: routing.h:322
Definition: routing.h:355
int64_t fixed_cost
Definition: routing.h:357
bool operator<(const VehicleClassEntry &other) const
Definition: routing.h:359
int vehicle_class
Definition: routing.h:356
Struct used to sort and store vehicles by their type.
Definition: routing.h:354
std::vector< std::set< VehicleClassEntry > > sorted_vehicle_classes_per_type
Definition: routing.h:374
std::vector< std::deque< int > > vehicles_per_vehicle_class
Definition: routing.h:375
std::vector< int64_t > post_travels
Definition: routing.h:2161
std::vector< int64_t > max_travels
Definition: routing.h:2159
std::vector< int64_t > pre_travels
Definition: routing.h:2160
std::vector< int64_t > min_travels
Definition: routing.h:2158