156#ifndef OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_H_
157#define OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_H_
173#include "absl/container/flat_hash_map.h"
174#include "absl/container/flat_hash_set.h"
175#include "absl/container/inlined_vector.h"
176#include "absl/hash/hash.h"
177#include "absl/log/check.h"
178#include "absl/strings/string_view.h"
179#include "absl/time/time.h"
180#include "absl/types/span.h"
187#include "ortools/constraint_solver/routing_enums.pb.h"
189#include "ortools/constraint_solver/routing_parameters.pb.h"
202class FinalizerVariables;
203class GlobalDimensionCumulOptimizer;
204class LocalDimensionCumulOptimizer;
205class LocalSearchPhaseParameters;
207class IndexNeighborFinder;
208class IntVarFilteredDecisionBuilder;
210class RoutingDimension;
218 explicit PathsMetadata(
const RoutingIndexManager& manager) {
219 const int num_indices = manager.num_indices();
220 const int num_paths = manager.num_vehicles();
221 path_of_node_.resize(num_indices, -1);
222 is_start_.resize(num_indices,
false);
223 is_end_.resize(num_indices,
false);
224 start_of_path_.resize(num_paths);
225 end_of_path_.resize(num_paths);
226 for (
int v = 0; v < num_paths; ++v) {
227 const int64_t
start = manager.GetStartIndex(v);
228 start_of_path_[v] =
start;
229 path_of_node_[
start] = v;
230 is_start_[
start] =
true;
231 const int64_t
end = manager.GetEndIndex(v);
232 end_of_path_[v] =
end;
233 path_of_node_[
end] = v;
238 bool IsStart(int64_t node)
const {
return is_start_[node]; }
239 bool IsEnd(int64_t node)
const {
return is_end_[node]; }
240 int GetPath(int64_t start_or_end_node)
const {
241 return path_of_node_[start_or_end_node];
243 int NumPaths()
const {
return start_of_path_.
size(); }
244 const std::vector<int64_t>& Paths()
const {
return path_of_node_; }
245 const std::vector<int64_t>& Starts()
const {
return start_of_path_; }
246 const std::vector<int64_t>& Ends()
const {
return end_of_path_; }
249 std::vector<bool> is_start_;
250 std::vector<bool> is_end_;
251 std::vector<int64_t> start_of_path_;
252 std::vector<int64_t> end_of_path_;
253 std::vector<int64_t> path_of_node_;
267 ROUTING_PARTIAL_SUCCESS_LOCAL_OPTIMUM_NOT_REACHED,
271 ROUTING_FAIL_TIMEOUT,
281 enum PickupAndDeliveryPolicy {
283 PICKUP_AND_DELIVERY_NO_ORDER,
285 PICKUP_AND_DELIVERY_LIFO,
287 PICKUP_AND_DELIVERY_FIFO
289 typedef RoutingCostClassIndex CostClassIndex;
290 typedef RoutingDimensionIndex DimensionIndex;
291 typedef RoutingDisjunctionIndex DisjunctionIndex;
292 typedef RoutingVehicleClassIndex VehicleClassIndex;
293 typedef RoutingResourceClassIndex ResourceClassIndex;
310 struct StateDependentTransit {
311 RangeIntToIntFunction* transit;
312 RangeMinMaxIndexFunction* transit_plus_identity;
314 typedef std::function<StateDependentTransit(int64_t, int64_t)>
315 VariableIndexEvaluator2;
321 int evaluator_index = 0;
343 struct DimensionCost {
344 int64_t transit_evaluator_class;
347 int64_t span_cost_coefficient;
348 int64_t slack_cost_coefficient;
349 const RoutingDimension* dimension;
350 bool operator<(
const DimensionCost& cost)
const {
351 return std::tie(transit_evaluator_class, span_cost_coefficient,
352 slack_cost_coefficient) <
353 std::tie(cost.transit_evaluator_class,
354 cost.span_cost_coefficient,
355 cost.slack_cost_coefficient);
358 friend bool operator==(
const DimensionCost& c1,
const DimensionCost& c2) {
359 return c1.transit_evaluator_class == c2.transit_evaluator_class &&
360 c1.span_cost_coefficient == c2.span_cost_coefficient &&
361 c1.slack_cost_coefficient == c2.slack_cost_coefficient;
363 template <
typename H>
365 return H::combine(std::move(h), cost.transit_evaluator_class,
366 cost.span_cost_coefficient,
367 cost.slack_cost_coefficient);
370 std::vector<DimensionCost>
371 dimension_transit_evaluator_class_and_cost_coefficient;
373 explicit CostClass(
int evaluator_index)
374 : evaluator_index(evaluator_index) {}
376 friend bool operator==(
const CostClass& c1,
const CostClass& c2) {
377 return c1.evaluator_index == c2.evaluator_index &&
378 c1.dimension_transit_evaluator_class_and_cost_coefficient ==
379 c2.dimension_transit_evaluator_class_and_cost_coefficient;
381 template <
typename H>
384 std::move(h),
c.evaluator_index,
385 c.dimension_transit_evaluator_class_and_cost_coefficient);
393 struct VehicleTypeContainer {
394 struct VehicleClassEntry {
398 bool operator<(
const VehicleClassEntry& other)
const {
400 std::tie(other.fixed_cost, other.vehicle_class);
404 int NumTypes()
const {
return sorted_vehicle_classes_per_type.size(); }
406 int Type(
int vehicle)
const {
407 DCHECK_LT(vehicle, type_index_of_vehicle.size());
408 return type_index_of_vehicle[vehicle];
411 std::vector<int> type_index_of_vehicle;
413 std::vector<std::set<VehicleClassEntry> > sorted_vehicle_classes_per_type;
414 std::vector<std::deque<int> > vehicles_per_vehicle_class;
429 class ResourceGroup {
435 Attributes(Domain start_domain, Domain end_domain);
437 const Domain& start_domain()
const {
return start_domain_; }
438 const Domain& end_domain()
const {
return end_domain_; }
440 friend bool operator==(
const Attributes&
a,
const Attributes&
b) {
441 return a.start_domain_ ==
b.start_domain_ &&
442 a.end_domain_ ==
b.end_domain_;
444 template <
typename H>
446 return H::combine(std::move(h), attributes.start_domain_,
447 attributes.end_domain_);
454 Domain start_domain_;
462 const ResourceGroup::Attributes& GetDimensionAttributes(
463 const RoutingDimension* dimension)
const;
466 explicit Resource(
const RoutingModel*
model) : model_(
model) {}
468 void SetDimensionAttributes(ResourceGroup::Attributes attributes,
469 const RoutingDimension* dimension);
470 const ResourceGroup::Attributes& GetDefaultAttributes()
const;
472 const RoutingModel*
const model_;
473 absl::flat_hash_map<DimensionIndex, ResourceGroup::Attributes>
474 dimension_attributes_;
476 friend class ResourceGroup;
481 int AddResource(Attributes attributes,
const RoutingDimension* dimension);
486 void NotifyVehicleRequiresAResource(
int vehicle);
488 const std::vector<int>& GetVehiclesRequiringAResource()
const {
489 return vehicles_requiring_resource_;
492 bool VehicleRequiresAResource(
int vehicle)
const {
493 return vehicle_requires_resource_[vehicle];
496 void SetAllowedResourcesForVehicle(
497 int vehicle,
const std::vector<int>& allowed_resource_indices) {
498 DCHECK(!model_->closed_);
502 DCHECK(!allowed_resource_indices.empty());
503 DCHECK(vehicle_requires_resource_[vehicle]);
504 DCHECK_LT(vehicle, vehicle_allowed_resources_.size());
505 vehicle_allowed_resources_[vehicle].clear();
506 vehicle_allowed_resources_[vehicle].insert(
507 allowed_resource_indices.begin(), allowed_resource_indices.end());
509 void ClearAllowedResourcesForVehicle(
int vehicle) {
510 DCHECK_LT(vehicle, vehicle_allowed_resources_.size());
511 vehicle_allowed_resources_[vehicle].clear();
513 const absl::flat_hash_set<int>& GetResourcesMarkedAllowedForVehicle(
515 DCHECK_LT(vehicle, vehicle_allowed_resources_.size());
516 return vehicle_allowed_resources_[vehicle];
518 bool IsResourceAllowedForVehicle(
int resource,
int vehicle)
const {
519 DCHECK_LT(vehicle, vehicle_allowed_resources_.size());
520 return vehicle_allowed_resources_[vehicle].empty() ||
521 vehicle_allowed_resources_[vehicle].contains(resource);
524 const std::vector<Resource>& GetResources()
const {
return resources_; }
525 const Resource& GetResource(
int resource_index)
const {
526 DCHECK_LT(resource_index, resources_.size());
527 return resources_[resource_index];
529 const absl::flat_hash_set<DimensionIndex>& GetAffectedDimensionIndices()
531 return affected_dimension_indices_;
534 int GetResourceClassesCount()
const {
535 return resource_indices_per_class_.size();
537 const std::vector<int>& GetResourceIndicesInClass(
538 ResourceClassIndex resource_class)
const {
539 DCHECK_LT(resource_class, resource_indices_per_class_.size());
540 return resource_indices_per_class_[resource_class];
544 GetResourceIndicesPerClass()
const {
545 return resource_indices_per_class_;
548 ResourceClassIndex GetResourceClassIndex(
int resource_index)
const {
549 DCHECK_LT(resource_index, resource_class_indices_.size());
550 return resource_class_indices_[resource_index];
553 int Size()
const {
return resources_.size(); }
554 int Index()
const {
return index_; }
557 explicit ResourceGroup(
const RoutingModel*
model)
558 : index_(
model->GetResourceGroups().
size()),
560 vehicle_requires_resource_(
model->vehicles(),
false),
561 vehicle_allowed_resources_(
model->vehicles()) {}
563 void ComputeResourceClasses();
566 const RoutingModel*
const model_;
567 std::vector<Resource> resources_;
570 std::vector<ResourceClassIndex> resource_class_indices_;
573 resource_indices_per_class_;
576 std::vector<bool> vehicle_requires_resource_;
577 std::vector<int> vehicles_requiring_resource_;
582 std::vector<absl::flat_hash_set<int> > vehicle_allowed_resources_;
585 absl::flat_hash_set<DimensionIndex> affected_dimension_indices_;
587 friend class RoutingModel;
591 struct VariableValuePair {
597 class SecondaryOptimizer {
599 SecondaryOptimizer(RoutingModel*
model,
600 RoutingSearchParameters* search_parameters,
601 int64_t solve_period);
602 bool Solve(
const std::vector<RoutingModel::VariableValuePair>& in_state,
603 std::vector<RoutingModel::VariableValuePair>* out_state);
606 RoutingModel*
const model_;
607 const RoutingSearchParameters*
const search_parameters_;
608 const int64_t solve_period_ = 0;
609 int64_t call_count_ = 0;
610 Assignment* state_ =
nullptr;
611 absl::flat_hash_map<IntVar*, int> var_to_index_;
615 static const int64_t kNoPenalty;
619 static const DisjunctionIndex kNoDisjunction;
623 static const DimensionIndex kNoDimension;
628 explicit RoutingModel(
const RoutingIndexManager& index_manager);
629 RoutingModel(
const RoutingIndexManager& index_manager,
633 RoutingModel(
const RoutingModel&) =
delete;
634 RoutingModel& operator=(
const RoutingModel&) =
delete;
639 enum TransitEvaluatorSign {
640 kTransitEvaluatorSignUnknown = 0,
641 kTransitEvaluatorSignPositiveOrZero = 1,
642 kTransitEvaluatorSignNegativeOrZero = 2,
649 int RegisterUnaryTransitVector(std::vector<int64_t> values);
650 int RegisterUnaryTransitCallback(
652 TransitEvaluatorSign sign = kTransitEvaluatorSignUnknown);
654 int RegisterTransitMatrix(
655 std::vector<std::vector<int64_t> > values);
656 int RegisterTransitCallback(
658 TransitEvaluatorSign sign = kTransitEvaluatorSignUnknown);
660 int RegisterStateDependentTransitCallback(VariableIndexEvaluator2
callback);
661 const TransitCallback2& TransitCallback(
int callback_index)
const {
662 CHECK_LT(callback_index, transit_evaluators_.size());
663 return transit_evaluators_[callback_index];
665 const TransitCallback1& UnaryTransitCallbackOrNull(
int callback_index)
const {
666 CHECK_LT(callback_index, unary_transit_evaluators_.size());
667 return unary_transit_evaluators_[callback_index];
669 const VariableIndexEvaluator2& StateDependentTransitCallback(
670 int callback_index)
const {
671 CHECK_LT(callback_index, state_dependent_transit_evaluators_.size());
672 return state_dependent_transit_evaluators_[callback_index];
697 bool AddDimension(
int evaluator_index, int64_t slack_max, int64_t capacity,
698 bool fix_start_cumul_to_zero,
const std::string&
name);
699 bool AddDimensionWithVehicleTransits(
700 const std::vector<int>& evaluator_indices, int64_t slack_max,
701 int64_t capacity,
bool fix_start_cumul_to_zero,
const std::string&
name);
702 bool AddDimensionWithVehicleCapacity(
int evaluator_index, int64_t slack_max,
703 std::vector<int64_t> vehicle_capacities,
704 bool fix_start_cumul_to_zero,
705 const std::string&
name);
706 bool AddDimensionWithVehicleTransitAndCapacity(
707 const std::vector<int>& evaluator_indices, int64_t slack_max,
708 std::vector<int64_t> vehicle_capacities,
bool fix_start_cumul_to_zero,
709 const std::string&
name);
718 std::pair<int, bool> AddConstantDimensionWithSlack(
719 int64_t
value, int64_t capacity, int64_t slack_max,
720 bool fix_start_cumul_to_zero,
const std::string&
name);
721 std::pair<int, bool> AddConstantDimension(int64_t
value, int64_t capacity,
722 bool fix_start_cumul_to_zero,
723 const std::string&
name) {
724 return AddConstantDimensionWithSlack(
value, capacity, 0,
725 fix_start_cumul_to_zero,
name);
736 std::pair<int, bool> AddVectorDimension(std::vector<int64_t> values,
738 bool fix_start_cumul_to_zero,
739 const std::string&
name);
749 std::pair<int, bool> AddMatrixDimension(
750 std::vector<std::vector<int64_t> > values,
751 int64_t capacity,
bool fix_start_cumul_to_zero,
const std::string&
name);
758 bool AddDimensionDependentDimensionWithVehicleCapacity(
759 const std::vector<int>& pure_transits,
760 const std::vector<int>& dependent_transits,
761 const RoutingDimension* base_dimension, int64_t slack_max,
762 std::vector<int64_t> vehicle_capacities,
bool fix_start_cumul_to_zero,
763 const std::string&
name) {
764 return AddDimensionDependentDimensionWithVehicleCapacityInternal(
765 pure_transits, dependent_transits, base_dimension, slack_max,
766 std::move(vehicle_capacities), fix_start_cumul_to_zero,
name);
770 bool AddDimensionDependentDimensionWithVehicleCapacity(
771 const std::vector<int>& transits,
const RoutingDimension* base_dimension,
772 int64_t slack_max, std::vector<int64_t> vehicle_capacities,
773 bool fix_start_cumul_to_zero,
const std::string&
name);
775 bool AddDimensionDependentDimensionWithVehicleCapacity(
776 int transit,
const RoutingDimension* base_dimension, int64_t slack_max,
777 int64_t vehicle_capacity,
bool fix_start_cumul_to_zero,
778 const std::string&
name);
779 bool AddDimensionDependentDimensionWithVehicleCapacity(
780 int pure_transit,
int dependent_transit,
781 const RoutingDimension* base_dimension, int64_t slack_max,
782 int64_t vehicle_capacity,
bool fix_start_cumul_to_zero,
783 const std::string&
name);
786 static RoutingModel::StateDependentTransit MakeStateDependentTransit(
787 const std::function<int64_t(int64_t)>& f, int64_t domain_start,
792 std::vector<std::string> GetAllDimensionNames()
const;
794 const std::vector<RoutingDimension*>& GetDimensions()
const {
795 return dimensions_.get();
798 std::vector<RoutingDimension*> GetDimensionsWithSoftOrSpanCosts()
const;
800 std::vector<RoutingDimension*> GetUnaryDimensions()
const;
803 std::vector<const RoutingDimension*> GetDimensionsWithGlobalCumulOptimizers()
805 std::vector<const RoutingDimension*> GetDimensionsWithLocalCumulOptimizers()
809 bool HasGlobalCumulOptimizer(
const RoutingDimension& dimension)
const {
810 return GetGlobalCumulOptimizerIndex(dimension) >= 0;
812 bool HasLocalCumulOptimizer(
const RoutingDimension& dimension)
const {
813 return GetLocalCumulOptimizerIndex(dimension) >= 0;
817 GlobalDimensionCumulOptimizer* GetMutableGlobalCumulLPOptimizer(
818 const RoutingDimension& dimension)
const;
819 GlobalDimensionCumulOptimizer* GetMutableGlobalCumulMPOptimizer(
820 const RoutingDimension& dimension)
const;
821 LocalDimensionCumulOptimizer* GetMutableLocalCumulLPOptimizer(
822 const RoutingDimension& dimension)
const;
823 LocalDimensionCumulOptimizer* GetMutableLocalCumulMPOptimizer(
824 const RoutingDimension& dimension)
const;
827 bool HasDimension(absl::string_view dimension_name)
const;
829 const RoutingDimension& GetDimensionOrDie(
830 const std::string& dimension_name)
const;
833 RoutingDimension* GetMutableDimension(
834 const std::string& dimension_name)
const;
839 void SetPrimaryConstrainedDimension(
const std::string& dimension_name) {
840 DCHECK(dimension_name.empty() || HasDimension(dimension_name));
841 primary_constrained_dimension_ = dimension_name;
844 const std::string& GetPrimaryConstrainedDimension()
const {
845 return primary_constrained_dimension_;
849 ResourceGroup* AddResourceGroup();
851 const std::vector<std::unique_ptr<ResourceGroup> >& GetResourceGroups()
853 return resource_groups_;
856 ResourceGroup* GetResourceGroup(
int rg_index)
const {
857 DCHECK_LT(rg_index, resource_groups_.size());
858 return resource_groups_[rg_index].get();
863 const std::vector<int>& GetDimensionResourceGroupIndices(
864 const RoutingDimension* dimension)
const;
868 int GetDimensionResourceGroupIndex(
const RoutingDimension* dimension)
const {
869 DCHECK_EQ(GetDimensionResourceGroupIndices(dimension).
size(), 1);
870 return GetDimensionResourceGroupIndices(dimension)[0];
889 DisjunctionIndex AddDisjunction(
const std::vector<int64_t>& indices,
890 int64_t penalty = kNoPenalty,
891 int64_t max_cardinality = 1);
893 const std::vector<DisjunctionIndex>& GetDisjunctionIndices(
894 int64_t
index)
const {
895 return index_to_disjunctions_[
index];
900 template <
typename F>
901 void ForEachNodeInDisjunctionWithMaxCardinalityFromIndex(
902 int64_t
index, int64_t max_cardinality, F f)
const {
903 for (
const DisjunctionIndex disjunction : GetDisjunctionIndices(
index)) {
904 if (disjunctions_[disjunction].
value.max_cardinality == max_cardinality) {
905 for (
const int64_t d_index : disjunctions_[disjunction].indices) {
911#if !defined(SWIGPYTHON)
914 const std::vector<int64_t>& GetDisjunctionNodeIndices(
915 DisjunctionIndex
index)
const {
916 return disjunctions_[
index].indices;
920 int64_t GetDisjunctionPenalty(DisjunctionIndex index) const {
921 return disjunctions_[
index].value.penalty;
925 int64_t GetDisjunctionMaxCardinality(DisjunctionIndex
index)
const {
926 return disjunctions_[
index].value.max_cardinality;
929 int GetNumberOfDisjunctions()
const {
return disjunctions_.size(); }
932 bool HasMandatoryDisjunctions()
const;
935 bool HasMaxCardinalityConstrainedDisjunctions()
const;
940 std::vector<std::pair<int64_t, int64_t>> GetPerfectBinaryDisjunctions()
const;
946 void IgnoreDisjunctionsAlreadyForcedToZero();
951 void AddSoftSameVehicleConstraint(
const std::vector<int64_t>& indices,
958 void SetAllowedVehiclesForIndex(
const std::vector<int>& vehicles,
962 bool IsVehicleAllowedForIndex(
int vehicle, int64_t
index)
const {
963 return allowed_vehicles_[
index].empty() ||
964 allowed_vehicles_[
index].find(vehicle) !=
965 allowed_vehicles_[
index].end();
983 void AddPickupAndDelivery(int64_t pickup, int64_t delivery);
987 void AddPickupAndDeliverySets(DisjunctionIndex pickup_disjunction,
988 DisjunctionIndex delivery_disjunction);
991 struct PickupDeliveryPosition {
996 int alternative_index;
999 const std::vector<PickupDeliveryPosition>& GetPickupPositions(
1000 int64_t node_index)
const;
1002 const std::vector<PickupDeliveryPosition>& GetDeliveryPositions(
1003 int64_t node_index)
const;
1005 bool IsPickup(int64_t node_index)
const {
1006 return !GetPickupPositions(node_index).empty();
1008 bool IsDelivery(int64_t node_index)
const {
1009 return !GetDeliveryPositions(node_index).empty();
1014 void SetPickupAndDeliveryPolicyOfAllVehicles(PickupAndDeliveryPolicy policy);
1015 void SetPickupAndDeliveryPolicyOfVehicle(PickupAndDeliveryPolicy policy,
1017 PickupAndDeliveryPolicy GetPickupAndDeliveryPolicyOfVehicle(
1022 int GetNumOfSingletonNodes()
const;
1026 const std::vector<PickupDeliveryPair>& GetPickupAndDeliveryPairs()
const {
1027 return pickup_delivery_pairs_;
1029 const std::vector<std::pair<DisjunctionIndex, DisjunctionIndex>>&
1030 GetPickupAndDeliveryDisjunctions()
const {
1031 return pickup_delivery_disjunctions_;
1037 const std::vector<PickupDeliveryPair>&
1038 GetImplicitUniquePickupAndDeliveryPairs()
const {
1040 return implicit_pickup_delivery_pairs_without_alternatives_;
1054 enum VisitTypePolicy {
1056 TYPE_ADDED_TO_VEHICLE,
1061 ADDED_TYPE_REMOVED_FROM_VEHICLE,
1064 TYPE_ON_VEHICLE_UP_TO_VISIT,
1069 TYPE_SIMULTANEOUSLY_ADDED_AND_REMOVED
1072 void SetVisitType(int64_t
index,
int type, VisitTypePolicy type_policy);
1073 int GetVisitType(int64_t
index)
const;
1074 const std::vector<int>& GetSingleNodesOfType(
int type)
const;
1075 const std::vector<int>& GetPairIndicesOfType(
int type)
const;
1076 VisitTypePolicy GetVisitTypePolicy(int64_t
index)
const;
1081 void CloseVisitTypes();
1082 int GetNumberOfVisitTypes()
const {
return num_visit_types_; }
1084 const std::vector<std::vector<int>>& GetTopologicallySortedVisitTypes()
1087 return topologically_sorted_visit_types_;
1094 void AddHardTypeIncompatibility(int type1, int type2);
1095 void AddTemporalTypeIncompatibility(
int type1,
int type2);
1097 const absl::flat_hash_set<int>& GetHardTypeIncompatibilitiesOfType(
1099 const absl::flat_hash_set<int>& GetTemporalTypeIncompatibilitiesOfType(
1103 bool HasHardTypeIncompatibilities()
const {
1104 return has_hard_type_incompatibilities_;
1106 bool HasTemporalTypeIncompatibilities()
const {
1107 return has_temporal_type_incompatibilities_;
1119 void AddSameVehicleRequiredTypeAlternatives(
1120 int dependent_type, absl::flat_hash_set<int> required_type_alternatives);
1125 void AddRequiredTypeAlternativesWhenAddingType(
1126 int dependent_type, absl::flat_hash_set<int> required_type_alternatives);
1132 void AddRequiredTypeAlternativesWhenRemovingType(
1133 int dependent_type, absl::flat_hash_set<int> required_type_alternatives);
1137 const std::vector<absl::flat_hash_set<int> >&
1138 GetSameVehicleRequiredTypeAlternativesOfType(
int type)
const;
1140 const std::vector<absl::flat_hash_set<int> >&
1141 GetRequiredTypeAlternativesWhenAddingType(
int type)
const;
1143 const std::vector<absl::flat_hash_set<int> >&
1144 GetRequiredTypeAlternativesWhenRemovingType(
int type)
const;
1148 bool HasSameVehicleTypeRequirements()
const {
1149 return has_same_vehicle_type_requirements_;
1151 bool HasTemporalTypeRequirements()
const {
1152 return has_temporal_type_requirements_;
1157 bool HasTypeRegulations()
const {
1158 return HasTemporalTypeIncompatibilities() ||
1159 HasHardTypeIncompatibilities() || HasSameVehicleTypeRequirements() ||
1160 HasTemporalTypeRequirements();
1167 int64_t UnperformedPenalty(int64_t
var_index)
const;
1171 int64_t UnperformedPenaltyOrValue(int64_t default_value,
1176 int64_t GetDepot()
const;
1182 void SetMaximumNumberOfActiveVehicles(
int max_active_vehicles) {
1183 max_active_vehicles_ = max_active_vehicles;
1186 int GetMaximumNumberOfActiveVehicles()
const {
return max_active_vehicles_; }
1190 void SetArcCostEvaluatorOfAllVehicles(
int evaluator_index);
1192 void SetArcCostEvaluatorOfVehicle(
int evaluator_index,
int vehicle);
1195 void SetFixedCostOfAllVehicles(int64_t cost);
1197 void SetFixedCostOfVehicle(int64_t cost,
int vehicle);
1201 int64_t GetFixedCostOfVehicle(
int vehicle)
const;
1208 void SetPathEnergyCostOfVehicle(
const std::string& force,
1210 int64_t unit_cost,
int vehicle);
1227 void SetAmortizedCostFactorsOfAllVehicles(int64_t linear_cost_factor,
1228 int64_t quadratic_cost_factor);
1230 void SetAmortizedCostFactorsOfVehicle(int64_t linear_cost_factor,
1231 int64_t quadratic_cost_factor,
1234 const std::vector<int64_t>& GetAmortizedLinearCostFactorOfVehicles()
const {
1235 return linear_cost_factor_of_vehicle_;
1237 const std::vector<int64_t>& GetAmortizedQuadraticCostFactorOfVehicles()
1239 return quadratic_cost_factor_of_vehicle_;
1242 void SetVehicleUsedWhenEmpty(
bool is_used,
int vehicle) {
1243 DCHECK_LT(vehicle, vehicles_);
1244 vehicle_used_when_empty_[vehicle] = is_used;
1247 bool IsVehicleUsedWhenEmpty(
int vehicle)
const {
1248 DCHECK_LT(vehicle, vehicles_);
1249 return vehicle_used_when_empty_[vehicle];
1255 const Solver::IndexEvaluator2& first_solution_evaluator()
const {
1256 return first_solution_evaluator_;
1260 void SetFirstSolutionEvaluator(Solver::IndexEvaluator2 evaluator) {
1261 first_solution_evaluator_ = std::move(evaluator);
1265 void AddLocalSearchOperator(LocalSearchOperator* ls_operator);
1267 void AddSearchMonitor(SearchMonitor* monitor);
1274 void AddAtSolutionCallback(std::function<
void()>
callback,
1275 bool track_unchecked_neighbors =
false);
1280 void AddVariableMinimizedByFinalizer(IntVar*
var);
1283 void AddVariableMaximizedByFinalizer(IntVar*
var);
1286 void AddWeightedVariableMinimizedByFinalizer(IntVar*
var, int64_t cost);
1289 void AddWeightedVariableMaximizedByFinalizer(IntVar*
var, int64_t cost);
1292 void AddVariableTargetToFinalizer(IntVar*
var, int64_t target);
1295 void AddWeightedVariableTargetToFinalizer(IntVar*
var, int64_t target,
1306 void CloseModelWithParameters(
1307 const RoutingSearchParameters& search_parameters);
1314 const Assignment*
Solve(
const Assignment* assignment =
nullptr);
1323 const RoutingSearchParameters& search_parameters,
1324 std::vector<const Assignment*>* solutions =
nullptr);
1327 const Assignment* SolveFromAssignmentWithParameters(
1328 const Assignment* assignment,
1329 const RoutingSearchParameters& search_parameters,
1330 std::vector<const Assignment*>* solutions =
nullptr);
1335 const Assignment* FastSolveFromAssignmentWithParameters(
1336 const Assignment* assignment,
1337 const RoutingSearchParameters& search_parameters,
1338 bool check_solution_in_cp,
1339 absl::flat_hash_set<IntVar*>* touched =
nullptr);
1342 const Assignment* SolveFromAssignmentsWithParameters(
1343 const std::vector<const Assignment*>& assignments,
1344 const RoutingSearchParameters& search_parameters,
1345 std::vector<const Assignment*>* solutions =
nullptr);
1348 const Assignment* SolveWithIteratedLocalSearch(
1349 const RoutingSearchParameters& search_parameters);
1355 void SetAssignmentFromOtherModelAssignment(
1356 Assignment* target_assignment,
const RoutingModel* source_model,
1357 const Assignment* source_assignment);
1364 int64_t ComputeLowerBound();
1367 int64_t objective_lower_bound()
const {
return objective_lower_bound_; }
1369 Status
status()
const {
return status_; }
1371 bool enable_deep_serialization()
const {
return enable_deep_serialization_; }
1380 IntVar* ApplyLocks(
const std::vector<int64_t>& locks);
1389 bool ApplyLocksToAllVehicles(
const std::vector<std::vector<int64_t>>& locks,
1395 const Assignment* PreAssignment()
const {
return preassignment_; }
1396 Assignment* MutablePreAssignment() {
return preassignment_; }
1400 bool WriteAssignment(
const std::string& file_name)
const;
1404 Assignment* ReadAssignment(
const std::string& file_name);
1407 Assignment* RestoreAssignment(
const Assignment&
solution);
1413 Assignment* ReadAssignmentFromRoutes(
1414 const std::vector<std::vector<int64_t>>& routes,
1415 bool ignore_inactive_indices);
1432 bool RoutesToAssignment(
const std::vector<std::vector<int64_t>>& routes,
1433 bool ignore_inactive_indices,
bool close_routes,
1434 Assignment* assignment)
const;
1438 void AssignmentToRoutes(
const Assignment& assignment,
1439 std::vector<std::vector<int64_t>>* routes)
const;
1445 std::vector<std::vector<int64_t>> GetRoutesFromAssignment(
1446 const Assignment& assignment);
1465 Assignment* CompactAssignment(
const Assignment& assignment)
const;
1469 Assignment* CompactAndCheckAssignment(
const Assignment& assignment)
const;
1471 void AddToAssignment(IntVar*
var);
1472 void AddIntervalToAssignment(IntervalVar*
interval);
1483 const Assignment* PackCumulsOfOptimizerDimensionsFromAssignment(
1484 const Assignment* original_assignment, absl::Duration duration_limit,
1485 bool* time_limit_was_reached =
nullptr);
1488 struct RouteDimensionTravelInfo {
1490 struct TransitionInfo {
1495 struct PiecewiseLinearFormulation {
1497 absl::InlinedVector<int64_t, 8> x_anchors;
1503 absl::InlinedVector<int64_t, 8> y_anchors;
1505 std::string DebugString(std::string line_prefix =
"")
const;
1510 PiecewiseLinearFormulation travel_start_dependent_travel;
1515 PiecewiseLinearFormulation travel_compression_cost;
1520 int64_t pre_travel_transit_value;
1521 int64_t post_travel_transit_value;
1525 int64_t compressed_travel_value_lower_bound;
1531 int64_t travel_value_upper_bound;
1533 std::string DebugString(std::string line_prefix =
"")
const;
1538 std::vector<TransitionInfo> transition_info;
1540 int64_t travel_cost_coefficient;
1542 std::string DebugString(std::string line_prefix =
"")
const;
1547 void SetSweepArranger(SweepArranger* sweep_arranger);
1549 SweepArranger* sweep_arranger()
const;
1551 class NodeNeighborsByCostClass {
1553 NodeNeighborsByCostClass() =
default;
1557 void ComputeNeighbors(
const RoutingModel& routing_model,
int num_neighbors,
1558 bool add_vehicle_starts_to_neighbors);
1560 const std::vector<int>& GetNeighborsOfNodeForCostClass(
1561 int cost_class,
int node_index)
const {
1562 return all_nodes_.empty() ? node_index_to_neighbors_by_cost_class_
1563 [node_index][cost_class]
1564 ->PositionsSetAtLeastOnce()
1569 std::vector<std::vector<std::unique_ptr<SparseBitset<int>>>>
1570 node_index_to_neighbors_by_cost_class_;
1571 std::vector<int> all_nodes_;
1578 const NodeNeighborsByCostClass* GetOrCreateNodeNeighborsByCostClass(
1579 double neighbors_ratio, int64_t min_neighbors,
1580 double& neighbors_ratio_used,
1581 bool add_vehicle_starts_to_neighbors =
true);
1584 const NodeNeighborsByCostClass* GetOrCreateNodeNeighborsByCostClass(
1585 int num_neighbors,
bool add_vehicle_starts_to_neighbors =
true);
1591 void AddLocalSearchFilter(LocalSearchFilter* filter) {
1592 CHECK(filter !=
nullptr);
1594 LOG(WARNING) <<
"Model is closed, filter addition will be ignored.";
1596 extra_filters_.push_back({filter, LocalSearchFilterManager::kRelax});
1597 extra_filters_.push_back({filter, LocalSearchFilterManager::kAccept});
1602 int64_t Start(
int vehicle)
const {
return paths_metadata_.Starts()[vehicle]; }
1604 int64_t End(
int vehicle)
const {
return paths_metadata_.Ends()[vehicle]; }
1606 bool IsStart(int64_t
index)
const {
return paths_metadata_.IsStart(
index); }
1608 bool IsEnd(int64_t
index)
const {
return paths_metadata_.IsEnd(
index); }
1611 int VehicleIndex(int64_t
index)
const {
1612 return paths_metadata_.GetPath(
index);
1617 int64_t
Next(
const Assignment& assignment, int64_t
index)
const;
1619 bool IsVehicleUsed(
const Assignment& assignment,
int vehicle)
const;
1621#if !defined(SWIGPYTHON)
1624 const std::vector<IntVar*>& Nexts()
const {
return nexts_; }
1627 const std::vector<IntVar*>& VehicleVars()
const {
return vehicle_vars_; }
1631 const std::vector<IntVar*>& ResourceVars(
int resource_group)
const {
1632 return resource_vars_[resource_group];
1637 IntVar* NextVar(int64_t
index)
const {
return nexts_[
index]; }
1639 IntVar* ActiveVar(int64_t
index)
const {
return active_[
index]; }
1642 IntVar* ActiveVehicleVar(
int vehicle)
const {
1643 return vehicle_active_[vehicle];
1648 IntVar* VehicleRouteConsideredVar(
int vehicle)
const {
1649 return vehicle_route_considered_[vehicle];
1653 IntVar* VehicleVar(int64_t
index)
const {
return vehicle_vars_[
index]; }
1657 IntVar* ResourceVar(
int vehicle,
int resource_group)
const {
1658 DCHECK_LT(resource_group, resource_vars_.size());
1659 DCHECK_LT(vehicle, resource_vars_[resource_group].
size());
1660 return resource_vars_[resource_group][vehicle];
1663 IntVar* CostVar()
const {
return cost_; }
1667 int64_t GetArcCostForVehicle(int64_t from_index, int64_t to_index,
1668 int64_t vehicle)
const;
1670 bool CostsAreHomogeneousAcrossVehicles()
const {
1671 return costs_are_homogeneous_across_vehicles_;
1675 int64_t GetHomogeneousCost(int64_t from_index, int64_t to_index)
const {
1676 return GetArcCostForVehicle(from_index, to_index, 0);
1680 int64_t GetArcCostForFirstSolution(int64_t from_index,
1681 int64_t to_index)
const;
1688 int64_t GetArcCostForClass(int64_t from_index, int64_t to_index,
1691 CostClassIndex GetCostClassIndexOfVehicle(int64_t vehicle)
const {
1693 DCHECK_GE(vehicle, 0);
1694 DCHECK_LT(vehicle, cost_class_index_of_vehicle_.size());
1695 DCHECK_GE(cost_class_index_of_vehicle_[vehicle], 0);
1696 return cost_class_index_of_vehicle_[vehicle];
1703 return has_vehicle_with_zero_cost_class_;
1708 int GetCostClassesCount()
const {
return cost_classes_.size(); }
1710 int GetNonZeroCostClassesCount()
const {
1711 return std::max(0, GetCostClassesCount() - 1);
1713 VehicleClassIndex GetVehicleClassIndexOfVehicle(int64_t vehicle)
const {
1715 return vehicle_class_index_of_vehicle_[vehicle];
1719 int GetVehicleOfClass(VehicleClassIndex
vehicle_class)
const {
1721 const RoutingModel::VehicleTypeContainer& vehicle_type_container =
1722 GetVehicleTypeContainer();
1724 vehicle_type_container.vehicles_per_vehicle_class[
vehicle_class.value()]
1728 return vehicle_type_container
1733 int GetVehicleClassesCount()
const {
return num_vehicle_classes_; }
1735 const std::vector<int>& GetSameVehicleIndicesOfIndex(
int node)
const {
1737 return same_vehicle_groups_[same_vehicle_group_[node]];
1740 const VehicleTypeContainer& GetVehicleTypeContainer()
const {
1742 return vehicle_type_container_;
1763 bool ArcIsMoreConstrainedThanArc(int64_t from, int64_t to1, int64_t to2);
1768 std::string DebugOutputAssignment(
1769 const Assignment& solution_assignment,
1770 const std::string& dimension_to_print)
const;
1777 std::vector<std::vector<std::pair<int64_t, int64_t>>> GetCumulBounds(
1778 const Assignment& solution_assignment,
const RoutingDimension& dimension);
1781 bool CheckIfAssignmentIsFeasible(
const Assignment& assignment,
1782 bool call_at_solution_monitors);
1785 Solver* solver()
const {
return solver_.get(); }
1789 bool CheckLimit(absl::Duration offset = absl::ZeroDuration()) {
1790 DCHECK(
limit_ !=
nullptr);
1791 return limit_->CheckWithOffset(offset);
1795 absl::Duration RemainingTime()
const {
1796 DCHECK(
limit_ !=
nullptr);
1797 return limit_->AbsoluteSolverDeadline() - solver_->Now();
1801 void UpdateTimeLimit(absl::Duration
time_limit) {
1802 RegularLimit* limit = GetOrCreateLimit();
1803 limit->UpdateLimits(
time_limit, std::numeric_limits<int64_t>::max(),
1804 std::numeric_limits<int64_t>::max(),
1805 limit->solutions());
1809 absl::Duration TimeBuffer()
const {
return time_buffer_; }
1812 std::atomic<bool>* GetMutableCPSatInterrupt() {
return &interrupt_cp_sat_; }
1814 std::atomic<bool>* GetMutableCPInterrupt() {
return &interrupt_cp_; }
1816 void CancelSearch() {
1817 interrupt_cp_sat_ =
true;
1818 interrupt_cp_ =
true;
1823 int nodes()
const {
return nodes_; }
1825 int vehicles()
const {
return vehicles_; }
1827 int64_t Size()
const {
return nodes_ + vehicles_ - start_end_count_; }
1831 int64_t GetNumberOfDecisionsInFirstSolution(
1832 const RoutingSearchParameters& search_parameters)
const;
1833 int64_t GetNumberOfRejectsInFirstSolution(
1834 const RoutingSearchParameters& search_parameters)
const;
1836 operations_research::FirstSolutionStrategy::Value
1837 GetAutomaticFirstSolutionStrategy()
const {
1838 return automatic_first_solution_strategy_;
1842 bool IsMatchingModel()
const;
1846 bool AreRoutesInterdependent(
const RoutingSearchParameters&
parameters)
const;
1851 using GetTabuVarsCallback =
1852 std::function<std::vector<operations_research::IntVar*>(RoutingModel*)>;
1854 void SetTabuVarsCallback(GetTabuVarsCallback tabu_var_callback);
1870 DecisionBuilder* MakeGuidedSlackFinalizer(
1871 const RoutingDimension* dimension,
1872 std::function<int64_t(int64_t)> initializer);
1879 static std::unique_ptr<LocalSearchOperator> MakeGreedyDescentLSOperator(
1880 std::vector<IntVar*> variables);
1882 const std::vector<SearchMonitor*>& GetSearchMonitors()
const {
1899 DecisionBuilder* MakeSelfDependentDimensionFinalizer(
1900 const RoutingDimension* dimension);
1902 const PathsMetadata& GetPathsMetadata()
const {
return paths_metadata_; }
1904 BinCapacities* GetBinCapacities() {
return bin_capacities_.get(); }
1908 void SetSecondaryModel(RoutingModel* secondary_model,
1909 RoutingSearchParameters secondary_parameters) {
1911 secondary_model_ = secondary_model;
1912 secondary_parameters_ = std::move(secondary_parameters);
1918 enum RoutingLocalSearchOperator {
1921 LIGHT_RELOCATE_PAIR,
1929 GLOBAL_CHEAPEST_INSERTION_CLOSE_NODES_LNS,
1930 LOCAL_CHEAPEST_INSERTION_CLOSE_NODES_LNS,
1931 GLOBAL_CHEAPEST_INSERTION_PATH_LNS,
1932 LOCAL_CHEAPEST_INSERTION_PATH_LNS,
1933 RELOCATE_PATH_GLOBAL_CHEAPEST_INSERTION_INSERT_UNPERFORMED,
1934 GLOBAL_CHEAPEST_INSERTION_EXPENSIVE_CHAIN_LNS,
1935 LOCAL_CHEAPEST_INSERTION_EXPENSIVE_CHAIN_LNS,
1936 RELOCATE_EXPENSIVE_CHAIN,
1940 RELOCATE_AND_MAKE_ACTIVE,
1941 MAKE_ACTIVE_AND_RELOCATE,
1943 MAKE_CHAIN_INACTIVE,
1945 EXTENDED_SWAP_ACTIVE,
1946 SHORTEST_PATH_SWAP_ACTIVE,
1952 EXCHANGE_RELOCATE_PAIR,
1955 LOCAL_SEARCH_OPERATOR_COUNTER
1961 template <
typename T>
1962 struct ValuedNodes {
1963 std::vector<int64_t> indices;
1966 struct DisjunctionValues {
1968 int64_t max_cardinality;
1970 typedef ValuedNodes<DisjunctionValues> Disjunction;
1974 struct CostCacheElement {
1987 template <
class DimensionCumulOptimizer>
1988 struct DimensionCumulOptimizers {
1989 std::unique_ptr<DimensionCumulOptimizer> lp_optimizer;
1990 std::unique_ptr<DimensionCumulOptimizer> mp_optimizer;
1995 void AddNoCycleConstraintInternal();
1996 bool AddDimensionWithCapacityInternal(
1997 const std::vector<int>& evaluator_indices, int64_t slack_max,
1998 std::vector<int64_t> vehicle_capacities,
bool fix_start_cumul_to_zero,
1999 const std::string&
name);
2000 bool AddDimensionDependentDimensionWithVehicleCapacityInternal(
2001 const std::vector<int>& pure_transits,
2002 const std::vector<int>& dependent_transits,
2003 const RoutingDimension* base_dimension, int64_t slack_max,
2004 std::vector<int64_t> vehicle_capacities,
bool fix_start_cumul_to_zero,
2005 const std::string&
name);
2006 bool InitializeDimensionInternal(
2007 const std::vector<int>& evaluator_indices,
2008 const std::vector<int>& state_dependent_evaluator_indices,
2009 int64_t slack_max,
bool fix_start_cumul_to_zero,
2010 RoutingDimension* dimension);
2011 DimensionIndex GetDimensionIndex(
const std::string& dimension_name)
const;
2040 void StoreDimensionCumulOptimizers(
const RoutingSearchParameters&
parameters);
2047 void FinalizeAllowedVehicles();
2049 void ComputeCostClasses(
const RoutingSearchParameters&
parameters);
2050 void ComputeVehicleClasses();
2058 void ComputeVehicleTypes();
2060 void ComputeResourceClasses();
2070 void FinalizeVisitTypes();
2072 void TopologicallySortVisitTypes();
2073 int64_t GetArcCostForClassInternal(int64_t from_index, int64_t to_index,
2075 void AppendHomogeneousArcCosts(
const RoutingSearchParameters&
parameters,
2077 std::vector<IntVar*>* cost_elements);
2078 void AppendArcCosts(
const RoutingSearchParameters&
parameters,
int node_index,
2079 std::vector<IntVar*>* cost_elements);
2080 Assignment* DoRestoreAssignment();
2081 static const CostClassIndex kCostClassIndexOfZeroCost;
2082 int64_t SafeGetCostClassInt64OfVehicle(int64_t vehicle)
const {
2083 DCHECK_LT(0, vehicles_);
2084 return (vehicle >= 0 ? GetCostClassIndexOfVehicle(vehicle)
2085 : kCostClassIndexOfZeroCost)
2088 int64_t GetDimensionTransitCostSum(int64_t i, int64_t j,
2089 const CostClass& cost_class)
const;
2091 IntVar* CreateDisjunction(DisjunctionIndex disjunction);
2093 void AddPickupAndDeliverySetsInternal(
const std::vector<int64_t>& pickups,
2094 const std::vector<int64_t>& deliveries);
2097 IntVar* CreateSameVehicleCost(
int vehicle_index);
2100 int FindNextActive(
int index,
const std::vector<int64_t>& indices)
const;
2104 bool RouteCanBeUsedByVehicle(
const Assignment& assignment,
int start_index,
2113 bool ReplaceUnusedVehicle(
int unused_vehicle,
int active_vehicle,
2114 Assignment* compact_assignment)
const;
2116 void QuietCloseModel();
2117 void QuietCloseModelWithParameters(
2125 bool SolveMatchingModel(Assignment* assignment,
2129 bool AppendAssignmentIfFeasible(
2130 const Assignment& assignment,
2131 std::vector<std::unique_ptr<Assignment>>* assignments,
2132 bool call_at_solution_monitors =
true);
2135 void LogSolution(
const RoutingSearchParameters&
parameters,
2136 absl::string_view description, int64_t solution_cost,
2137 int64_t start_time_ms);
2140 Assignment* CompactAssignmentInternal(
const Assignment& assignment,
2141 bool check_compact_assignment)
const;
2144 std::string FindErrorInSearchParametersForModel(
2145 const RoutingSearchParameters& search_parameters)
const;
2147 void SetupSearch(
const RoutingSearchParameters& search_parameters);
2150 Assignment* GetOrCreateAssignment();
2151 Assignment* GetOrCreateTmpAssignment();
2152 RegularLimit* GetOrCreateLimit();
2153 RegularLimit* GetOrCreateCumulativeLimit();
2154 RegularLimit* GetOrCreateLocalSearchLimit();
2155 RegularLimit* GetOrCreateLargeNeighborhoodSearchLimit();
2156 RegularLimit* GetOrCreateFirstSolutionLargeNeighborhoodSearchLimit();
2157 LocalSearchOperator* CreateInsertionOperator();
2158 LocalSearchOperator* CreateMakeInactiveOperator();
2161 LocalSearchOperator* CreateCPOperator(
const T& operator_factory) {
2162 return operator_factory(solver_.get(), nexts_,
2163 CostsAreHomogeneousAcrossVehicles()
2164 ? std::vector<IntVar*>()
2166 vehicle_start_class_callback_);
2169 LocalSearchOperator* CreateCPOperator() {
2170 return CreateCPOperator(MakeLocalSearchOperator<T>);
2172 using NeighborAccessor = std::function<const std::vector<int>&(int, int)>;
2174 LocalSearchOperator* CreateCPOperatorWithNeighbors(
2175 NeighborAccessor get_neighbors) {
2176 return CreateCPOperatorWithNeighbors(
2177 MakeLocalSearchOperatorWithNeighbors<T>, std::move(get_neighbors));
2180 LocalSearchOperator* CreateOperatorWithNeighborsRatio(
2181 int neighbors_ratio_used, NeighborAccessor get_neighbors) {
2182 return neighbors_ratio_used == 1
2183 ? CreateCPOperator<T>()
2184 : CreateCPOperatorWithNeighbors<T>(
std::move(get_neighbors));
2187 LocalSearchOperator* CreateCPOperatorWithNeighbors(
2188 const T& operator_factory, NeighborAccessor get_neighbors) {
2189 return operator_factory(
2190 solver_.get(), nexts_,
2191 CostsAreHomogeneousAcrossVehicles() ? std::vector<IntVar*>()
2193 vehicle_start_class_callback_, std::move(get_neighbors));
2195 template <
class T,
class Arg>
2196 LocalSearchOperator* CreateOperator(
const Arg& arg) {
2197 return solver_->RevAlloc(
new T(nexts_,
2198 CostsAreHomogeneousAcrossVehicles()
2199 ? std::vector<IntVar*>()
2201 vehicle_start_class_callback_, arg));
2203 template <
class T,
class Arg>
2204 LocalSearchOperator* CreateOperatorWithNeighbors(
2205 NeighborAccessor get_neighbors,
const Arg& arg) {
2206 return solver_->RevAlloc(
2208 CostsAreHomogeneousAcrossVehicles() ? std::vector<IntVar*>()
2210 vehicle_start_class_callback_, std::move(get_neighbors), arg));
2212 template <
class T,
class Arg>
2213 LocalSearchOperator* CreateOperatorWithNeighborsRatio(
2214 int neighbors_ratio_used, NeighborAccessor get_neighbors,
2216 return neighbors_ratio_used == 1
2217 ? CreateOperator<T>(arg)
2218 : CreateOperatorWithNeighbors<T>(
std::move(get_neighbors), arg);
2220 template <
class T,
class Arg1,
class MoveableArg2>
2221 LocalSearchOperator* CreateOperator(
const Arg1& arg1, MoveableArg2 arg2) {
2222 return solver_->RevAlloc(
2224 CostsAreHomogeneousAcrossVehicles() ? std::vector<IntVar*>()
2226 vehicle_start_class_callback_, arg1, std::move(arg2)));
2228 template <
class T,
class Arg1,
class MoveableArg2>
2229 LocalSearchOperator* CreateOperatorWithNeighborsRatio(
2230 int neighbors_ratio_used, NeighborAccessor get_neighbors,
2231 const Arg1& arg1, MoveableArg2 arg2) {
2232 return neighbors_ratio_used == 1
2233 ? CreateOperator<T>(arg1, std::move(arg2))
2234 : solver_->RevAlloc(new T(nexts_,
2235 CostsAreHomogeneousAcrossVehicles()
2236 ?
std::vector<IntVar*>()
2238 vehicle_start_class_callback_,
2239 std::move(get_neighbors), arg1,
2243 LocalSearchOperator* CreatePairOperator() {
2244 return CreateOperator<T>(pickup_delivery_pairs_);
2247 LocalSearchOperator* CreatePairOperator(
int neighbors_ratio_used,
2248 NeighborAccessor get_neighbors) {
2249 return neighbors_ratio_used == 1
2250 ? CreateOperator<T>(pickup_delivery_pairs_)
2251 : CreateOperatorWithNeighbors<T>(
std::move(get_neighbors),
2252 pickup_delivery_pairs_);
2255 void CreateNeighborhoodOperators(
const RoutingSearchParameters&
parameters);
2256 LocalSearchOperator* ConcatenateOperators(
2257 const RoutingSearchParameters& search_parameters,
2258 const std::vector<LocalSearchOperator*>& operators)
const;
2259 LocalSearchOperator* GetNeighborhoodOperators(
2260 const RoutingSearchParameters& search_parameters,
2261 const absl::flat_hash_set<RoutingLocalSearchOperator>&
2262 operators_to_consider)
const;
2264 struct FilterOptions {
2265 bool filter_objective;
2266 bool filter_with_cp_solver;
2268 bool operator==(
const FilterOptions& other)
const {
2269 return other.filter_objective == filter_objective &&
2270 other.filter_with_cp_solver == filter_with_cp_solver;
2272 template <
typename H>
2274 return H::combine(std::move(h), options.filter_objective,
2275 options.filter_with_cp_solver);
2278 std::vector<LocalSearchFilterManager::FilterEvent> CreateLocalSearchFilters(
2279 const RoutingSearchParameters&
parameters,
const FilterOptions& options);
2280 LocalSearchFilterManager* GetOrCreateLocalSearchFilterManager(
2281 const RoutingSearchParameters&
parameters,
const FilterOptions& options);
2282 DecisionBuilder* CreateSolutionFinalizer(
2283 const RoutingSearchParameters&
parameters, SearchLimit* lns_limit);
2284 void CreateFirstSolutionDecisionBuilders(
2285 const RoutingSearchParameters& search_parameters);
2286 DecisionBuilder* GetFirstSolutionDecisionBuilder(
2287 const RoutingSearchParameters& search_parameters)
const;
2288 IntVarFilteredDecisionBuilder* GetFilteredFirstSolutionDecisionBuilderOrNull(
2289 const RoutingSearchParameters&
parameters)
const;
2291 template <
typename Heuristic,
typename... Args>
2292 IntVarFilteredDecisionBuilder* CreateIntVarFilteredDecisionBuilder(
2293 const Args&... args);
2295 LocalSearchPhaseParameters* CreateLocalSearchParameters(
2296 const RoutingSearchParameters& search_parameters,
bool secondary_ls);
2297 DecisionBuilder* CreatePrimaryLocalSearchDecisionBuilder(
2298 const RoutingSearchParameters& search_parameters);
2299 void SetupDecisionBuilders(
const RoutingSearchParameters& search_parameters);
2300 void SetupMetaheuristics(
const RoutingSearchParameters& search_parameters);
2301 void SetupAssignmentCollector(
2302 const RoutingSearchParameters& search_parameters);
2303 void SetupTrace(
const RoutingSearchParameters& search_parameters);
2304 void SetupImprovementLimit(
const RoutingSearchParameters& search_parameters);
2305 void SetupSearchMonitors(
const RoutingSearchParameters& search_parameters);
2306 bool UsesLightPropagation(
2307 const RoutingSearchParameters& search_parameters)
const;
2308 GetTabuVarsCallback tabu_var_callback_;
2314 void DetectImplicitPickupAndDeliveries();
2316 int GetVehicleStartClass(int64_t
start)
const;
2318 void InitSameVehicleGroups(
int number_of_groups) {
2319 same_vehicle_group_.assign(Size(), 0);
2320 same_vehicle_groups_.assign(number_of_groups, {});
2322 void SetSameVehicleGroup(
int index,
int group) {
2323 same_vehicle_group_[
index] = group;
2324 same_vehicle_groups_[group].push_back(
index);
2329 int GetGlobalCumulOptimizerIndex(
const RoutingDimension& dimension)
const;
2330 int GetLocalCumulOptimizerIndex(
const RoutingDimension& dimension)
const;
2333 std::unique_ptr<Solver> solver_;
2336 int max_active_vehicles_;
2337 Constraint* no_cycle_constraint_ =
nullptr;
2339 std::vector<IntVar*> nexts_;
2340 std::vector<IntVar*> vehicle_vars_;
2341 std::vector<IntVar*> active_;
2348 std::vector<std::vector<IntVar*> > resource_vars_;
2351 std::vector<IntVar*> vehicle_active_;
2352 std::vector<IntVar*> vehicle_route_considered_;
2357 std::vector<IntVar*> is_bound_to_end_;
2358 mutable RevSwitch is_bound_to_end_ct_added_;
2360 absl::flat_hash_map<std::string, DimensionIndex> dimension_name_to_index_;
2367 std::vector<std::unique_ptr<ResourceGroup> > resource_groups_;
2370 dimension_resource_group_indices_;
2375 std::vector<DimensionCumulOptimizers<GlobalDimensionCumulOptimizer> >
2376 global_dimension_optimizers_;
2378 std::vector<DimensionCumulOptimizers<LocalDimensionCumulOptimizer> >
2379 local_dimension_optimizers_;
2382 std::string primary_constrained_dimension_;
2384 IntVar* cost_ =
nullptr;
2385 std::vector<int> vehicle_to_transit_cost_;
2386 std::vector<int64_t> fixed_cost_of_vehicle_;
2387 std::vector<CostClassIndex> cost_class_index_of_vehicle_;
2388 bool has_vehicle_with_zero_cost_class_;
2389 std::vector<int64_t> linear_cost_factor_of_vehicle_;
2390 std::vector<int64_t> quadratic_cost_factor_of_vehicle_;
2391 bool vehicle_amortized_cost_factors_set_;
2403 std::vector<bool> vehicle_used_when_empty_;
2405 absl::flat_hash_map<std::pair<std::string, std::string>, std::vector<int64_t>,
2406 absl::Hash<std::pair<std::string, std::string>>>
2407 force_distance_to_vehicle_unit_costs_;
2410 bool costs_are_homogeneous_across_vehicles_;
2411 bool cache_callbacks_;
2412 mutable std::vector<CostCacheElement> cost_cache_;
2413 std::vector<VehicleClassIndex> vehicle_class_index_of_vehicle_;
2414 int num_vehicle_classes_;
2416 VehicleTypeContainer vehicle_type_container_;
2417 std::function<int(int64_t)> vehicle_start_class_callback_;
2421 std::vector<std::vector<DisjunctionIndex> > index_to_disjunctions_;
2423 std::vector<ValuedNodes<int64_t> > same_vehicle_costs_;
2426 std::vector<absl::flat_hash_set<int>> allowed_vehicles_;
2429 std::vector<PickupDeliveryPair> pickup_delivery_pairs_;
2430 std::vector<PickupDeliveryPair>
2431 implicit_pickup_delivery_pairs_without_alternatives_;
2432 std::vector<std::pair<DisjunctionIndex, DisjunctionIndex> >
2433 pickup_delivery_disjunctions_;
2438 std::vector<std::vector<PickupDeliveryPosition>> index_to_pickup_positions_;
2440 std::vector<std::vector<PickupDeliveryPosition>> index_to_delivery_positions_;
2442 std::vector<PickupAndDeliveryPolicy> vehicle_pickup_delivery_policy_;
2444 std::vector<int> same_vehicle_group_;
2446 std::vector<std::vector<int>> same_vehicle_groups_;
2449 std::vector<int> index_to_visit_type_;
2451 std::vector<VisitTypePolicy> index_to_type_policy_;
2453 std::vector<std::vector<int> > single_nodes_of_type_;
2454 std::vector<std::vector<int> > pair_indices_of_type_;
2456 std::vector<absl::flat_hash_set<int> >
2457 hard_incompatible_types_per_type_index_;
2458 bool has_hard_type_incompatibilities_;
2459 std::vector<absl::flat_hash_set<int> >
2460 temporal_incompatible_types_per_type_index_;
2461 bool has_temporal_type_incompatibilities_;
2463 std::vector<std::vector<absl::flat_hash_set<int> > >
2464 same_vehicle_required_type_alternatives_per_type_index_;
2465 bool has_same_vehicle_type_requirements_;
2466 std::vector<std::vector<absl::flat_hash_set<int> > >
2467 required_type_alternatives_when_adding_type_index_;
2468 std::vector<std::vector<absl::flat_hash_set<int> > >
2469 required_type_alternatives_when_removing_type_index_;
2470 bool has_temporal_type_requirements_;
2471 absl::flat_hash_map<int, absl::flat_hash_set<VisitTypePolicy> >
2472 trivially_infeasible_visit_types_to_policies_;
2489 std::vector<std::vector<int> > topologically_sorted_visit_types_;
2491 int num_visit_types_;
2494 std::vector<int> index_to_equivalence_class_;
2495 const PathsMetadata paths_metadata_;
2498 RoutingIndexManager manager_;
2499 int start_end_count_;
2501 bool closed_ =
false;
2502 Status status_ = ROUTING_NOT_SOLVED;
2503 bool enable_deep_serialization_ =
true;
2506 RoutingModel* secondary_model_ =
nullptr;
2507 RoutingSearchParameters secondary_parameters_;
2508 std::unique_ptr<SecondaryOptimizer> secondary_optimizer_;
2511 std::vector<DecisionBuilder*> first_solution_decision_builders_;
2512 std::vector<IntVarFilteredDecisionBuilder*>
2513 first_solution_filtered_decision_builders_;
2514 Solver::IndexEvaluator2 first_solution_evaluator_;
2515 FirstSolutionStrategy::Value automatic_first_solution_strategy_ =
2516 FirstSolutionStrategy::UNSET;
2517 std::vector<LocalSearchOperator*> local_search_operators_;
2518 std::vector<SearchMonitor*> monitors_;
2519 std::vector<SearchMonitor*> secondary_ls_monitors_;
2520 std::vector<SearchMonitor*> at_solution_monitors_;
2521 SearchMonitor* metaheuristic_ =
nullptr;
2522 SearchMonitor* search_log_ =
nullptr;
2523 bool local_optimum_reached_ =
false;
2525 int64_t objective_lower_bound_ =
kint64min;
2526 SolutionCollector* collect_assignments_ =
nullptr;
2527 SolutionCollector* collect_secondary_ls_assignments_ =
nullptr;
2528 SolutionCollector* collect_one_assignment_ =
nullptr;
2529 SolutionCollector* optimized_dimensions_assignment_collector_ =
nullptr;
2530 DecisionBuilder* solve_db_ =
nullptr;
2531 DecisionBuilder* improve_db_ =
nullptr;
2532 DecisionBuilder* secondary_ls_db_ =
nullptr;
2533 DecisionBuilder* restore_assignment_ =
nullptr;
2534 DecisionBuilder* restore_tmp_assignment_ =
nullptr;
2535 Assignment* assignment_ =
nullptr;
2536 Assignment* preassignment_ =
nullptr;
2537 Assignment* tmp_assignment_ =
nullptr;
2538 LocalSearchOperator* primary_ls_operator_ =
nullptr;
2539 LocalSearchOperator* secondary_ls_operator_ =
nullptr;
2540 std::vector<IntVar*> extra_vars_;
2541 std::vector<IntervalVar*> extra_intervals_;
2542 std::vector<LocalSearchOperator*> extra_operators_;
2543 absl::flat_hash_map<FilterOptions, LocalSearchFilterManager*>
2544 local_search_filter_managers_;
2545 std::vector<LocalSearchFilterManager::FilterEvent> extra_filters_;
2546 struct NodeNeighborsParameters {
2548 bool add_vehicle_starts_to_neighbors;
2550 bool operator==(
const NodeNeighborsParameters& other)
const {
2551 return num_neighbors == other.num_neighbors &&
2552 add_vehicle_starts_to_neighbors ==
2553 other.add_vehicle_starts_to_neighbors;
2555 template <
typename H>
2556 friend H
AbslHashValue(H h,
const NodeNeighborsParameters& params) {
2557 return H::combine(std::move(h), params.num_neighbors,
2558 params.add_vehicle_starts_to_neighbors);
2561 absl::flat_hash_map<NodeNeighborsParameters,
2562 std::unique_ptr<NodeNeighborsByCostClass>>
2563 node_neighbors_by_cost_class_per_size_;
2564 std::unique_ptr<FinalizerVariables> finalizer_variables_;
2566 std::unique_ptr<SweepArranger> sweep_arranger_;
2569 RegularLimit*
limit_ =
nullptr;
2570 RegularLimit* cumulative_limit_ =
nullptr;
2571 RegularLimit* ls_limit_ =
nullptr;
2572 RegularLimit* lns_limit_ =
nullptr;
2573 RegularLimit* first_solution_lns_limit_ =
nullptr;
2574 absl::Duration time_buffer_;
2576 std::atomic<bool> interrupt_cp_sat_;
2577 std::atomic<bool> interrupt_cp_;
2579 typedef std::pair<int64_t, int64_t> CacheKey;
2580 typedef absl::flat_hash_map<CacheKey, int64_t> TransitCallbackCache;
2581 typedef absl::flat_hash_map<CacheKey, StateDependentTransit>
2582 StateDependentTransitCallbackCache;
2592 std::vector<TransitCallback1> unary_transit_evaluators_;
2593 std::vector<TransitCallback2> transit_evaluators_;
2594 std::vector<TransitEvaluatorSign> transit_evaluator_sign_;
2596 std::vector<VariableIndexEvaluator2> state_dependent_transit_evaluators_;
2597 std::vector<std::unique_ptr<StateDependentTransitCallbackCache>>
2598 state_dependent_transit_evaluators_cache_;
2601 std::unique_ptr<BinCapacities> bin_capacities_;
2603 friend class RoutingDimension;
2604 friend class RoutingModelInspector;
2605 friend class ResourceGroup::Resource;
2609class RoutingModelVisitor :
public BaseObject {
2612 static const char kLightElement[];
2613 static const char kLightElement2[];
2614 static const char kRemoveValues[];
2620class DisjunctivePropagator {
2628 int num_chain_tasks = 0;
2631 std::vector<int64_t> duration_min;
2632 std::vector<int64_t> duration_max;
2635 std::vector<bool> is_preemptible;
2636 std::vector<const SortedDisjointIntervalList*> forbidden_intervals;
2637 std::vector<std::pair<int64_t, int64_t>> distance_duration;
2638 int64_t span_min = 0;
2644 duration_min.clear();
2645 duration_max.clear();
2648 is_preemptible.clear();
2649 forbidden_intervals.clear();
2650 distance_duration.clear();
2653 num_chain_tasks = 0;
2659 bool Propagate(Tasks* tasks);
2662 bool Precedences(Tasks* tasks);
2665 bool MirrorTasks(Tasks* tasks);
2667 bool EdgeFinding(Tasks* tasks);
2670 bool DetectablePrecedencesWithChain(Tasks* tasks);
2672 bool ForbiddenIntervals(Tasks* tasks);
2674 bool DistanceDuration(Tasks* tasks);
2677 bool ChainSpanMin(Tasks* tasks);
2682 bool ChainSpanMinDynamic(Tasks* tasks);
2687 sat::ThetaLambdaTree<int64_t> theta_lambda_tree_;
2689 std::vector<int> tasks_by_start_min_;
2690 std::vector<int> tasks_by_end_max_;
2691 std::vector<int> event_of_task_;
2692 std::vector<int> nonchain_tasks_by_start_max_;
2694 std::vector<int64_t> total_duration_before_;
2697struct TravelBounds {
2698 std::vector<int64_t> min_travels;
2699 std::vector<int64_t> max_travels;
2700 std::vector<int64_t> pre_travels;
2701 std::vector<int64_t> post_travels;
2705 const TravelBounds& travel_bounds,
2706 const RoutingDimension& dimension,
2707 DisjunctivePropagator::Tasks* tasks);
2709 DisjunctivePropagator::Tasks* tasks);
2711 const RoutingModel::TransitCallback2& evaluator,
2712 std::vector<int64_t>* values);
2714 const RoutingDimension& dimension,
2715 TravelBounds* travel_bounds);
2728class GlobalVehicleBreaksConstraint :
public Constraint {
2730 explicit GlobalVehicleBreaksConstraint(
const RoutingDimension* dimension);
2731 std::string DebugString()
const override {
2732 return "GlobalVehicleBreaksConstraint";
2735 void Post()
override;
2736 void InitialPropagate()
override;
2739 void PropagateNode(
int node);
2740 void PropagateVehicle(
int vehicle);
2742 const RoutingModel* model_;
2743 const RoutingDimension*
const dimension_;
2744 std::vector<Demon*> vehicle_demons_;
2745 std::vector<int64_t> path_;
2751 void FillPartialPathOfVehicle(
int vehicle);
2752 void FillPathTravels(absl::Span<const int64_t> path);
2764 class TaskTranslator {
2766 TaskTranslator(IntVar*
start, int64_t before_start, int64_t after_start)
2768 before_start_(before_start),
2769 after_start_(after_start) {}
2771 TaskTranslator() =
default;
2773 void SetStartMin(int64_t
value) {
2774 if (start_ !=
nullptr) {
2776 }
else if (interval_ !=
nullptr) {
2777 interval_->SetStartMin(
value);
2780 void SetStartMax(int64_t
value) {
2781 if (start_ !=
nullptr) {
2783 }
else if (interval_ !=
nullptr) {
2784 interval_->SetStartMax(
value);
2787 void SetDurationMin(int64_t
value) {
2788 if (interval_ !=
nullptr) {
2789 interval_->SetDurationMin(
value);
2792 void SetEndMin(int64_t
value) {
2793 if (start_ !=
nullptr) {
2795 }
else if (interval_ !=
nullptr) {
2796 interval_->SetEndMin(
value);
2799 void SetEndMax(int64_t
value) {
2800 if (start_ !=
nullptr) {
2802 }
else if (interval_ !=
nullptr) {
2803 interval_->SetEndMax(
value);
2808 IntVar* start_ =
nullptr;
2809 int64_t before_start_;
2810 int64_t after_start_;
2811 IntervalVar* interval_ =
nullptr;
2815 std::vector<TaskTranslator> task_translators_;
2818 DisjunctivePropagator disjunctive_propagator_;
2819 DisjunctivePropagator::Tasks tasks_;
2822 TravelBounds travel_bounds_;
2825class TypeRegulationsChecker {
2827 explicit TypeRegulationsChecker(
const RoutingModel&
model);
2828 virtual ~TypeRegulationsChecker() =
default;
2830 bool CheckVehicle(
int vehicle,
2831 const std::function<int64_t(int64_t)>& next_accessor);
2835 using VisitTypePolicy = RoutingModel::VisitTypePolicy;
2838 struct TypePolicyOccurrence {
2842 int num_type_added_to_vehicle = 0;
2848 int num_type_removed_from_vehicle = 0;
2853 int position_of_last_type_on_vehicle_up_to_visit = -1;
2860 bool TypeOccursOnRoute(
int type)
const;
2867 bool TypeCurrentlyOnRoute(
int type,
int pos)
const;
2869 void InitializeCheck(
int vehicle,
2870 const std::function<int64_t(int64_t)>& next_accessor);
2871 virtual void OnInitializeCheck() {}
2872 virtual bool HasRegulationsToCheck()
const = 0;
2873 virtual bool CheckTypeRegulations(
int type, VisitTypePolicy policy,
2875 virtual bool FinalizeCheck()
const {
return true; }
2877 const RoutingModel& model_;
2880 std::vector<TypePolicyOccurrence> occurrences_of_type_;
2881 std::vector<int64_t> current_route_visits_;
2885class TypeIncompatibilityChecker :
public TypeRegulationsChecker {
2887 TypeIncompatibilityChecker(
const RoutingModel&
model,
2888 bool check_hard_incompatibilities);
2889 ~TypeIncompatibilityChecker()
override =
default;
2892 bool HasRegulationsToCheck()
const override;
2893 bool CheckTypeRegulations(
int type, VisitTypePolicy policy,
int pos)
override;
2897 bool check_hard_incompatibilities_;
2901class TypeRequirementChecker :
public TypeRegulationsChecker {
2903 explicit TypeRequirementChecker(
const RoutingModel&
model)
2904 : TypeRegulationsChecker(
model) {}
2905 ~TypeRequirementChecker()
override =
default;
2908 bool HasRegulationsToCheck()
const override;
2909 void OnInitializeCheck()
override {
2910 types_with_same_vehicle_requirements_on_route_.clear();
2915 bool CheckRequiredTypesCurrentlyOnRoute(
2916 const std::vector<absl::flat_hash_set<int> >& required_type_alternatives,
2919 bool CheckTypeRegulations(
int type, VisitTypePolicy policy,
int pos)
override;
2920 bool FinalizeCheck()
const override;
2922 absl::flat_hash_set<int> types_with_same_vehicle_requirements_on_route_;
2965class TypeRegulationsConstraint :
public Constraint {
2967 explicit TypeRegulationsConstraint(
const RoutingModel&
model);
2969 void Post()
override;
2970 void InitialPropagate()
override;
2973 void PropagateNodeRegulations(
int node);
2974 void CheckRegulationsOnVehicle(
int vehicle);
2976 const RoutingModel& model_;
2977 TypeIncompatibilityChecker incompatibility_checker_;
2978 TypeRequirementChecker requirement_checker_;
2979 std::vector<Demon*> vehicle_demons_;
2997 BoundCost() :
bound(0), cost(0) {}
3001class SimpleBoundCosts {
3003 SimpleBoundCosts(
int num_bounds, BoundCost default_bound_cost)
3004 : bound_costs_(num_bounds, default_bound_cost) {}
3006 BoundCost& bound_cost(
int element) {
return bound_costs_[element]; }
3008 BoundCost bound_cost(
int element)
const {
return bound_costs_[element]; }
3009 int Size() {
return bound_costs_.size(); }
3010 SimpleBoundCosts(
const SimpleBoundCosts&) =
delete;
3011 SimpleBoundCosts operator=(
const SimpleBoundCosts&) =
delete;
3014 std::vector<BoundCost> bound_costs_;
3037class RoutingDimension {
3040 RoutingDimension(
const RoutingDimension&) =
delete;
3041 RoutingDimension& operator=(
const RoutingDimension&) =
delete;
3043 ~RoutingDimension();
3045 RoutingModel*
model()
const {
return model_; }
3049 int64_t GetTransitValue(int64_t from_index, int64_t to_index,
3050 int64_t vehicle)
const;
3053 int64_t GetTransitValueFromClass(int64_t from_index, int64_t to_index,
3055 return model_->TransitCallback(class_evaluators_[
vehicle_class])(from_index,
3061 IntVar* TransitVar(int64_t
index)
const {
return transits_[
index]; }
3062 IntVar* FixedTransitVar(int64_t
index)
const {
3063 return fixed_transits_[
index];
3065 IntVar* SlackVar(int64_t
index)
const {
return slacks_[
index]; }
3067#if !defined(SWIGPYTHON)
3070 const std::vector<IntVar*>& cumuls()
const {
return cumuls_; }
3071 const std::vector<IntVar*>& fixed_transits()
const {
return fixed_transits_; }
3072 const std::vector<IntVar*>& transits()
const {
return transits_; }
3073 const std::vector<IntVar*>& slacks()
const {
return slacks_; }
3074#if !defined(SWIGCSHARP) && !defined(SWIGJAVA)
3076 const std::vector<SortedDisjointIntervalList>& forbidden_intervals()
const {
3077 return forbidden_intervals_;
3080 SortedDisjointIntervalList GetAllowedIntervalsInRange(
3081 int64_t
index, int64_t min_value, int64_t max_value)
const;
3084 int64_t GetFirstPossibleGreaterOrEqualValueForNode(int64_t
index,
3085 int64_t min_value)
const {
3086 DCHECK_LT(
index, forbidden_intervals_.size());
3087 const SortedDisjointIntervalList& forbidden_intervals =
3088 forbidden_intervals_[
index];
3089 const auto first_forbidden_interval_it =
3090 forbidden_intervals.FirstIntervalGreaterOrEqual(min_value);
3091 if (first_forbidden_interval_it != forbidden_intervals.end() &&
3092 min_value >= first_forbidden_interval_it->start) {
3094 return CapAdd(first_forbidden_interval_it->end, 1);
3103 int64_t GetLastPossibleLessOrEqualValueForNode(int64_t
index,
3104 int64_t max_value)
const {
3105 DCHECK_LT(
index, forbidden_intervals_.size());
3106 const SortedDisjointIntervalList& forbidden_intervals =
3107 forbidden_intervals_[
index];
3108 const auto last_forbidden_interval_it =
3109 forbidden_intervals.LastIntervalLessOrEqual(max_value);
3110 if (last_forbidden_interval_it != forbidden_intervals.end() &&
3111 max_value <= last_forbidden_interval_it->
end) {
3113 return CapSub(last_forbidden_interval_it->start, 1);
3119 const std::vector<int64_t>& vehicle_capacities()
const {
3120 return vehicle_capacities_;
3124 const RoutingModel::TransitCallback2& transit_evaluator(
int vehicle)
const {
3125 return model_->TransitCallback(
3126 class_evaluators_[vehicle_to_class_[vehicle]]);
3131 const RoutingModel::TransitCallback2& class_transit_evaluator(
3133 const int vehicle = model_->GetVehicleOfClass(
vehicle_class);
3134 DCHECK_NE(vehicle, -1);
3135 return transit_evaluator(vehicle);
3139 bool IsUnary()
const {
3140 for (
int evaluator_index : class_evaluators_) {
3141 if (model_->UnaryTransitCallbackOrNull(evaluator_index) ==
nullptr) {
3151 const RoutingModel::TransitCallback1& GetUnaryTransitEvaluator(
3152 int vehicle)
const {
3153 return model_->UnaryTransitCallbackOrNull(
3154 class_evaluators_[vehicle_to_class_[vehicle]]);
3156 const RoutingModel::TransitCallback2& GetBinaryTransitEvaluator(
3157 int vehicle)
const {
3158 return model_->TransitCallback(
3159 class_evaluators_[vehicle_to_class_[vehicle]]);
3163 bool AreVehicleTransitsPositive(
int vehicle)
const {
3164 const int evaluator_index = class_evaluators_[vehicle_to_class_[vehicle]];
3165 return model()->transit_evaluator_sign_[evaluator_index] ==
3166 RoutingModel::kTransitEvaluatorSignPositiveOrZero;
3168 bool AllTransitEvaluatorSignsAreUnknown()
const;
3169 RoutingModel::TransitEvaluatorSign GetTransitEvaluatorSign(
3170 int vehicle)
const {
3171 const int evaluator_index = class_evaluators_[vehicle_to_class_[vehicle]];
3172 return model()->transit_evaluator_sign_[evaluator_index];
3174 int vehicle_to_class(
int vehicle)
const {
return vehicle_to_class_[vehicle]; }
3180 void SetSpanUpperBoundForVehicle(int64_t
upper_bound,
int vehicle);
3187 void SetSpanCostCoefficientForVehicle(int64_t
coefficient,
int vehicle);
3188 void SetSpanCostCoefficientForAllVehicles(int64_t
coefficient);
3196 void SetSlackCostCoefficientForVehicle(int64_t
coefficient,
int vehicle);
3197 void SetSlackCostCoefficientForAllVehicles(int64_t
coefficient);
3204 void SetGlobalSpanCostCoefficient(int64_t
coefficient);
3211 void SetCumulVarPiecewiseLinearCost(int64_t
index,
3212 const PiecewiseLinearFunction& cost);
3215 bool HasCumulVarPiecewiseLinearCost(int64_t
index)
const;
3218 const PiecewiseLinearFunction* GetCumulVarPiecewiseLinearCost(
3219 int64_t
index)
const;
3234 bool HasCumulVarSoftUpperBound(int64_t
index)
const;
3238 int64_t GetCumulVarSoftUpperBound(int64_t
index)
const;
3242 int64_t GetCumulVarSoftUpperBoundCoefficient(int64_t
index)
const;
3257 bool HasCumulVarSoftLowerBound(int64_t
index)
const;
3261 int64_t GetCumulVarSoftLowerBound(int64_t
index)
const;
3265 int64_t GetCumulVarSoftLowerBoundCoefficient(int64_t
index)
const;
3282#if !defined(SWIGPYTHON)
3283 void SetBreakIntervalsOfVehicle(std::vector<IntervalVar*> breaks,
int vehicle,
3284 int pre_travel_evaluator,
3285 int post_travel_evaluator);
3289 void SetBreakIntervalsOfVehicle(std::vector<IntervalVar*> breaks,
int vehicle,
3290 std::vector<int64_t> node_visit_transits);
3296 void SetBreakDistanceDurationOfVehicle(int64_t
distance, int64_t duration,
3300 void InitializeBreaks();
3302 bool HasBreakConstraints()
const;
3303#if !defined(SWIGPYTHON)
3306 void SetBreakIntervalsOfVehicle(
3307 std::vector<IntervalVar*> breaks,
int vehicle,
3308 std::vector<int64_t> node_visit_transits,
3309 std::function<int64_t(int64_t, int64_t)> delays);
3312 const std::vector<IntervalVar*>& GetBreakIntervalsOfVehicle(
3317 const std::vector<std::pair<int64_t, int64_t> >&
3318 GetBreakDistanceDurationOfVehicle(
int vehicle)
const;
3321 int GetPreTravelEvaluatorOfVehicle(
int vehicle)
const;
3322 int GetPostTravelEvaluatorOfVehicle(
int vehicle)
const;
3325 const RoutingDimension* base_dimension()
const {
return base_dimension_; }
3333 int64_t ShortestTransitionSlack(int64_t node)
const;
3336 const std::string&
name()
const {
return name_; }
3340 const ReverseArcListGraph<int, int>& GetPathPrecedenceGraph()
const {
3341 return path_precedence_graph_;
3354 typedef std::function<int64_t(
int,
int)> PickupToDeliveryLimitFunction;
3356 void SetPickupToDeliveryLimitFunctionForPair(
3357 PickupToDeliveryLimitFunction limit_function,
int pair_index);
3359 bool HasPickupToDeliveryLimits()
const;
3361 int64_t GetPickupToDeliveryLimitForPair(
int pair_index,
3362 int pickup_alternative_index,
3363 int delivery_alternative_index)
const;
3365 struct NodePrecedence {
3367 int64_t second_node;
3371 void AddNodePrecedence(NodePrecedence precedence) {
3372 node_precedences_.push_back(precedence);
3374 const std::vector<NodePrecedence>& GetNodePrecedences()
const {
3375 return node_precedences_;
3379 void AddNodePrecedence(int64_t first_node, int64_t second_node,
3381 AddNodePrecedence({first_node, second_node, offset});
3384 int64_t GetSpanUpperBoundForVehicle(
int vehicle)
const {
3385 return vehicle_span_upper_bounds_[vehicle];
3388 const std::vector<int64_t>& vehicle_span_upper_bounds()
const {
3389 return vehicle_span_upper_bounds_;
3392 int64_t GetSpanCostCoefficientForVehicle(
int vehicle)
const {
3393 return vehicle_span_cost_coefficients_[vehicle];
3396 int64_t GetSpanCostCoefficientForVehicleClass(
3398 const int vehicle = model_->GetVehicleOfClass(
vehicle_class);
3399 DCHECK_NE(vehicle, -1);
3400 return GetSpanCostCoefficientForVehicle(vehicle);
3404 const std::vector<int64_t>& vehicle_span_cost_coefficients()
const {
3405 return vehicle_span_cost_coefficients_;
3409 const std::vector<int64_t>& vehicle_slack_cost_coefficients()
const {
3410 return vehicle_slack_cost_coefficients_;
3413 int64_t GetSlackCostCoefficientForVehicle(
int vehicle)
const {
3414 return vehicle_slack_cost_coefficients_[vehicle];
3417 int64_t GetSlackCostCoefficientForVehicleClass(
3419 const int vehicle = model_->GetVehicleOfClass(
vehicle_class);
3420 DCHECK_NE(vehicle, -1);
3421 return GetSlackCostCoefficientForVehicle(vehicle);
3424 int64_t global_span_cost_coefficient()
const {
3425 return global_span_cost_coefficient_;
3428 int64_t GetGlobalOptimizerOffset()
const {
3429 DCHECK_GE(global_optimizer_offset_, 0);
3430 return global_optimizer_offset_;
3432 int64_t GetLocalOptimizerOffsetForVehicle(
int vehicle)
const {
3433 if (vehicle >= local_optimizer_offset_for_vehicle_.size()) {
3436 DCHECK_GE(local_optimizer_offset_for_vehicle_[vehicle], 0);
3437 return local_optimizer_offset_for_vehicle_[vehicle];
3442 void SetSoftSpanUpperBoundForVehicle(BoundCost bound_cost,
int vehicle) {
3443 if (!HasSoftSpanUpperBounds()) {
3444 vehicle_soft_span_upper_bound_ = std::make_unique<SimpleBoundCosts>(
3445 model_->vehicles(), BoundCost{kint64max, 0});
3447 vehicle_soft_span_upper_bound_->bound_cost(vehicle) = bound_cost;
3449 bool HasSoftSpanUpperBounds()
const {
3450 return vehicle_soft_span_upper_bound_ !=
nullptr;
3452 BoundCost GetSoftSpanUpperBoundForVehicle(
int vehicle)
const {
3453 DCHECK(HasSoftSpanUpperBounds());
3454 return vehicle_soft_span_upper_bound_->bound_cost(vehicle);
3458 void SetQuadraticCostSoftSpanUpperBoundForVehicle(BoundCost bound_cost,
3460 if (!HasQuadraticCostSoftSpanUpperBounds()) {
3461 vehicle_quadratic_cost_soft_span_upper_bound_ =
3462 std::make_unique<SimpleBoundCosts>(model_->vehicles(),
3463 BoundCost{kint64max, 0});
3465 vehicle_quadratic_cost_soft_span_upper_bound_->bound_cost(vehicle) =
3468 bool HasQuadraticCostSoftSpanUpperBounds()
const {
3469 return vehicle_quadratic_cost_soft_span_upper_bound_ !=
nullptr;
3471 BoundCost GetQuadraticCostSoftSpanUpperBoundForVehicle(
int vehicle)
const {
3472 DCHECK(HasQuadraticCostSoftSpanUpperBounds());
3473 return vehicle_quadratic_cost_soft_span_upper_bound_->bound_cost(vehicle);
3483 struct PiecewiseLinearCost {
3484 PiecewiseLinearCost() :
var(nullptr), cost(nullptr) {}
3486 std::unique_ptr<PiecewiseLinearFunction> cost;
3490 RoutingDimension(RoutingModel*
model, std::vector<int64_t> vehicle_capacities,
3491 const std::string&
name,
3492 const RoutingDimension* base_dimension);
3493 RoutingDimension(RoutingModel*
model, std::vector<int64_t> vehicle_capacities,
3494 const std::string&
name, SelfBased);
3495 void Initialize(
const std::vector<int>& transit_evaluators,
3496 const std::vector<int>& state_dependent_transit_evaluators,
3498 void InitializeCumuls();
3499 void InitializeTransits(
3500 const std::vector<int>& transit_evaluators,
3501 const std::vector<int>& state_dependent_transit_evaluators,
3503 void InitializeTransitVariables(int64_t slack_max);
3505 void SetupCumulVarSoftUpperBoundCosts(
3506 std::vector<IntVar*>* cost_elements)
const;
3508 void SetupCumulVarSoftLowerBoundCosts(
3509 std::vector<IntVar*>* cost_elements)
const;
3510 void SetupCumulVarPiecewiseLinearCosts(
3511 std::vector<IntVar*>* cost_elements)
const;
3514 void SetupGlobalSpanCost(std::vector<IntVar*>* cost_elements)
const;
3515 void SetupSlackAndDependentTransitCosts()
const;
3517 void CloseModel(
bool use_light_propagation);
3519 void SetOffsetForGlobalOptimizer(int64_t offset) {
3520 global_optimizer_offset_ = std::max(
Zero(), offset);
3523 void SetVehicleOffsetsForLocalOptimizer(std::vector<int64_t> offsets) {
3525 std::transform(offsets.begin(), offsets.end(), offsets.begin(),
3526 [](int64_t offset) { return std::max(Zero(), offset); });
3527 local_optimizer_offset_for_vehicle_ = std::move(offsets);
3531 std::vector<SortedDisjointIntervalList> forbidden_intervals_;
3532 std::vector<IntVar*> capacity_vars_;
3533 const std::vector<int64_t> vehicle_capacities_;
3534 std::vector<IntVar*> transits_;
3535 std::vector<IntVar*> fixed_transits_;
3538 std::vector<int> class_evaluators_;
3539 std::vector<int64_t> vehicle_to_class_;
3541 ReverseArcListGraph<int, int> path_precedence_graph_;
3547 std::vector<NodePrecedence> node_precedences_;
3552 const RoutingDimension*
const base_dimension_;
3557 std::vector<int> state_dependent_class_evaluators_;
3558 std::vector<int64_t> state_dependent_vehicle_to_class_;
3563 std::vector<PickupToDeliveryLimitFunction>
3564 pickup_to_delivery_limits_per_pair_index_;
3567 bool break_constraints_are_initialized_ =
false;
3569 std::vector<std::vector<IntervalVar*> > vehicle_break_intervals_;
3570 std::vector<std::vector<std::pair<int64_t, int64_t> > >
3571 vehicle_break_distance_duration_;
3576 std::vector<int> vehicle_pre_travel_evaluators_;
3577 std::vector<int> vehicle_post_travel_evaluators_;
3579 std::vector<IntVar*> slacks_;
3580 std::vector<IntVar*> dependent_transits_;
3581 std::vector<int64_t> vehicle_span_upper_bounds_;
3582 int64_t global_span_cost_coefficient_;
3583 std::vector<int64_t> vehicle_span_cost_coefficients_;
3584 std::vector<int64_t> vehicle_slack_cost_coefficients_;
3585 std::vector<SoftBound> cumul_var_soft_upper_bound_;
3586 std::vector<SoftBound> cumul_var_soft_lower_bound_;
3587 std::vector<PiecewiseLinearCost> cumul_var_piecewise_linear_cost_;
3588 RoutingModel*
const model_;
3589 const std::string name_;
3590 int64_t global_optimizer_offset_;
3591 std::vector<int64_t> local_optimizer_offset_for_vehicle_;
3593 std::unique_ptr<SimpleBoundCosts> vehicle_soft_span_upper_bound_;
3594 std::unique_ptr<SimpleBoundCosts>
3595 vehicle_quadratic_cost_soft_span_upper_bound_;
3596 friend class RoutingModel;
3597 friend class RoutingModelInspector;
3605 const RoutingSearchParameters& search_parameters,
3606 const Assignment* initial_solution,
3611 const RoutingModel& routing_model,
const RoutingDimension& dimension);
NodeIndexType size() const
const std::string name
A name for logging purposes.
const std::vector< IntVar * > cumuls_
For infeasible and unbounded see Not checked if options check_solutions_if_inf_or_unbounded and the If options first_solution_only is false
problem is infeasible or unbounded (default).
absl::StatusOr< SolveResult > Solve(const Model &model, const SolverType solver_type, const SolveArguments &solve_args, const SolverInitArguments &init_args)
H AbslHashValue(H h, const IndicatorConstraint &constraint)
CpSolverResponse SolveWithParameters(const CpModelProto &model_proto, const SatParameters ¶ms)
Solves the given CpModelProto with the given parameters.
In SWIG mode, we don't want anything besides these top-level includes.
LinearRange operator==(const LinearExpr &lhs, const LinearExpr &rhs)
int64_t CapAdd(int64_t x, int64_t y)
void FillTravelBoundsOfVehicle(int vehicle, const std::vector< int64_t > &path, const RoutingDimension &dimension, TravelBounds *travel_bounds)
int64_t CapSub(int64_t x, int64_t y)
IntVarLocalSearchFilter * MakeVehicleBreaksFilter(const RoutingModel &routing_model, const RoutingDimension &dimension)
std::function< int64_t(int64_t)> RoutingTransitCallback1
void AppendTasksFromPath(absl::Span< const int64_t > path, const TravelBounds &travel_bounds, const RoutingDimension &dimension, DisjunctivePropagator::Tasks *tasks)
void FillPathEvaluation(const std::vector< int64_t > &path, const RoutingModel::TransitCallback2 &evaluator, std::vector< int64_t > *values)
std::function< int64_t(int64_t, int64_t)> RoutingTransitCallback2
bool SolveModelWithSat(RoutingModel *model, const RoutingSearchParameters &search_parameters, const Assignment *initial_solution, Assignment *solution)
void AppendTasksFromIntervals(const std::vector< IntervalVar * > &intervals, DisjunctivePropagator::Tasks *tasks)
int64_t fixed_cost
Contrarily to CostClass, here we need strict equivalence.
RoutingModel::CostClassIndex cost_class_index
The cost class of the vehicle.
std::optional< int64_t > end
static const int64_t kint64max
static const int64_t kint64min