157 #ifndef OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_H_
158 #define OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_H_
163 #include <functional>
171 #include "absl/container/flat_hash_map.h"
172 #include "absl/container/flat_hash_set.h"
173 #include "absl/container/inlined_vector.h"
174 #include "absl/time/time.h"
182 #include "ortools/constraint_solver/routing_enums.pb.h"
184 #include "ortools/constraint_solver/routing_parameters.pb.h"
195 class GlobalDimensionCumulOptimizer;
196 class LocalDimensionCumulOptimizer;
197 class LocalSearchPhaseParameters;
199 class IndexNeighborFinder;
200 class IntVarFilteredDecisionBuilder;
202 class RoutingDimension;
213 path_of_node_.resize(num_indices, -1);
214 is_start_.resize(num_indices,
false);
215 is_end_.resize(num_indices,
false);
216 start_of_path_.resize(num_paths);
217 end_of_path_.resize(num_paths);
218 for (
int v = 0; v < num_paths; ++v) {
220 start_of_path_[v] =
start;
221 path_of_node_[
start] = v;
222 is_start_[
start] =
true;
224 end_of_path_[v] =
end;
225 path_of_node_[
end] = v;
230 bool IsStart(int64_t node)
const {
return is_start_[node]; }
231 bool IsEnd(int64_t node)
const {
return is_end_[node]; }
232 int GetPath(int64_t start_or_end_node)
const {
233 return path_of_node_[start_or_end_node];
235 const std::vector<int64_t>&
Starts()
const {
return start_of_path_; }
236 const std::vector<int64_t>&
Ends()
const {
return end_of_path_; }
239 std::vector<bool> is_start_;
240 std::vector<bool> is_end_;
241 std::vector<int64_t> start_of_path_;
242 std::vector<int64_t> end_of_path_;
243 std::vector<int64_t> path_of_node_;
347 std::vector<DimensionCost>
355 if (
a.evaluator_index !=
b.evaluator_index) {
356 return a.evaluator_index <
b.evaluator_index;
358 return a.dimension_transit_evaluator_class_and_cost_coefficient <
359 b.dimension_transit_evaluator_class_and_cost_coefficient;
471 absl::flat_hash_map<DimensionIndex, ResourceGroup::Attributes>
472 dimension_attributes_;
490 return vehicles_requiring_resource_;
494 return vehicle_requires_resource_[vehicle];
497 const std::vector<Resource>&
GetResources()
const {
return resources_; }
499 DCHECK_LT(resource_index, resources_.size());
500 return resources_[resource_index];
504 return affected_dimension_indices_;
506 int Size()
const {
return resources_.size(); }
510 std::vector<Resource> resources_;
511 std::vector<bool> vehicle_requires_resource_;
512 std::vector<int> vehicles_requiring_resource_;
514 absl::flat_hash_set<DimensionIndex> affected_dimension_indices_;
542 std::vector<std::vector<int64_t> > values);
548 CHECK_LT(callback_index, transit_evaluators_.size());
549 return transit_evaluators_[callback_index];
552 CHECK_LT(callback_index, unary_transit_evaluators_.size());
553 return unary_transit_evaluators_[callback_index];
556 int callback_index)
const {
557 CHECK_LT(callback_index, state_dependent_transit_evaluators_.size());
558 return state_dependent_transit_evaluators_[callback_index];
584 bool fix_start_cumul_to_zero,
const std::string&
name);
586 const std::vector<int>& evaluator_indices, int64_t slack_max,
587 int64_t
capacity,
bool fix_start_cumul_to_zero,
const std::string&
name);
589 std::vector<int64_t> vehicle_capacities,
590 bool fix_start_cumul_to_zero,
591 const std::string&
name);
593 const std::vector<int>& evaluator_indices, int64_t slack_max,
594 std::vector<int64_t> vehicle_capacities,
bool fix_start_cumul_to_zero,
595 const std::string&
name);
606 bool fix_start_cumul_to_zero,
const std::string&
name);
608 bool fix_start_cumul_to_zero,
609 const std::string&
name) {
611 fix_start_cumul_to_zero,
name);
624 bool fix_start_cumul_to_zero,
625 const std::string&
name);
636 std::vector<std::vector<int64_t> > values,
637 int64_t
capacity,
bool fix_start_cumul_to_zero,
const std::string&
name);
645 const std::vector<int>& pure_transits,
646 const std::vector<int>& dependent_transits,
648 std::vector<int64_t> vehicle_capacities,
bool fix_start_cumul_to_zero,
649 const std::string&
name) {
650 return AddDimensionDependentDimensionWithVehicleCapacityInternal(
651 pure_transits, dependent_transits, base_dimension, slack_max,
652 std::move(vehicle_capacities), fix_start_cumul_to_zero,
name);
658 int64_t slack_max, std::vector<int64_t> vehicle_capacities,
659 bool fix_start_cumul_to_zero,
const std::string&
name);
663 int64_t vehicle_capacity,
bool fix_start_cumul_to_zero,
664 const std::string&
name);
666 int pure_transit,
int dependent_transit,
668 int64_t vehicle_capacity,
bool fix_start_cumul_to_zero,
669 const std::string&
name);
673 const std::function<int64_t(int64_t)>& f, int64_t domain_start,
686 std::vector<IntVar*> spans,
687 std::vector<IntVar*> total_slacks);
694 return dimensions_.get();
707 return GetGlobalCumulOptimizerIndex(dimension) >= 0;
710 return GetLocalCumulOptimizerIndex(dimension) >= 0;
724 bool HasDimension(
const std::string& dimension_name)
const;
727 const std::string& dimension_name)
const;
731 const std::string& dimension_name)
const;
737 DCHECK(dimension_name.empty() ||
HasDimension(dimension_name));
738 primary_constrained_dimension_ = dimension_name;
742 return primary_constrained_dimension_;
751 return resource_groups_;
755 DCHECK_LT(rg_index, resource_groups_.size());
756 return resource_groups_[rg_index].get();
789 int64_t max_cardinality = 1);
792 int64_t
index)
const {
793 return index_to_disjunctions_[
index];
798 template <
typename F>
800 int64_t
index, int64_t max_cardinality, F f)
const {
802 if (disjunctions_[disjunction].
value.max_cardinality == max_cardinality) {
803 for (
const int64_t d_index : disjunctions_[disjunction].indices) {
809 #if !defined(SWIGPYTHON)
814 return disjunctions_[
index].indices;
818 int64_t GetDisjunctionPenalty(DisjunctionIndex index) const {
819 return disjunctions_[
index].value.penalty;
824 return disjunctions_[
index].value.max_cardinality;
830 bool HasMandatoryDisjunctions()
const;
833 bool HasMaxCardinalityConstrainedDisjunctions()
const;
838 std::vector<std::pair<int64_t, int64_t>> GetPerfectBinaryDisjunctions()
const;
844 void IgnoreDisjunctionsAlreadyForcedToZero();
849 void AddSoftSameVehicleConstraint(
const std::vector<int64_t>& indices,
856 void SetAllowedVehiclesForIndex(
const std::vector<int>& vehicles,
861 return allowed_vehicles_[
index].empty() ||
862 allowed_vehicles_[
index].find(vehicle) !=
863 allowed_vehicles_[
index].end();
881 void AddPickupAndDelivery(int64_t pickup, int64_t delivery);
885 void AddPickupAndDeliverySets(DisjunctionIndex pickup_disjunction,
886 DisjunctionIndex delivery_disjunction);
891 const std::vector<std::pair<int, int> >&
892 GetPickupIndexPairs(int64_t node_index)
const;
894 const std::vector<std::pair<int, int> >&
895 GetDeliveryIndexPairs(int64_t node_index)
const;
900 void SetPickupAndDeliveryPolicyOfAllVehicles(PickupAndDeliveryPolicy policy);
901 void SetPickupAndDeliveryPolicyOfVehicle(PickupAndDeliveryPolicy policy,
903 PickupAndDeliveryPolicy GetPickupAndDeliveryPolicyOfVehicle(
908 int GetNumOfSingletonNodes()
const;
913 return pickup_delivery_pairs_;
915 const std::vector<std::pair<DisjunctionIndex, DisjunctionIndex>>&
917 return pickup_delivery_disjunctions_;
925 return implicit_pickup_delivery_pairs_without_alternatives_;
939 enum VisitTypePolicy {
954 TYPE_SIMULTANEOUSLY_ADDED_AND_REMOVED
957 void SetVisitType(int64_t
index,
int type, VisitTypePolicy type_policy);
958 int GetVisitType(int64_t
index)
const;
959 const std::vector<int>& GetSingleNodesOfType(
int type)
const;
960 const std::vector<int>& GetPairIndicesOfType(
int type)
const;
961 VisitTypePolicy GetVisitTypePolicy(int64_t
index)
const;
966 void CloseVisitTypes();
972 return topologically_sorted_visit_types_;
979 void AddHardTypeIncompatibility(int type1, int type2);
980 void AddTemporalTypeIncompatibility(
int type1,
int type2);
982 const absl::flat_hash_set<int>& GetHardTypeIncompatibilitiesOfType(
984 const absl::flat_hash_set<int>& GetTemporalTypeIncompatibilitiesOfType(
989 return has_hard_type_incompatibilities_;
992 return has_temporal_type_incompatibilities_;
1004 void AddSameVehicleRequiredTypeAlternatives(
1005 int dependent_type, absl::flat_hash_set<int> required_type_alternatives);
1010 void AddRequiredTypeAlternativesWhenAddingType(
1011 int dependent_type, absl::flat_hash_set<int> required_type_alternatives);
1017 void AddRequiredTypeAlternativesWhenRemovingType(
1018 int dependent_type, absl::flat_hash_set<int> required_type_alternatives);
1022 const std::vector<absl::flat_hash_set<int> >&
1023 GetSameVehicleRequiredTypeAlternativesOfType(
int type)
const;
1025 const std::vector<absl::flat_hash_set<int> >&
1026 GetRequiredTypeAlternativesWhenAddingType(
int type)
const;
1028 const std::vector<absl::flat_hash_set<int> >&
1029 GetRequiredTypeAlternativesWhenRemovingType(
int type)
const;
1034 return has_same_vehicle_type_requirements_;
1037 return has_temporal_type_requirements_;
1043 return HasTemporalTypeIncompatibilities() ||
1044 HasHardTypeIncompatibilities() || HasSameVehicleTypeRequirements() ||
1045 HasTemporalTypeRequirements();
1052 int64_t UnperformedPenalty(int64_t var_index)
const;
1056 int64_t UnperformedPenaltyOrValue(int64_t default_value,
1057 int64_t var_index)
const;
1061 int64_t GetDepot()
const;
1068 max_active_vehicles_ = max_active_vehicles;
1075 void SetArcCostEvaluatorOfAllVehicles(
int evaluator_index);
1077 void SetArcCostEvaluatorOfVehicle(
int evaluator_index,
int vehicle);
1080 void SetFixedCostOfAllVehicles(int64_t
cost);
1082 void SetFixedCostOfVehicle(int64_t
cost,
int vehicle);
1086 int64_t GetFixedCostOfVehicle(
int vehicle)
const;
1103 void SetAmortizedCostFactorsOfAllVehicles(int64_t linear_cost_factor,
1104 int64_t quadratic_cost_factor);
1106 void SetAmortizedCostFactorsOfVehicle(int64_t linear_cost_factor,
1107 int64_t quadratic_cost_factor,
1111 return linear_cost_factor_of_vehicle_;
1115 return quadratic_cost_factor_of_vehicle_;
1119 DCHECK_LT(vehicle, vehicles_);
1120 vehicle_used_when_empty_[vehicle] = is_used;
1124 DCHECK_LT(vehicle, vehicles_);
1125 return vehicle_used_when_empty_[vehicle];
1132 return first_solution_evaluator_;
1137 first_solution_evaluator_ = std::move(evaluator);
1147 void AddAtSolutionCallback(std::function<
void()>
callback);
1152 void AddVariableMinimizedByFinalizer(
IntVar*
var);
1155 void AddVariableMaximizedByFinalizer(
IntVar*
var);
1158 void AddWeightedVariableMinimizedByFinalizer(
IntVar*
var, int64_t
cost);
1161 void AddWeightedVariableMaximizedByFinalizer(
IntVar*
var, int64_t
cost);
1164 void AddVariableTargetToFinalizer(
IntVar*
var, int64_t target);
1167 void AddWeightedVariableTargetToFinalizer(
IntVar*
var, int64_t target,
1178 void CloseModelWithParameters(
1179 const RoutingSearchParameters& search_parameters);
1195 const RoutingSearchParameters& search_parameters,
1196 std::vector<const Assignment*>* solutions =
nullptr);
1199 const Assignment* SolveFromAssignmentWithParameters(
1201 const RoutingSearchParameters& search_parameters,
1202 std::vector<const Assignment*>* solutions =
nullptr);
1205 const Assignment* SolveFromAssignmentsWithParameters(
1206 const std::vector<const Assignment*>& assignments,
1207 const RoutingSearchParameters& search_parameters,
1208 std::vector<const Assignment*>* solutions =
nullptr);
1214 void SetAssignmentFromOtherModelAssignment(
1223 int64_t ComputeLowerBound();
1236 IntVar* ApplyLocks(
const std::vector<int64_t>& locks);
1245 bool ApplyLocksToAllVehicles(
const std::vector<std::vector<int64_t>>& locks,
1256 bool WriteAssignment(
const std::string& file_name)
const;
1260 Assignment* ReadAssignment(
const std::string& file_name);
1270 const std::vector<std::vector<int64_t>>& routes,
1271 bool ignore_inactive_indices);
1288 bool RoutesToAssignment(
const std::vector<std::vector<int64_t>>& routes,
1289 bool ignore_inactive_indices,
bool close_routes,
1294 void AssignmentToRoutes(
1296 std::vector<std::vector<int64_t>>*
const routes)
const;
1302 std::vector<std::vector<int64_t>> GetRoutesFromAssignment(
1328 void AddToAssignment(
IntVar*
const var);
1340 const Assignment* PackCumulsOfOptimizerDimensionsFromAssignment(
1341 const Assignment* original_assignment, absl::Duration duration_limit,
1342 bool* time_limit_was_reached =
nullptr);
1362 std::string DebugString(std::string line_prefix =
"")
const;
1390 std::string DebugString(std::string line_prefix =
"")
const;
1399 std::string DebugString(std::string line_prefix =
"")
const;
1414 void ComputeNeighbors(
const RoutingModel& routing_model,
int num_neighbors);
1417 int cost_class,
int node_index)
const {
1418 return all_nodes_.empty() ? node_index_to_neighbors_by_cost_class_
1419 [node_index][cost_class]
1420 ->PositionsSetAtLeastOnce()
1425 std::vector<std::vector<std::unique_ptr<SparseBitset<int>>>>
1426 node_index_to_neighbors_by_cost_class_;
1427 std::vector<int> all_nodes_;
1432 const NodeNeighborsByCostClass* GetOrCreateNodeNeighborsByCostClass(
1440 CHECK(filter !=
nullptr);
1442 LOG(WARNING) <<
"Model is closed, filter addition will be ignored.";
1444 extra_filters_.push_back({filter, LocalSearchFilterManager::kRelax});
1445 extra_filters_.push_back({filter, LocalSearchFilterManager::kAccept});
1450 int64_t
Start(
int vehicle)
const {
return paths_metadata_.Starts()[vehicle]; }
1452 int64_t
End(
int vehicle)
const {
return paths_metadata_.Ends()[vehicle]; }
1460 return paths_metadata_.GetPath(
index);
1467 bool IsVehicleUsed(
const Assignment& assignment,
int vehicle)
const;
1469 #if !defined(SWIGPYTHON)
1472 const std::vector<IntVar*>&
Nexts()
const {
return nexts_; }
1475 const std::vector<IntVar*>&
VehicleVars()
const {
return vehicle_vars_; }
1480 return resource_vars_[resource_group];
1491 return vehicle_active_[vehicle];
1497 return vehicle_route_considered_[vehicle];
1506 DCHECK_LT(resource_group, resource_vars_.size());
1507 DCHECK_LT(vehicle, resource_vars_[resource_group].size());
1508 return resource_vars_[resource_group][vehicle];
1515 int64_t GetArcCostForVehicle(int64_t from_index, int64_t to_index,
1516 int64_t vehicle)
const;
1519 return costs_are_homogeneous_across_vehicles_;
1524 return GetArcCostForVehicle(from_index, to_index, 0);
1528 int64_t GetArcCostForFirstSolution(int64_t from_index,
1529 int64_t to_index)
const;
1536 int64_t GetArcCostForClass(int64_t from_index, int64_t to_index,
1537 int64_t cost_class_index)
const;
1541 DCHECK_GE(vehicle, 0);
1542 DCHECK_LT(vehicle, cost_class_index_of_vehicle_.size());
1543 DCHECK_GE(cost_class_index_of_vehicle_[vehicle], 0);
1544 return cost_class_index_of_vehicle_[vehicle];
1550 if (cost_class_index == kCostClassIndexOfZeroCost) {
1551 return has_vehicle_with_zero_cost_class_;
1553 return cost_class_index < cost_classes_.size();
1559 return std::max(0, GetCostClassesCount() - 1);
1563 return vehicle_class_index_of_vehicle_[vehicle];
1570 GetVehicleTypeContainer();
1576 return vehicle_type_container
1585 return same_vehicle_groups_[same_vehicle_group_[node]];
1590 return vehicle_type_container_;
1611 bool ArcIsMoreConstrainedThanArc(int64_t from, int64_t to1, int64_t to2);
1616 std::string DebugOutputAssignment(
1618 const std::string& dimension_to_print)
const;
1625 std::vector<std::vector<std::pair<int64_t, int64_t>>> GetCumulBounds(
1635 DCHECK(
limit_ !=
nullptr);
1636 return limit_->CheckWithOffset(offset);
1641 DCHECK(
limit_ !=
nullptr);
1642 return limit_->AbsoluteSolverDeadline() - solver_->Now();
1654 int64_t
Size()
const {
return nodes_ + vehicles_ - start_end_count_; }
1658 int64_t GetNumberOfDecisionsInFirstSolution(
1659 const RoutingSearchParameters& search_parameters)
const;
1660 int64_t GetNumberOfRejectsInFirstSolution(
1661 const RoutingSearchParameters& search_parameters)
const;
1665 return automatic_first_solution_strategy_;
1669 bool IsMatchingModel()
const;
1673 bool AreRoutesInterdependent(
const RoutingSearchParameters&
parameters)
const;
1679 std::function<std::vector<operations_research::IntVar*>(
RoutingModel*)>;
1699 std::function<int64_t(int64_t)> initializer);
1706 static std::unique_ptr<LocalSearchOperator> MakeGreedyDescentLSOperator(
1707 std::vector<IntVar*> variables);
1731 enum RoutingLocalSearchOperator {
1734 LIGHT_RELOCATE_PAIR,
1742 GLOBAL_CHEAPEST_INSERTION_CLOSE_NODES_LNS,
1743 LOCAL_CHEAPEST_INSERTION_CLOSE_NODES_LNS,
1744 GLOBAL_CHEAPEST_INSERTION_PATH_LNS,
1745 LOCAL_CHEAPEST_INSERTION_PATH_LNS,
1746 RELOCATE_PATH_GLOBAL_CHEAPEST_INSERTION_INSERT_UNPERFORMED,
1747 GLOBAL_CHEAPEST_INSERTION_EXPENSIVE_CHAIN_LNS,
1748 LOCAL_CHEAPEST_INSERTION_EXPENSIVE_CHAIN_LNS,
1749 RELOCATE_EXPENSIVE_CHAIN,
1753 RELOCATE_AND_MAKE_ACTIVE,
1754 MAKE_ACTIVE_AND_RELOCATE,
1756 MAKE_CHAIN_INACTIVE,
1758 EXTENDED_SWAP_ACTIVE,
1759 SHORTEST_PATH_SWAP_ACTIVE,
1765 EXCHANGE_RELOCATE_PAIR,
1768 LOCAL_SEARCH_OPERATOR_COUNTER
1774 template <
typename T>
1775 struct ValuedNodes {
1776 std::vector<int64_t> indices;
1779 struct DisjunctionValues {
1781 int64_t max_cardinality;
1783 typedef ValuedNodes<DisjunctionValues> Disjunction;
1787 struct CostCacheElement {
1794 CostClassIndex cost_class_index;
1800 template <
class DimensionCumulOptimizer>
1801 struct DimensionCumulOptimizers {
1802 std::unique_ptr<DimensionCumulOptimizer> lp_optimizer;
1803 std::unique_ptr<DimensionCumulOptimizer> mp_optimizer;
1808 void AddNoCycleConstraintInternal();
1809 bool AddDimensionWithCapacityInternal(
1810 const std::vector<int>& evaluator_indices, int64_t slack_max,
1811 std::vector<int64_t> vehicle_capacities,
bool fix_start_cumul_to_zero,
1812 const std::string&
name);
1813 bool AddDimensionDependentDimensionWithVehicleCapacityInternal(
1814 const std::vector<int>& pure_transits,
1815 const std::vector<int>& dependent_transits,
1816 const RoutingDimension* base_dimension, int64_t slack_max,
1817 std::vector<int64_t> vehicle_capacities,
bool fix_start_cumul_to_zero,
1818 const std::string&
name);
1819 bool InitializeDimensionInternal(
1820 const std::vector<int>& evaluator_indices,
1821 const std::vector<int>& state_dependent_evaluator_indices,
1822 int64_t slack_max,
bool fix_start_cumul_to_zero,
1823 RoutingDimension* dimension);
1824 DimensionIndex GetDimensionIndex(
const std::string& dimension_name)
const;
1853 void StoreDimensionCumulOptimizers(
const RoutingSearchParameters&
parameters);
1855 void ComputeCostClasses(
const RoutingSearchParameters&
parameters);
1856 void ComputeVehicleClasses();
1864 void ComputeVehicleTypes();
1874 void FinalizeVisitTypes();
1876 void TopologicallySortVisitTypes();
1877 int64_t GetArcCostForClassInternal(int64_t from_index, int64_t to_index,
1878 CostClassIndex cost_class_index)
const;
1879 void AppendHomogeneousArcCosts(
const RoutingSearchParameters&
parameters,
1881 std::vector<IntVar*>* cost_elements);
1882 void AppendArcCosts(
const RoutingSearchParameters&
parameters,
int node_index,
1883 std::vector<IntVar*>* cost_elements);
1884 Assignment* DoRestoreAssignment();
1885 static const CostClassIndex kCostClassIndexOfZeroCost;
1886 int64_t SafeGetCostClassInt64OfVehicle(int64_t vehicle)
const {
1887 DCHECK_LT(0, vehicles_);
1888 return (vehicle >= 0 ? GetCostClassIndexOfVehicle(vehicle)
1889 : kCostClassIndexOfZeroCost)
1892 int64_t GetDimensionTransitCostSum(int64_t i, int64_t j,
1893 const CostClass& cost_class)
const;
1895 IntVar* CreateDisjunction(DisjunctionIndex disjunction);
1897 void AddPickupAndDeliverySetsInternal(
const std::vector<int64_t>& pickups,
1898 const std::vector<int64_t>& deliveries);
1901 IntVar* CreateSameVehicleCost(
int vehicle_index);
1904 int FindNextActive(
int index,
const std::vector<int64_t>& indices)
const;
1908 bool RouteCanBeUsedByVehicle(
const Assignment& assignment,
int start_index,
1917 bool ReplaceUnusedVehicle(
int unused_vehicle,
int active_vehicle,
1918 Assignment* compact_assignment)
const;
1920 void QuietCloseModel();
1921 void QuietCloseModelWithParameters(
1929 bool SolveMatchingModel(Assignment* assignment,
1933 bool AppendAssignmentIfFeasible(
1934 const Assignment& assignment,
1935 std::vector<std::unique_ptr<Assignment>>* assignments);
1938 void LogSolution(
const RoutingSearchParameters&
parameters,
1939 const std::string& description, int64_t solution_cost,
1940 int64_t start_time_ms);
1943 Assignment* CompactAssignmentInternal(
const Assignment& assignment,
1944 bool check_compact_assignment)
const;
1949 std::string FindErrorInSearchParametersForModel(
1950 const RoutingSearchParameters& search_parameters)
const;
1952 void SetupSearch(
const RoutingSearchParameters& search_parameters);
1955 Assignment* GetOrCreateAssignment();
1956 Assignment* GetOrCreateTmpAssignment();
1957 RegularLimit* GetOrCreateLimit();
1958 RegularLimit* GetOrCreateLocalSearchLimit();
1959 RegularLimit* GetOrCreateLargeNeighborhoodSearchLimit();
1960 RegularLimit* GetOrCreateFirstSolutionLargeNeighborhoodSearchLimit();
1961 LocalSearchOperator* CreateInsertionOperator();
1962 LocalSearchOperator* CreateMakeInactiveOperator();
1964 LocalSearchOperator* CreateCPOperator(
const T& operator_factory) {
1965 return operator_factory(solver_.get(), nexts_,
1966 CostsAreHomogeneousAcrossVehicles()
1967 ? std::vector<IntVar*>()
1969 vehicle_start_class_callback_);
1972 LocalSearchOperator* CreateCPOperator() {
1973 return CreateCPOperator(MakeLocalSearchOperator<T>);
1975 template <
class T,
class Arg>
1976 LocalSearchOperator* CreateOperator(
const Arg& arg) {
1977 return solver_->RevAlloc(
new T(nexts_,
1978 CostsAreHomogeneousAcrossVehicles()
1979 ? std::vector<IntVar*>()
1981 vehicle_start_class_callback_, arg));
1983 template <
class T,
class Arg1,
class MoveableArg2>
1984 LocalSearchOperator* CreateOperator(
const Arg1& arg1, MoveableArg2 arg2) {
1985 return solver_->RevAlloc(
1987 CostsAreHomogeneousAcrossVehicles() ? std::vector<IntVar*>()
1989 vehicle_start_class_callback_, arg1, std::move(arg2)));
1992 LocalSearchOperator* CreatePairOperator() {
1993 return CreateOperator<T>(pickup_delivery_pairs_);
1995 void CreateNeighborhoodOperators(
const RoutingSearchParameters&
parameters);
1996 LocalSearchOperator* ConcatenateOperators(
1997 const RoutingSearchParameters& search_parameters,
1998 const std::vector<LocalSearchOperator*>& operators)
const;
1999 LocalSearchOperator* GetNeighborhoodOperators(
2000 const RoutingSearchParameters& search_parameters)
const;
2002 struct FilterOptions {
2003 bool filter_objective;
2004 bool filter_with_cp_solver;
2006 bool operator==(
const FilterOptions& other)
const {
2007 return other.filter_objective == filter_objective &&
2008 other.filter_with_cp_solver == filter_with_cp_solver;
2010 template <
typename H>
2012 return H::combine(std::move(h), options.filter_objective,
2013 options.filter_with_cp_solver);
2016 std::vector<LocalSearchFilterManager::FilterEvent> CreateLocalSearchFilters(
2017 const RoutingSearchParameters&
parameters,
const FilterOptions& options);
2018 LocalSearchFilterManager* GetOrCreateLocalSearchFilterManager(
2019 const RoutingSearchParameters&
parameters,
const FilterOptions& options);
2020 DecisionBuilder* CreateSolutionFinalizer(
2021 const RoutingSearchParameters&
parameters, SearchLimit* lns_limit);
2022 DecisionBuilder* CreateFinalizerForMinimizedAndMaximizedVariables();
2023 void CreateFirstSolutionDecisionBuilders(
2024 const RoutingSearchParameters& search_parameters);
2025 DecisionBuilder* GetFirstSolutionDecisionBuilder(
2026 const RoutingSearchParameters& search_parameters)
const;
2027 IntVarFilteredDecisionBuilder* GetFilteredFirstSolutionDecisionBuilderOrNull(
2028 const RoutingSearchParameters&
parameters)
const;
2030 template <
typename Heuristic,
typename... Args>
2031 IntVarFilteredDecisionBuilder* CreateIntVarFilteredDecisionBuilder(
2032 const Args&... args);
2034 LocalSearchPhaseParameters* CreateLocalSearchParameters(
2035 const RoutingSearchParameters& search_parameters);
2036 DecisionBuilder* CreateLocalSearchDecisionBuilder(
2037 const RoutingSearchParameters& search_parameters);
2038 void SetupDecisionBuilders(
const RoutingSearchParameters& search_parameters);
2039 void SetupMetaheuristics(
const RoutingSearchParameters& search_parameters);
2040 void SetupAssignmentCollector(
2041 const RoutingSearchParameters& search_parameters);
2042 void SetupTrace(
const RoutingSearchParameters& search_parameters);
2043 void SetupImprovementLimit(
const RoutingSearchParameters& search_parameters);
2044 void SetupSearchMonitors(
const RoutingSearchParameters& search_parameters);
2045 bool UsesLightPropagation(
2046 const RoutingSearchParameters& search_parameters)
const;
2047 GetTabuVarsCallback tabu_var_callback_;
2053 void DetectImplicitPickupAndDeliveries();
2055 int GetVehicleStartClass(int64_t
start)
const;
2057 void InitSameVehicleGroups(
int number_of_groups) {
2058 same_vehicle_group_.assign(Size(), 0);
2059 same_vehicle_groups_.assign(number_of_groups, {});
2061 void SetSameVehicleGroup(
int index,
int group) {
2062 same_vehicle_group_[
index] = group;
2063 same_vehicle_groups_[group].push_back(
index);
2068 int GetGlobalCumulOptimizerIndex(
const RoutingDimension& dimension)
const;
2069 int GetLocalCumulOptimizerIndex(
const RoutingDimension& dimension)
const;
2072 std::unique_ptr<Solver> solver_;
2075 int max_active_vehicles_;
2076 Constraint* no_cycle_constraint_ =
nullptr;
2078 std::vector<IntVar*> nexts_;
2079 std::vector<IntVar*> vehicle_vars_;
2080 std::vector<IntVar*> active_;
2087 std::vector<std::vector<IntVar*> > resource_vars_;
2090 std::vector<IntVar*> vehicle_active_;
2091 std::vector<IntVar*> vehicle_route_considered_;
2096 std::vector<IntVar*> is_bound_to_end_;
2097 mutable RevSwitch is_bound_to_end_ct_added_;
2099 absl::flat_hash_map<std::string, DimensionIndex> dimension_name_to_index_;
2106 std::vector<std::unique_ptr<ResourceGroup> > resource_groups_;
2109 dimension_resource_group_indices_;
2114 std::vector<DimensionCumulOptimizers<GlobalDimensionCumulOptimizer> >
2115 global_dimension_optimizers_;
2117 std::vector<DimensionCumulOptimizers<LocalDimensionCumulOptimizer> >
2118 local_dimension_optimizers_;
2121 std::string primary_constrained_dimension_;
2123 IntVar* cost_ =
nullptr;
2124 std::vector<int> vehicle_to_transit_cost_;
2125 std::vector<int64_t> fixed_cost_of_vehicle_;
2126 std::vector<CostClassIndex> cost_class_index_of_vehicle_;
2127 bool has_vehicle_with_zero_cost_class_;
2128 std::vector<int64_t> linear_cost_factor_of_vehicle_;
2129 std::vector<int64_t> quadratic_cost_factor_of_vehicle_;
2130 bool vehicle_amortized_cost_factors_set_;
2142 std::vector<bool> vehicle_used_when_empty_;
2146 bool costs_are_homogeneous_across_vehicles_;
2147 bool cache_callbacks_;
2148 mutable std::vector<CostCacheElement> cost_cache_;
2149 std::vector<VehicleClassIndex> vehicle_class_index_of_vehicle_;
2153 VehicleTypeContainer vehicle_type_container_;
2154 std::function<int(int64_t)> vehicle_start_class_callback_;
2158 std::vector<std::vector<DisjunctionIndex> > index_to_disjunctions_;
2160 std::vector<ValuedNodes<int64_t> > same_vehicle_costs_;
2163 std::vector<absl::flat_hash_set<int>> allowed_vehicles_;
2166 IndexPairs pickup_delivery_pairs_;
2167 IndexPairs implicit_pickup_delivery_pairs_without_alternatives_;
2168 std::vector<std::pair<DisjunctionIndex, DisjunctionIndex> >
2169 pickup_delivery_disjunctions_;
2173 std::vector<std::vector<std::pair<int, int> > > index_to_pickup_index_pairs_;
2175 std::vector<std::vector<std::pair<int, int> > >
2176 index_to_delivery_index_pairs_;
2178 std::vector<PickupAndDeliveryPolicy> vehicle_pickup_delivery_policy_;
2180 std::vector<int> same_vehicle_group_;
2182 std::vector<std::vector<int>> same_vehicle_groups_;
2185 std::vector<int> index_to_visit_type_;
2187 std::vector<VisitTypePolicy> index_to_type_policy_;
2189 std::vector<std::vector<int> > single_nodes_of_type_;
2190 std::vector<std::vector<int> > pair_indices_of_type_;
2192 std::vector<absl::flat_hash_set<int> >
2193 hard_incompatible_types_per_type_index_;
2194 bool has_hard_type_incompatibilities_;
2195 std::vector<absl::flat_hash_set<int> >
2196 temporal_incompatible_types_per_type_index_;
2197 bool has_temporal_type_incompatibilities_;
2199 std::vector<std::vector<absl::flat_hash_set<int> > >
2200 same_vehicle_required_type_alternatives_per_type_index_;
2201 bool has_same_vehicle_type_requirements_;
2202 std::vector<std::vector<absl::flat_hash_set<int> > >
2203 required_type_alternatives_when_adding_type_index_;
2204 std::vector<std::vector<absl::flat_hash_set<int> > >
2205 required_type_alternatives_when_removing_type_index_;
2206 bool has_temporal_type_requirements_;
2207 absl::flat_hash_map<int, absl::flat_hash_set<VisitTypePolicy> >
2208 trivially_infeasible_visit_types_to_policies_;
2225 std::vector<std::vector<int> > topologically_sorted_visit_types_;
2227 int num_visit_types_;
2230 std::vector<int> index_to_equivalence_class_;
2231 const PathsMetadata paths_metadata_;
2234 RoutingIndexManager manager_;
2235 int start_end_count_;
2237 bool closed_ =
false;
2238 Status status_ = ROUTING_NOT_SOLVED;
2239 bool enable_deep_serialization_ =
true;
2242 std::vector<DecisionBuilder*> first_solution_decision_builders_;
2243 std::vector<IntVarFilteredDecisionBuilder*>
2244 first_solution_filtered_decision_builders_;
2245 Solver::IndexEvaluator2 first_solution_evaluator_;
2247 FirstSolutionStrategy::UNSET;
2248 std::vector<LocalSearchOperator*> local_search_operators_;
2249 std::vector<SearchMonitor*> monitors_;
2250 bool local_optimum_reached_ =
false;
2252 int64_t objective_lower_bound_ =
kint64min;
2253 SolutionCollector* collect_assignments_ =
nullptr;
2254 SolutionCollector* collect_one_assignment_ =
nullptr;
2255 SolutionCollector* optimized_dimensions_assignment_collector_ =
nullptr;
2256 DecisionBuilder* solve_db_ =
nullptr;
2257 DecisionBuilder* improve_db_ =
nullptr;
2258 DecisionBuilder* restore_assignment_ =
nullptr;
2259 DecisionBuilder* restore_tmp_assignment_ =
nullptr;
2260 Assignment* assignment_ =
nullptr;
2261 Assignment* preassignment_ =
nullptr;
2262 Assignment* tmp_assignment_ =
nullptr;
2263 std::vector<IntVar*> extra_vars_;
2264 std::vector<IntervalVar*> extra_intervals_;
2265 std::vector<LocalSearchOperator*> extra_operators_;
2266 absl::flat_hash_map<FilterOptions, LocalSearchFilterManager*>
2267 local_search_filter_managers_;
2268 std::vector<LocalSearchFilterManager::FilterEvent> extra_filters_;
2269 absl::flat_hash_map<int, std::unique_ptr<NodeNeighborsByCostClass>>
2270 node_neighbors_by_cost_class_per_size_;
2273 VarTarget(IntVar* v, int64_t t) :
var(v), target(t) {}
2278 std::vector<std::pair<VarTarget, int64_t>>
2279 weighted_finalizer_variable_targets_;
2280 std::vector<VarTarget> finalizer_variable_targets_;
2281 absl::flat_hash_map<IntVar*, int> weighted_finalizer_variable_index_;
2282 absl::flat_hash_set<IntVar*> finalizer_variable_target_set_;
2283 std::unique_ptr<SweepArranger> sweep_arranger_;
2286 RegularLimit*
limit_ =
nullptr;
2287 RegularLimit* ls_limit_ =
nullptr;
2288 RegularLimit* lns_limit_ =
nullptr;
2289 RegularLimit* first_solution_lns_limit_ =
nullptr;
2290 absl::Duration time_buffer_;
2292 typedef std::pair<int64_t, int64_t> CacheKey;
2293 typedef absl::flat_hash_map<CacheKey, int64_t> TransitCallbackCache;
2294 typedef absl::flat_hash_map<CacheKey, StateDependentTransit>
2295 StateDependentTransitCallbackCache;
2297 std::vector<TransitCallback1> unary_transit_evaluators_;
2298 std::vector<TransitCallback2> transit_evaluators_;
2309 std::vector<bool> is_transit_evaluator_positive_;
2310 std::vector<VariableIndexEvaluator2> state_dependent_transit_evaluators_;
2311 std::vector<std::unique_ptr<StateDependentTransitCallbackCache>>
2312 state_dependent_transit_evaluators_cache_;
2325 static const char kLightElement[];
2326 static const char kLightElement2[];
2327 static const char kRemoveValues[];
2341 int num_chain_tasks = 0;
2351 int64_t span_min = 0;
2357 duration_min.clear();
2358 duration_max.clear();
2361 is_preemptible.clear();
2362 forbidden_intervals.clear();
2363 distance_duration.clear();
2366 num_chain_tasks = 0;
2372 bool Propagate(Tasks* tasks);
2375 bool Precedences(Tasks* tasks);
2378 bool MirrorTasks(Tasks* tasks);
2380 bool EdgeFinding(Tasks* tasks);
2383 bool DetectablePrecedencesWithChain(Tasks* tasks);
2385 bool ForbiddenIntervals(Tasks* tasks);
2387 bool DistanceDuration(Tasks* tasks);
2390 bool ChainSpanMin(Tasks* tasks);
2395 bool ChainSpanMinDynamic(Tasks* tasks);
2402 std::vector<int> tasks_by_start_min_;
2403 std::vector<int> tasks_by_end_max_;
2404 std::vector<int> event_of_task_;
2405 std::vector<int> nonchain_tasks_by_start_max_;
2407 std::vector<int64_t> total_duration_before_;
2425 std::vector<int64_t>* values);
2445 return "GlobalVehicleBreaksConstraint";
2448 void Post()
override;
2449 void InitialPropagate()
override;
2452 void PropagateNode(
int node);
2453 void PropagateVehicle(
int vehicle);
2457 std::vector<Demon*> vehicle_demons_;
2458 std::vector<int64_t> path_;
2464 void FillPartialPathOfVehicle(
int vehicle);
2465 void FillPathTravels(
const std::vector<int64_t>& path);
2477 class TaskTranslator {
2479 TaskTranslator(
IntVar*
start, int64_t before_start, int64_t after_start)
2481 before_start_(before_start),
2482 after_start_(after_start) {}
2484 TaskTranslator() =
default;
2486 void SetStartMin(int64_t
value) {
2487 if (start_ !=
nullptr) {
2489 }
else if (interval_ !=
nullptr) {
2490 interval_->SetStartMin(
value);
2493 void SetStartMax(int64_t
value) {
2494 if (start_ !=
nullptr) {
2496 }
else if (interval_ !=
nullptr) {
2497 interval_->SetStartMax(
value);
2500 void SetDurationMin(int64_t
value) {
2501 if (interval_ !=
nullptr) {
2502 interval_->SetDurationMin(
value);
2505 void SetEndMin(int64_t
value) {
2506 if (start_ !=
nullptr) {
2508 }
else if (interval_ !=
nullptr) {
2509 interval_->SetEndMin(
value);
2512 void SetEndMax(int64_t
value) {
2513 if (start_ !=
nullptr) {
2515 }
else if (interval_ !=
nullptr) {
2516 interval_->SetEndMax(
value);
2521 IntVar* start_ =
nullptr;
2522 int64_t before_start_;
2523 int64_t after_start_;
2524 IntervalVar* interval_ =
nullptr;
2528 std::vector<TaskTranslator> task_translators_;
2531 DisjunctivePropagator disjunctive_propagator_;
2532 DisjunctivePropagator::Tasks tasks_;
2535 TravelBounds travel_bounds_;
2543 bool CheckVehicle(
int vehicle,
2544 const std::function<int64_t(int64_t)>& next_accessor);
2555 int num_type_added_to_vehicle = 0;
2561 int num_type_removed_from_vehicle = 0;
2566 int position_of_last_type_on_vehicle_up_to_visit = -1;
2573 bool TypeOccursOnRoute(
int type)
const;
2580 bool TypeCurrentlyOnRoute(
int type,
int pos)
const;
2582 void InitializeCheck(
int vehicle,
2583 const std::function<int64_t(int64_t)>& next_accessor);
2593 std::vector<TypePolicyOccurrence> occurrences_of_type_;
2594 std::vector<int64_t> current_route_visits_;
2601 bool check_hard_incompatibilities);
2605 bool HasRegulationsToCheck()
const override;
2606 bool CheckTypeRegulations(
int type,
VisitTypePolicy policy,
int pos)
override;
2610 bool check_hard_incompatibilities_;
2621 bool HasRegulationsToCheck()
const override;
2622 void OnInitializeCheck()
override {
2623 types_with_same_vehicle_requirements_on_route_.clear();
2628 bool CheckRequiredTypesCurrentlyOnRoute(
2629 const std::vector<absl::flat_hash_set<int> >& required_type_alternatives,
2632 bool CheckTypeRegulations(
int type, VisitTypePolicy policy,
int pos)
override;
2633 bool FinalizeCheck()
const override;
2635 absl::flat_hash_set<int> types_with_same_vehicle_requirements_on_route_;
2682 void Post()
override;
2683 void InitialPropagate()
override;
2686 void PropagateNodeRegulations(
int node);
2687 void CheckRegulationsOnVehicle(
int vehicle);
2692 std::vector<Demon*> vehicle_demons_;
2717 : bound_costs_(num_bounds, default_bound_cost) {}
2722 int Size() {
return bound_costs_.size(); }
2727 std::vector<BoundCost> bound_costs_;
2758 int64_t GetTransitValue(int64_t from_index, int64_t to_index,
2759 int64_t vehicle)
const;
2764 return model_->TransitCallback(class_evaluators_[
vehicle_class])(from_index,
2772 return fixed_transits_[
index];
2776 #if !defined(SWIGPYTHON)
2781 const std::vector<IntVar*>&
transits()
const {
return transits_; }
2782 const std::vector<IntVar*>&
slacks()
const {
return slacks_; }
2783 #if !defined(SWIGCSHARP) && !defined(SWIGJAVA)
2786 return forbidden_intervals_;
2790 int64_t
index, int64_t min_value, int64_t max_value)
const;
2794 int64_t min_value)
const {
2795 DCHECK_LT(
index, forbidden_intervals_.size());
2797 forbidden_intervals_[
index];
2798 const auto first_forbidden_interval_it =
2800 if (first_forbidden_interval_it != forbidden_intervals.
end() &&
2801 min_value >= first_forbidden_interval_it->start) {
2803 return CapAdd(first_forbidden_interval_it->end, 1);
2813 int64_t max_value)
const {
2814 DCHECK_LT(
index, forbidden_intervals_.size());
2816 forbidden_intervals_[
index];
2817 const auto last_forbidden_interval_it =
2819 if (last_forbidden_interval_it != forbidden_intervals.
end() &&
2820 max_value <= last_forbidden_interval_it->
end) {
2822 return CapSub(last_forbidden_interval_it->start, 1);
2829 return vehicle_capacities_;
2834 return model_->TransitCallback(
2835 class_evaluators_[vehicle_to_class_[vehicle]]);
2842 const int vehicle = model_->GetVehicleOfClass(
vehicle_class);
2843 DCHECK_NE(vehicle, -1);
2844 return transit_evaluator(vehicle);
2851 int vehicle)
const {
2852 return model_->UnaryTransitCallbackOrNull(
2853 class_evaluators_[vehicle_to_class_[vehicle]]);
2856 int vehicle)
const {
2857 return model_->TransitCallback(
2858 class_evaluators_[vehicle_to_class_[vehicle]]);
2863 return model()->is_transit_evaluator_positive_
2864 [class_evaluators_[vehicle_to_class_[vehicle]]];
2872 void SetSpanUpperBoundForVehicle(int64_t
upper_bound,
int vehicle);
2879 void SetSpanCostCoefficientForVehicle(int64_t
coefficient,
int vehicle);
2880 void SetSpanCostCoefficientForAllVehicles(int64_t
coefficient);
2887 void SetGlobalSpanCostCoefficient(int64_t
coefficient);
2894 void SetCumulVarPiecewiseLinearCost(int64_t
index,
2898 bool HasCumulVarPiecewiseLinearCost(int64_t
index)
const;
2902 int64_t
index)
const;
2917 bool HasCumulVarSoftUpperBound(int64_t
index)
const;
2921 int64_t GetCumulVarSoftUpperBound(int64_t
index)
const;
2925 int64_t GetCumulVarSoftUpperBoundCoefficient(int64_t
index)
const;
2940 bool HasCumulVarSoftLowerBound(int64_t
index)
const;
2944 int64_t GetCumulVarSoftLowerBound(int64_t
index)
const;
2948 int64_t GetCumulVarSoftLowerBoundCoefficient(int64_t
index)
const;
2965 #if !defined(SWIGPYTHON)
2966 void SetBreakIntervalsOfVehicle(std::vector<IntervalVar*> breaks,
int vehicle,
2967 int pre_travel_evaluator,
2968 int post_travel_evaluator);
2972 void SetBreakIntervalsOfVehicle(std::vector<IntervalVar*> breaks,
int vehicle,
2973 std::vector<int64_t> node_visit_transits);
2979 void SetBreakDistanceDurationOfVehicle(int64_t
distance, int64_t duration,
2983 void InitializeBreaks();
2985 bool HasBreakConstraints()
const;
2986 #if !defined(SWIGPYTHON)
2989 void SetBreakIntervalsOfVehicle(
2990 std::vector<IntervalVar*> breaks,
int vehicle,
2991 std::vector<int64_t> node_visit_transits,
2992 std::function<int64_t(int64_t, int64_t)> delays);
2995 const std::vector<IntervalVar*>& GetBreakIntervalsOfVehicle(
3000 const std::vector<std::pair<int64_t, int64_t> >&
3001 GetBreakDistanceDurationOfVehicle(
int vehicle)
const;
3004 int GetPreTravelEvaluatorOfVehicle(
int vehicle)
const;
3005 int GetPostTravelEvaluatorOfVehicle(
int vehicle)
const;
3016 int64_t ShortestTransitionSlack(int64_t node)
const;
3019 const std::string&
name()
const {
return name_; }
3024 return path_precedence_graph_;
3039 void SetPickupToDeliveryLimitFunctionForPair(
3042 bool HasPickupToDeliveryLimits()
const;
3044 int64_t GetPickupToDeliveryLimitForPair(
int pair_index,
int pickup,
3045 int delivery)
const;
3054 node_precedences_.push_back(precedence);
3057 return node_precedences_;
3063 AddNodePrecedence({first_node, second_node, offset});
3067 return vehicle_span_upper_bounds_[vehicle];
3071 return vehicle_span_upper_bounds_;
3075 return vehicle_span_cost_coefficients_[vehicle];
3080 const int vehicle = model_->GetVehicleOfClass(
vehicle_class);
3081 DCHECK_NE(vehicle, -1);
3082 return GetSpanCostCoefficientForVehicle(vehicle);
3087 return vehicle_span_cost_coefficients_;
3091 return global_span_cost_coefficient_;
3095 DCHECK_GE(global_optimizer_offset_, 0);
3096 return global_optimizer_offset_;
3099 if (vehicle >= local_optimizer_offset_for_vehicle_.size()) {
3102 DCHECK_GE(local_optimizer_offset_for_vehicle_[vehicle], 0);
3103 return local_optimizer_offset_for_vehicle_[vehicle];
3109 if (!HasSoftSpanUpperBounds()) {
3110 vehicle_soft_span_upper_bound_ = std::make_unique<SimpleBoundCosts>(
3111 model_->vehicles(),
BoundCost{kint64max, 0});
3113 vehicle_soft_span_upper_bound_->bound_cost(vehicle) = bound_cost;
3116 return vehicle_soft_span_upper_bound_ !=
nullptr;
3119 DCHECK(HasSoftSpanUpperBounds());
3120 return vehicle_soft_span_upper_bound_->bound_cost(vehicle);
3126 if (!HasQuadraticCostSoftSpanUpperBounds()) {
3127 vehicle_quadratic_cost_soft_span_upper_bound_ =
3128 std::make_unique<SimpleBoundCosts>(model_->vehicles(),
3131 vehicle_quadratic_cost_soft_span_upper_bound_->bound_cost(vehicle) =
3135 return vehicle_quadratic_cost_soft_span_upper_bound_ !=
nullptr;
3138 DCHECK(HasQuadraticCostSoftSpanUpperBounds());
3139 return vehicle_quadratic_cost_soft_span_upper_bound_->bound_cost(vehicle);
3149 struct PiecewiseLinearCost {
3150 PiecewiseLinearCost() :
var(nullptr),
cost(nullptr) {}
3152 std::unique_ptr<PiecewiseLinearFunction>
cost;
3156 RoutingDimension(RoutingModel*
model, std::vector<int64_t> vehicle_capacities,
3157 const std::string&
name,
3158 const RoutingDimension* base_dimension);
3159 RoutingDimension(RoutingModel*
model, std::vector<int64_t> vehicle_capacities,
3160 const std::string&
name, SelfBased);
3161 void Initialize(
const std::vector<int>& transit_evaluators,
3162 const std::vector<int>& state_dependent_transit_evaluators,
3164 void InitializeCumuls();
3165 void InitializeTransits(
3166 const std::vector<int>& transit_evaluators,
3167 const std::vector<int>& state_dependent_transit_evaluators,
3169 void InitializeTransitVariables(int64_t slack_max);
3171 void SetupCumulVarSoftUpperBoundCosts(
3172 std::vector<IntVar*>* cost_elements)
const;
3174 void SetupCumulVarSoftLowerBoundCosts(
3175 std::vector<IntVar*>* cost_elements)
const;
3176 void SetupCumulVarPiecewiseLinearCosts(
3177 std::vector<IntVar*>* cost_elements)
const;
3180 void SetupGlobalSpanCost(std::vector<IntVar*>* cost_elements)
const;
3181 void SetupSlackAndDependentTransitCosts()
const;
3183 void CloseModel(
bool use_light_propagation);
3185 void SetOffsetForGlobalOptimizer(int64_t offset) {
3189 void SetVehicleOffsetsForLocalOptimizer(std::vector<int64_t> offsets) {
3191 std::transform(offsets.begin(), offsets.end(), offsets.begin(),
3192 [](int64_t offset) { return std::max(Zero(), offset); });
3193 local_optimizer_offset_for_vehicle_ = std::move(offsets);
3197 std::vector<SortedDisjointIntervalList> forbidden_intervals_;
3198 std::vector<IntVar*> capacity_vars_;
3199 const std::vector<int64_t> vehicle_capacities_;
3200 std::vector<IntVar*> transits_;
3201 std::vector<IntVar*> fixed_transits_;
3204 std::vector<int> class_evaluators_;
3205 std::vector<int64_t> vehicle_to_class_;
3207 ReverseArcListGraph<int, int> path_precedence_graph_;
3213 std::vector<NodePrecedence> node_precedences_;
3218 const RoutingDimension*
const base_dimension_;
3223 std::vector<int> state_dependent_class_evaluators_;
3224 std::vector<int64_t> state_dependent_vehicle_to_class_;
3229 std::vector<PickupToDeliveryLimitFunction>
3230 pickup_to_delivery_limits_per_pair_index_;
3233 bool break_constraints_are_initialized_ =
false;
3235 std::vector<std::vector<IntervalVar*> > vehicle_break_intervals_;
3236 std::vector<std::vector<std::pair<int64_t, int64_t> > >
3237 vehicle_break_distance_duration_;
3242 std::vector<int> vehicle_pre_travel_evaluators_;
3243 std::vector<int> vehicle_post_travel_evaluators_;
3245 std::vector<IntVar*> slacks_;
3246 std::vector<IntVar*> dependent_transits_;
3247 std::vector<int64_t> vehicle_span_upper_bounds_;
3248 int64_t global_span_cost_coefficient_;
3249 std::vector<int64_t> vehicle_span_cost_coefficients_;
3250 std::vector<SoftBound> cumul_var_soft_upper_bound_;
3251 std::vector<SoftBound> cumul_var_soft_lower_bound_;
3252 std::vector<PiecewiseLinearCost> cumul_var_piecewise_linear_cost_;
3253 RoutingModel*
const model_;
3254 const std::string name_;
3255 int64_t global_optimizer_offset_;
3256 std::vector<int64_t> local_optimizer_offset_for_vehicle_;
3258 std::unique_ptr<SimpleBoundCosts> vehicle_soft_span_upper_bound_;
3259 std::unique_ptr<SimpleBoundCosts>
3260 vehicle_quadratic_cost_soft_span_upper_bound_;
3270 std::vector<IntVar*> variables,
3271 std::vector<int64_t> targets);
3278 const RoutingSearchParameters& search_parameters,
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...
We call domain any subset of Int64 = [kint64min, kint64max].
GlobalVehicleBreaksConstraint ensures breaks constraints are enforced on all vehicles in the dimensio...
std::string DebugString() const override
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.
void SetSoftSpanUpperBoundForVehicle(BoundCost bound_cost, int vehicle)
If the span of vehicle on this dimension is larger than bound, the cost will be increased by cost * (...
void SetQuadraticCostSoftSpanUpperBoundForVehicle(BoundCost bound_cost, int vehicle)
If the span of vehicle on this dimension is larger than bound, the cost will be increased by cost * (...
const std::vector< IntVar * > & cumuls() const
Like CumulVar(), TransitVar(), SlackVar() but return the whole variable vectors instead (indexed by i...
IntVar * FixedTransitVar(int64_t index) const
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.
int64_t GetSpanCostCoefficientForVehicleClass(RoutingVehicleClassIndex vehicle_class) const
RoutingModel * model() const
Returns the model on which the dimension was created.
int64_t GetGlobalOptimizerOffset() const
const RoutingModel::TransitCallback1 & GetUnaryTransitEvaluator(int vehicle) const
Returns the unary callback evaluating the transit value between two node indices for a given vehicle.
BoundCost GetSoftSpanUpperBoundForVehicle(int vehicle) const
int64_t GetSpanCostCoefficientForVehicle(int vehicle) const
int64_t global_span_cost_coefficient() const
int64_t GetSpanUpperBoundForVehicle(int vehicle) const
bool AreVehicleTransitsPositive(int vehicle) const
Returns true iff the transit evaluator of 'vehicle' is positive for all arcs.
void AddNodePrecedence(int64_t first_node, int64_t second_node, int64_t offset)
const std::vector< IntVar * > & fixed_transits() const
const RoutingModel::TransitCallback2 & GetBinaryTransitEvaluator(int vehicle) const
const std::vector< IntVar * > & transits() const
const RoutingDimension * base_dimension() const
Returns the parent in the dependency tree if any or nullptr otherwise.
std::function< int64_t(int, int)> PickupToDeliveryLimitFunction
Limits, in terms of maximum difference between the cumul variables, between the pickup and delivery a...
void AddNodePrecedence(NodePrecedence precedence)
const std::vector< int64_t > & vehicle_span_cost_coefficients() const
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...
BoundCost GetQuadraticCostSoftSpanUpperBoundForVehicle(int vehicle) const
bool HasQuadraticCostSoftSpanUpperBounds() const
IntVar * SlackVar(int64_t index) const
int vehicle_to_class(int vehicle) const
const RoutingModel::TransitCallback2 & transit_evaluator(int vehicle) const
Returns the callback evaluating the transit value between two node indices for a given vehicle.
const std::vector< int64_t > & vehicle_capacities() const
Returns the capacities for all vehicles.
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...
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 ...
int64_t GetLocalOptimizerOffsetForVehicle(int vehicle) const
const ReverseArcListGraph< int, int > & GetPathPrecedenceGraph() const
Accessors.
const std::string & name() const
Returns the name of the dimension.
const std::vector< IntVar * > & slacks() const
IntVar * CumulVar(int64_t index) const
Get the cumul, transit and slack variables for the given node (given as int64_t var index).
const std::vector< NodePrecedence > & GetNodePrecedences() const
const std::vector< int64_t > & vehicle_span_upper_bounds() const
bool HasSoftSpanUpperBounds() const
IntVar * TransitVar(int64_t index) const
const std::vector< SortedDisjointIntervalList > & forbidden_intervals() const
Returns forbidden intervals for each node.
Manager for any NodeIndex <-> variable index conversion.
int64_t GetEndIndex(int vehicle) const
int64_t GetStartIndex(int vehicle) const
const std::vector< int > & GetNeighborsOfNodeForCostClass(int cost_class, int node_index) const
Returns the neighbors of the given node for the given cost_class.
NodeNeighborsByCostClass()=default
Attributes for a dimension.
const Domain & start_domain() const
const Domain & end_domain() const
A Resource sets attributes (costs/constraints) for a set of dimensions.
const ResourceGroup::Attributes & GetDimensionAttributes(const RoutingDimension *dimension) const
A ResourceGroup defines a set of available Resources with attributes on one or multiple dimensions.
const Resource & GetResource(int resource_index) const
bool VehicleRequiresAResource(int vehicle) const
int AddResource(Attributes attributes, const RoutingDimension *dimension)
Adds a Resource with the given attributes for the corresponding dimension.
const std::vector< Resource > & GetResources() const
const absl::flat_hash_set< DimensionIndex > & GetAffectedDimensionIndices() const
ResourceGroup(const RoutingModel *model)
const std::vector< int > & GetVehiclesRequiringAResource() const
void NotifyVehicleRequiresAResource(int vehicle)
Notifies that the given vehicle index requires a resource from this group if the vehicle is used (i....
IntVar * ResourceVar(int vehicle, int resource_group) const
Returns the resource variable for the given vehicle index in the given resource group.
const std::vector< std::unique_ptr< ResourceGroup > > & GetResourceGroups() const
const std::vector< std::pair< DisjunctionIndex, DisjunctionIndex > > & GetPickupAndDeliveryDisjunctions() const
const Assignment * PreAssignment() const
Returns an assignment used to fix some of the variables of the problem.
const std::string & GetPrimaryConstrainedDimension() const
Get the primary constrained dimension, or an empty string if it is unset.
std::function< std::vector< operations_research::IntVar * >(RoutingModel *)> GetTabuVarsCallback
Sets the callback returning the variable to use for the Tabu Search metaheuristic.
int nodes() const
Sizes and indices Returns the number of nodes in the model.
const std::vector< int > & GetSameVehicleIndicesOfIndex(int node) const
Returns variable indices of nodes constrained to be on the same route.
ResourceGroup * GetResourceGroup(int rg_index) const
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.
std::vector< const RoutingDimension * > GetDimensionsWithGlobalCumulOptimizers() const
Returns the dimensions which have [global|local]_dimension_optimizers_.
VehicleClassIndex GetVehicleClassIndexOfVehicle(int64_t vehicle) const
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 ...
RoutingIndexPair IndexPair
GlobalDimensionCumulOptimizer * GetMutableGlobalCumulLPOptimizer(const RoutingDimension &dimension) const
Returns the global/local dimension cumul optimizer for a given dimension, or nullptr if there is none...
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...
IntVar * ActiveVehicleVar(int vehicle) const
Returns the active variable of the vehicle.
RoutingTransitCallback1 TransitCallback1
const std::vector< int > & GetDimensionResourceGroupIndices(const RoutingDimension *dimension) const
Returns the indices of resource groups for this dimension.
int GetNumberOfVisitTypes() const
bool IsVehicleUsedWhenEmpty(int vehicle) const
const std::vector< std::vector< int > > & GetTopologicallySortedVisitTypes() const
int GetVehicleClassesCount() const
Returns the number of different vehicle classes in the model.
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.
Assignment * MutablePreAssignment()
IntVar * ActiveVar(int64_t index) const
Returns the active variable of the node corresponding to index.
const std::vector< DisjunctionIndex > & GetDisjunctionIndices(int64_t index) const
Returns the indices of the disjunctions to which an index belongs.
IntVar * NextVar(int64_t index) const
!defined(SWIGPYTHON)
int RegisterStateDependentTransitCallback(VariableIndexEvaluator2 callback)
int GetDimensionResourceGroupIndex(const RoutingDimension *dimension) const
Returns the index of the resource group attached to the dimension.
const std::vector< int64_t > & GetDisjunctionNodeIndices(DisjunctionIndex index) const
Returns the variable indices of the nodes in the disjunction of index 'index'.
const std::vector< int64_t > & GetAmortizedQuadraticCostFactorOfVehicles() const
const TransitCallback1 & UnaryTransitCallbackOrNull(int callback_index) const
VisitTypePolicy
Set the node visit types and incompatibilities/requirements between the types (see below).
@ TYPE_ADDED_TO_VEHICLE
When visited, the number of types 'T' on the vehicle increases by one.
@ ADDED_TYPE_REMOVED_FROM_VEHICLE
When visited, one instance of type 'T' previously added to the route (TYPE_ADDED_TO_VEHICLE),...
@ TYPE_ON_VEHICLE_UP_TO_VISIT
With the following policy, the visit enforces that type 'T' is considered on the route from its start...
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...
IntVar * VehicleVar(int64_t index) const
Returns the vehicle variable of the node corresponding to index.
int RegisterUnaryTransitVector(std::vector< int64_t > values)
Registers 'callback' and returns its index.
bool HasLocalCumulOptimizer(const RoutingDimension &dimension) const
void AddLocalSearchFilter(LocalSearchFilter *filter)
Adds a custom local search filter to the list of filters used to speed up local search by pruning unf...
int64_t Size() const
Returns the number of next variables in the model.
RoutingDimension * GetMutableDimension(const std::string &dimension_name) const
Returns a dimension from its name.
bool HasTemporalTypeRequirements() const
Solver * solver() const
Returns the underlying constraint solver.
static const int64_t kNoPenalty
Constant used to express a hard constraint instead of a soft penalty.
RoutingTransitCallback2 TransitCallback2
const std::vector< RoutingDimension * > & GetDimensions() const
Returns all dimensions of the model.
int64_t GetDisjunctionMaxCardinality(DisjunctionIndex index) const
Returns the maximum number of possible active nodes of the node disjunction of index 'index'.
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...
const std::vector< IntVar * > & ResourceVars(int resource_group) const
Returns vehicle resource variables for a given resource group, such that ResourceVars(r_g)[v] is the ...
const Solver::IndexEvaluator2 & first_solution_evaluator() const
Gets/sets the evaluator used during the search.
LocalDimensionCumulOptimizer * GetMutableLocalCumulLPOptimizer(const RoutingDimension &dimension) const
Status
Status of the search.
@ ROUTING_INFEASIBLE
Problem proven to be infeasible.
@ ROUTING_SUCCESS
Problem solved successfully after calling RoutingModel::Solve().
@ ROUTING_FAIL
No solution found to the problem after calling RoutingModel::Solve().
@ ROUTING_NOT_SOLVED
Problem not solved yet (before calling RoutingModel::Solve()).
@ ROUTING_PARTIAL_SUCCESS_LOCAL_OPTIMUM_NOT_REACHED
Problem solved successfully after calling RoutingModel::Solve(), except that a local optimum has not ...
@ ROUTING_INVALID
Model, model parameters or flags are not valid.
@ ROUTING_FAIL_TIMEOUT
Time limit reached before finding a solution with RoutingModel::Solve().
bool HasVehicleWithCostClassIndex(CostClassIndex cost_class_index) const
Returns true iff the model contains a vehicle with the given cost_class_index.
bool enable_deep_serialization() const
Returns the value of the internal enable_deep_serialization_ parameter.
std::vector< RoutingDimension * > GetDimensionsWithSoftOrSpanCosts() const
Returns dimensions with soft or vehicle span costs.
std::vector< const RoutingDimension * > GetDimensionsWithLocalCumulOptimizers() const
RoutingIndexPairs IndexPairs
bool CheckLimit(absl::Duration offset=absl::ZeroDuration())
Returns true if the search limit has been crossed with the given time offset.
bool IsVehicleAllowedForIndex(int vehicle, int64_t index)
Returns true if a vehicle is allowed to visit a given node.
int RegisterPositiveUnaryTransitCallback(TransitCallback1 callback)
const std::vector< IntVar * > & VehicleVars() const
Returns all vehicle variables of the model, such that VehicleVars(i) is the vehicle variable of the n...
absl::Duration TimeBuffer() const
Returns the time buffer to safely return a solution.
void SetMaximumNumberOfActiveVehicles(int max_active_vehicles)
Constrains the maximum number of active vehicles, aka the number of vehicles which do not have an emp...
const IndexPairs & GetImplicitUniquePickupAndDeliveryPairs() const
Returns implicit pickup and delivery pairs currently in the model.
const std::vector< int64_t > & GetAmortizedLinearCostFactorOfVehicles() const
DisjunctionIndex AddDisjunction(const std::vector< int64_t > &indices, int64_t penalty=kNoPenalty, int64_t max_cardinality=1)
Adds a disjunction constraint on the indices: exactly 'max_cardinality' of the indices are active.
bool HasGlobalCumulOptimizer(const RoutingDimension &dimension) const
Returns whether the given dimension has global/local cumul optimizers.
int RegisterTransitCallback(TransitCallback2 callback)
int AddResourceGroup()
Adds a resource group to the routing model.
int GetMaximumNumberOfActiveVehicles() const
Returns the maximum number of active vehicles.
RoutingDimensionIndex DimensionIndex
void SetVehicleUsedWhenEmpty(bool is_used, int vehicle)
LocalDimensionCumulOptimizer * GetMutableLocalCumulMPOptimizer(const RoutingDimension &dimension) const
bool HasHardTypeIncompatibilities() const
Returns true iff any hard (resp.
const IndexPairs & GetPickupAndDeliveryPairs() const
Returns pickup and delivery pairs currently in the model.
int RegisterPositiveTransitCallback(TransitCallback2 callback)
PickupAndDeliveryPolicy
Types of precedence policy applied to pickup and delivery pairs.
@ PICKUP_AND_DELIVERY_LIFO
Deliveries must be performed in reverse order of pickups.
@ PICKUP_AND_DELIVERY_NO_ORDER
Any precedence is accepted.
@ PICKUP_AND_DELIVERY_FIFO
Deliveries must be performed in the same order as pickups.
int64_t Start(int vehicle) const
Model inspection.
int vehicles() const
Returns the number of vehicle routes in the model.
int GetNumberOfDisjunctions() const
Returns the number of node disjunctions in the model.
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...
bool HasTypeRegulations() const
Returns true iff the model has any incompatibilities or requirements set on node types.
void SetFirstSolutionEvaluator(Solver::IndexEvaluator2 evaluator)
Takes ownership of evaluator.
RoutingVehicleClassIndex VehicleClassIndex
std::function< StateDependentTransit(int64_t, int64_t)> VariableIndexEvaluator2
int GetNonZeroCostClassesCount() const
Ditto, minus the 'always zero', built-in cost class.
bool AddDimensionWithVehicleCapacity(int evaluator_index, int64_t slack_max, std::vector< int64_t > vehicle_capacities, bool fix_start_cumul_to_zero, const std::string &name)
bool HasSameVehicleTypeRequirements() const
Returns true iff any same-route (resp.
IntVar * CostVar() const
Returns the global cost variable which is being minimized.
std::pair< int, bool > AddConstantDimension(int64_t value, int64_t capacity, bool fix_start_cumul_to_zero, const std::string &name)
void SetPrimaryConstrainedDimension(const std::string &dimension_name)
Set the given dimension as "primary constrained".
const VariableIndexEvaluator2 & StateDependentTransitCallback(int callback_index) const
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.
int RegisterUnaryTransitCallback(TransitCallback1 callback)
bool IsEnd(int64_t index) const
Returns true if 'index' represents the last node of a route.
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)
RoutingCostClassIndex CostClassIndex
bool HasTemporalTypeIncompatibilities() const
int GetCostClassesCount() const
Returns the number of different cost classes in the model.
const TransitCallback2 & TransitCallback(int callback_index) const
operations_research::FirstSolutionStrategy::Value GetAutomaticFirstSolutionStrategy() const
Returns the automatic first solution strategy selected.
const std::vector< SearchMonitor * > & GetSearchMonitors() const
IntVar * VehicleRouteConsideredVar(int vehicle) const
Returns the variable specifying whether or not the given vehicle route is considered for costs and co...
absl::Duration RemainingTime() const
Returns the time left in the search limit.
Status status() const
Returns the current status of the routing model.
int RegisterTransitMatrix(std::vector< std::vector< int64_t > > values)
static const DimensionIndex kNoDimension
Constant used to express the "no dimension" index, returned when a dimension name does not correspond...
bool CostsAreHomogeneousAcrossVehicles() const
Whether costs are homogeneous across all vehicles.
CostClassIndex GetCostClassIndexOfVehicle(int64_t vehicle) const
Get the cost class index of the given vehicle.
const VehicleTypeContainer & GetVehicleTypeContainer() const
static const DisjunctionIndex kNoDisjunction
Constant used to express the "no disjunction" index, returned when a node does not appear in any disj...
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...
int GetVehicleOfClass(VehicleClassIndex vehicle_class) const
Returns a vehicle of the given vehicle class, and -1 if there are no vehicles for this class.
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
int64_t End(int vehicle) const
Returns the variable index of the ending node of a vehicle route.
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 RoutingDimension & GetDimensionOrDie(const std::string &dimension_name) const
Returns a dimension from its name. Dies if the dimension does not exist.
A search monitor is a simple set of callbacks to monitor all search events.
BoundCost & bound_cost(int element)
SimpleBoundCosts(int num_bounds, BoundCost default_bound_cost)
BoundCost bound_cost(int element) const
SimpleBoundCosts(const SimpleBoundCosts &)=delete
SimpleBoundCosts operator=(const SimpleBoundCosts &)=delete
std::function< int64_t(int64_t, int64_t)> IndexEvaluator2
This class represents a sorted list of disjoint, closed intervals.
Iterator LastIntervalLessOrEqual(int64_t value) const
ConstIterator end() const
Iterator FirstIntervalGreaterOrEqual(int64_t value) const
Returns an iterator to either:
Class to arrange indices by their distance and their angle from the depot.
Checker for type incompatibilities.
~TypeIncompatibilityChecker() override=default
virtual bool HasRegulationsToCheck() const =0
virtual bool CheckTypeRegulations(int type, VisitTypePolicy policy, int pos)=0
virtual ~TypeRegulationsChecker()=default
virtual void OnInitializeCheck()
virtual bool FinalizeCheck() const
const RoutingModel & model_
The following constraint ensures that incompatibilities and requirements between types are respected.
Checker for type requirements.
~TypeRequirementChecker() override=default
TypeRequirementChecker(const RoutingModel &model)
const std::vector< IntVar * > cumuls_
static const int64_t kint64max
static const int64_t kint64min
#define DISALLOW_COPY_AND_ASSIGN(TypeName)
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)
std::function< int64_t(const Model &)> Value(IntegerVariable v)
CpSolverResponse SolveWithParameters(const CpModelProto &model_proto, const SatParameters ¶ms)
Solves the given CpModelProto with the given parameters.
Collection of objects used to extend the Constraint Solver library.
bool SolveModelWithSat(const RoutingModel &model, const RoutingSearchParameters &search_parameters, const Assignment *initial_solution, Assignment *solution)
Attempts to solve the model using the cp-sat solver.
int64_t CapAdd(int64_t x, int64_t y)
std::function< int64_t(int64_t, int64_t)> RoutingTransitCallback2
IntVarLocalSearchFilter * MakeVehicleBreaksFilter(const RoutingModel &routing_model, const RoutingDimension &dimension)
int64_t CapSub(int64_t x, int64_t y)
std::pair< std::vector< int64_t >, std::vector< int64_t > > RoutingIndexPair
void AppendTasksFromIntervals(const std::vector< IntervalVar * > &intervals, DisjunctivePropagator::Tasks *tasks)
DecisionBuilder * MakeRestoreDimensionValuesForUnchangedRoutes(RoutingModel *model)
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...
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
void FillPathEvaluation(const std::vector< int64_t > &path, const RoutingModel::TransitCallback2 &evaluator, std::vector< int64_t > *values)
void FillTravelBoundsOfVehicle(int vehicle, const std::vector< int64_t > &path, const RoutingDimension &dimension, TravelBounds *travel_bounds)
LinearRange operator==(const LinearExpr &lhs, const LinearExpr &rhs)
std::vector< RoutingIndexPair > RoutingIndexPairs
std::optional< int64_t > end
A structure meant to store soft bounds and associated violation constants.
BoundCost(int64_t bound, int64_t cost)
A structure to hold tasks described by their features.
std::vector< std::pair< int64_t, int64_t > > distance_duration
std::vector< int64_t > end_min
std::vector< int64_t > start_min
std::vector< const SortedDisjointIntervalList * > forbidden_intervals
std::vector< bool > is_preemptible
std::vector< int64_t > end_max
std::vector< int64_t > duration_max
std::vector< int64_t > start_max
std::vector< int64_t > duration_min
SUBTLE: The vehicle's fixed cost is skipped on purpose here, because we can afford to do so:
const RoutingDimension * dimension
bool operator<(const DimensionCost &cost) const
int64_t transit_evaluator_class
CostClass(int evaluator_index)
int evaluator_index
Index of the arc cost evaluator, registered in the RoutingModel class.
static bool LessThan(const CostClass &a, const CostClass &b)
Comparator for STL containers and algorithms.
std::vector< DimensionCost > dimension_transit_evaluator_class_and_cost_coefficient
The following struct defines a piecewise linear formulation, with int64_t values for the "anchor" x a...
absl::InlinedVector< int64_t, 8 > y_anchors
The y values used for the interpolation: For any x anchor value, let i be an index such that x_anchor...
absl::InlinedVector< int64_t, 8 > x_anchors
The set of increasing anchor cumul values for the interpolation.
Contains the information for a single transition on the route.
int64_t pre_travel_transit_value
The parts of the transit which occur pre/post travel between the nodes.
PiecewiseLinearFormulation travel_compression_cost
travel_compression_cost models the cost of the difference between the (real) travel value Tᵣ given by...
int64_t travel_value_upper_bound
The hard upper bound of the (real) travel value Tᵣ (see above).
int64_t compressed_travel_value_lower_bound
The hard lower bound of the compressed travel value that will be enforced by the scheduling module.
PiecewiseLinearFormulation travel_start_dependent_travel
Models the (real) travel value Tᵣ, for this transition based on the departure value of the travel.
int64_t post_travel_transit_value
Contains the information needed by the solver to optimize a dimension's cumuls with travel-start depe...
std::vector< TransitionInfo > transition_info
For each node #i on the route, transition_info[i] contains the relevant information for the travel be...
int64_t travel_cost_coefficient
The cost per unit of travel for this vehicle.
What follows is relevant for models with time/state dependent transits.
RangeIntToIntFunction * transit
RangeMinMaxIndexFunction * transit_plus_identity
f(x)
int64_t fixed_cost
Contrarily to CostClass, here we need strict equivalence.
absl::StrongVector< DimensionIndex, int64_t > dimension_end_cumuls_max
std::vector< int > required_resource_group_indices
Sorted set of resource groups for which the vehicle requires a resource.
uint64_t unvisitable_nodes_fprint
Fingerprint of unvisitable non-start/end nodes.
bool used_when_empty
Whether or not the vehicle is used when empty.
int start_equivalence_class
Vehicle start and end equivalence classes.
int end_equivalence_class
absl::StrongVector< DimensionIndex, int64_t > dimension_capacities
static bool LessThan(const VehicleClass &a, const VehicleClass &b)
Comparator for STL containers and algorithms.
absl::StrongVector< DimensionIndex, int64_t > dimension_end_cumuls_min
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.
absl::StrongVector< DimensionIndex, int64_t > dimension_start_cumuls_min
Bounds of cumul variables at start and end vehicle nodes.
absl::StrongVector< DimensionIndex, int64_t > dimension_start_cumuls_max
CostClassIndex cost_class_index
The cost class of the vehicle.
bool operator<(const VehicleClassEntry &other) const
Struct used to sort and store vehicles by their type.
std::vector< int > type_index_of_vehicle
std::vector< std::set< VehicleClassEntry > > sorted_vehicle_classes_per_type
int Type(int vehicle) const
std::vector< std::deque< int > > vehicles_per_vehicle_class
std::vector< int64_t > post_travels
std::vector< int64_t > max_travels
std::vector< int64_t > pre_travels
std::vector< int64_t > min_travels