157 #ifndef OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_H_
158 #define OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_H_
162 #include <functional>
170 #include "absl/container/flat_hash_map.h"
171 #include "absl/container/flat_hash_set.h"
172 #include "absl/functional/bind_front.h"
173 #include "absl/memory/memory.h"
174 #include "absl/time/time.h"
195 class GlobalDimensionCumulOptimizer;
196 class LocalDimensionCumulOptimizer;
197 class LocalSearchPhaseParameters;
199 class IndexNeighborFinder;
200 class IntVarFilteredDecisionBuilder;
202 class RoutingDimension;
303 std::vector<DimensionCost>
311 if (
a.evaluator_index !=
b.evaluator_index) {
312 return a.evaluator_index <
b.evaluator_index;
314 return a.dimension_transit_evaluator_class_and_cost_coefficient <
315 b.dimension_transit_evaluator_class_and_cost_coefficient;
403 std::vector<std::vector<int64_t> > values);
409 CHECK_LT(callback_index, transit_evaluators_.size());
410 return transit_evaluators_[callback_index];
413 CHECK_LT(callback_index, unary_transit_evaluators_.size());
414 return unary_transit_evaluators_[callback_index];
417 int callback_index)
const {
418 CHECK_LT(callback_index, state_dependent_transit_evaluators_.size());
419 return state_dependent_transit_evaluators_[callback_index];
445 bool fix_start_cumul_to_zero,
const std::string&
name);
447 const std::vector<int>& evaluator_indices, int64_t slack_max,
448 int64_t
capacity,
bool fix_start_cumul_to_zero,
const std::string&
name);
450 std::vector<int64_t> vehicle_capacities,
451 bool fix_start_cumul_to_zero,
452 const std::string&
name);
454 const std::vector<int>& evaluator_indices, int64_t slack_max,
455 std::vector<int64_t> vehicle_capacities,
bool fix_start_cumul_to_zero,
456 const std::string&
name);
467 bool fix_start_cumul_to_zero,
const std::string&
name);
469 bool fix_start_cumul_to_zero,
470 const std::string&
name) {
472 fix_start_cumul_to_zero,
name);
485 bool fix_start_cumul_to_zero,
486 const std::string&
name);
497 std::vector<std::vector<int64_t> > values,
498 int64_t
capacity,
bool fix_start_cumul_to_zero,
const std::string&
name);
506 const std::vector<int>& pure_transits,
507 const std::vector<int>& dependent_transits,
509 std::vector<int64_t> vehicle_capacities,
bool fix_start_cumul_to_zero,
510 const std::string&
name) {
511 return AddDimensionDependentDimensionWithVehicleCapacityInternal(
512 pure_transits, dependent_transits, base_dimension, slack_max,
513 std::move(vehicle_capacities), fix_start_cumul_to_zero,
name);
519 int64_t slack_max, std::vector<int64_t> vehicle_capacities,
520 bool fix_start_cumul_to_zero,
const std::string&
name);
524 int64_t vehicle_capacity,
bool fix_start_cumul_to_zero,
525 const std::string&
name);
527 int pure_transit,
int dependent_transit,
529 int64_t vehicle_capacity,
bool fix_start_cumul_to_zero,
530 const std::string&
name);
534 const std::function<int64_t(int64_t)>& f, int64_t domain_start,
547 std::vector<IntVar*> spans,
548 std::vector<IntVar*> total_slacks);
555 return dimensions_.get();
562 const std::vector<std::unique_ptr<GlobalDimensionCumulOptimizer> >&
564 return global_dimension_optimizers_;
566 const std::vector<std::unique_ptr<LocalDimensionCumulOptimizer> >&
568 return local_dimension_optimizers_;
570 const std::vector<std::unique_ptr<LocalDimensionCumulOptimizer> >&
572 return local_dimension_mp_optimizers_;
586 bool HasDimension(
const std::string& dimension_name)
const;
589 const std::string& dimension_name)
const;
593 const std::string& dimension_name)
const;
600 primary_constrained_dimension_ = dimension_name;
604 return primary_constrained_dimension_;
624 int64_t max_cardinality = 1);
627 int64_t
index)
const {
628 return index_to_disjunctions_[
index];
633 template <
typename F>
635 int64_t
index, int64_t max_cardinality, F f)
const {
637 if (disjunctions_[disjunction].
value.max_cardinality == max_cardinality) {
638 for (
const int64_t d_index : disjunctions_[disjunction].indices) {
644 #if !defined(SWIGPYTHON)
649 return disjunctions_[
index].indices;
653 int64_t GetDisjunctionPenalty(DisjunctionIndex index) const {
654 return disjunctions_[
index].value.penalty;
659 return disjunctions_[
index].value.max_cardinality;
667 std::vector<std::pair<int64_t, int64_t>> GetPerfectBinaryDisjunctions()
const;
673 void IgnoreDisjunctionsAlreadyForcedToZero();
678 void AddSoftSameVehicleConstraint(
const std::vector<int64_t>& indices,
685 void SetAllowedVehiclesForIndex(
const std::vector<int>& vehicles,
690 return allowed_vehicles_[
index].empty() ||
691 allowed_vehicles_[
index].find(vehicle) !=
692 allowed_vehicles_[
index].end();
710 void AddPickupAndDelivery(int64_t pickup, int64_t delivery);
714 void AddPickupAndDeliverySets(DisjunctionIndex pickup_disjunction,
715 DisjunctionIndex delivery_disjunction);
720 const std::vector<std::pair<int, int> >&
721 GetPickupIndexPairs(int64_t node_index)
const;
723 const std::vector<std::pair<int, int> >&
724 GetDeliveryIndexPairs(int64_t node_index)
const;
729 void SetPickupAndDeliveryPolicyOfAllVehicles(PickupAndDeliveryPolicy policy);
730 void SetPickupAndDeliveryPolicyOfVehicle(PickupAndDeliveryPolicy policy,
732 PickupAndDeliveryPolicy GetPickupAndDeliveryPolicyOfVehicle(
737 int GetNumOfSingletonNodes()
const;
742 return pickup_delivery_pairs_;
744 const std::vector<std::pair<DisjunctionIndex, DisjunctionIndex>>&
746 return pickup_delivery_disjunctions_;
754 return implicit_pickup_delivery_pairs_without_alternatives_;
768 enum VisitTypePolicy {
783 TYPE_SIMULTANEOUSLY_ADDED_AND_REMOVED
786 void SetVisitType(int64_t
index,
int type, VisitTypePolicy type_policy);
787 int GetVisitType(int64_t
index)
const;
788 const std::vector<int>& GetSingleNodesOfType(
int type)
const;
789 const std::vector<int>& GetPairIndicesOfType(
int type)
const;
790 VisitTypePolicy GetVisitTypePolicy(int64_t
index)
const;
795 void CloseVisitTypes();
801 return topologically_sorted_visit_types_;
808 void AddHardTypeIncompatibility(int type1, int type2);
809 void AddTemporalTypeIncompatibility(
int type1,
int type2);
811 const absl::flat_hash_set<int>& GetHardTypeIncompatibilitiesOfType(
813 const absl::flat_hash_set<int>& GetTemporalTypeIncompatibilitiesOfType(
818 return has_hard_type_incompatibilities_;
821 return has_temporal_type_incompatibilities_;
833 void AddSameVehicleRequiredTypeAlternatives(
834 int dependent_type, absl::flat_hash_set<int> required_type_alternatives);
839 void AddRequiredTypeAlternativesWhenAddingType(
840 int dependent_type, absl::flat_hash_set<int> required_type_alternatives);
846 void AddRequiredTypeAlternativesWhenRemovingType(
847 int dependent_type, absl::flat_hash_set<int> required_type_alternatives);
851 const std::vector<absl::flat_hash_set<int> >&
852 GetSameVehicleRequiredTypeAlternativesOfType(
int type)
const;
854 const std::vector<absl::flat_hash_set<int> >&
855 GetRequiredTypeAlternativesWhenAddingType(
int type)
const;
857 const std::vector<absl::flat_hash_set<int> >&
858 GetRequiredTypeAlternativesWhenRemovingType(
int type)
const;
863 return has_same_vehicle_type_requirements_;
866 return has_temporal_type_requirements_;
872 return HasTemporalTypeIncompatibilities() ||
873 HasHardTypeIncompatibilities() || HasSameVehicleTypeRequirements() ||
874 HasTemporalTypeRequirements();
881 int64_t UnperformedPenalty(int64_t var_index)
const;
885 int64_t UnperformedPenaltyOrValue(int64_t default_value,
886 int64_t var_index)
const;
890 int64_t GetDepot()
const;
897 max_active_vehicles_ = max_active_vehicles;
904 void SetArcCostEvaluatorOfAllVehicles(
int evaluator_index);
906 void SetArcCostEvaluatorOfVehicle(
int evaluator_index,
int vehicle);
909 void SetFixedCostOfAllVehicles(int64_t
cost);
911 void SetFixedCostOfVehicle(int64_t
cost,
int vehicle);
915 int64_t GetFixedCostOfVehicle(
int vehicle)
const;
932 void SetAmortizedCostFactorsOfAllVehicles(int64_t linear_cost_factor,
933 int64_t quadratic_cost_factor);
935 void SetAmortizedCostFactorsOfVehicle(int64_t linear_cost_factor,
936 int64_t quadratic_cost_factor,
940 return linear_cost_factor_of_vehicle_;
944 return quadratic_cost_factor_of_vehicle_;
949 consider_empty_route_costs_[vehicle] = consider_costs;
954 return consider_empty_route_costs_[vehicle];
961 return first_solution_evaluator_;
966 first_solution_evaluator_ = std::move(evaluator);
976 void AddAtSolutionCallback(std::function<
void()>
callback);
981 void AddVariableMinimizedByFinalizer(
IntVar*
var);
984 void AddVariableMaximizedByFinalizer(
IntVar*
var);
987 void AddWeightedVariableMinimizedByFinalizer(
IntVar*
var, int64_t
cost);
990 void AddVariableTargetToFinalizer(
IntVar*
var, int64_t target);
1000 void CloseModelWithParameters(
1001 const RoutingSearchParameters& search_parameters);
1017 const RoutingSearchParameters& search_parameters,
1018 std::vector<const Assignment*>* solutions =
nullptr);
1021 const Assignment* SolveFromAssignmentWithParameters(
1023 const RoutingSearchParameters& search_parameters,
1024 std::vector<const Assignment*>* solutions =
nullptr);
1027 const Assignment* SolveFromAssignmentsWithParameters(
1028 const std::vector<const Assignment*>& assignments,
1029 const RoutingSearchParameters& search_parameters,
1030 std::vector<const Assignment*>* solutions =
nullptr);
1036 void SetAssignmentFromOtherModelAssignment(
1045 int64_t ComputeLowerBound();
1056 IntVar* ApplyLocks(
const std::vector<int64_t>& locks);
1065 bool ApplyLocksToAllVehicles(
const std::vector<std::vector<int64_t>>& locks,
1076 bool WriteAssignment(
const std::string& file_name)
const;
1080 Assignment* ReadAssignment(
const std::string& file_name);
1090 const std::vector<std::vector<int64_t>>& routes,
1091 bool ignore_inactive_indices);
1108 bool RoutesToAssignment(
const std::vector<std::vector<int64_t>>& routes,
1109 bool ignore_inactive_indices,
bool close_routes,
1114 void AssignmentToRoutes(
1116 std::vector<std::vector<int64_t>>*
const routes)
const;
1122 std::vector<std::vector<int64_t>> GetRoutesFromAssignment(
1148 void AddToAssignment(
IntVar*
const var);
1160 const Assignment* PackCumulsOfOptimizerDimensionsFromAssignment(
1161 const Assignment* original_assignment, absl::Duration duration_limit);
1174 CHECK(filter !=
nullptr);
1176 LOG(
WARNING) <<
"Model is closed, filter addition will be ignored.";
1178 extra_filters_.push_back({filter, LocalSearchFilterManager::kRelax});
1179 extra_filters_.push_back({filter, LocalSearchFilterManager::kAccept});
1184 int64_t
Start(
int vehicle)
const {
return starts_[vehicle]; }
1186 int64_t
End(
int vehicle)
const {
return ends_[vehicle]; }
1188 bool IsStart(int64_t
index)
const;
1199 bool IsVehicleUsed(
const Assignment& assignment,
int vehicle)
const;
1201 #if !defined(SWIGPYTHON)
1204 const std::vector<IntVar*>&
Nexts()
const {
return nexts_; }
1207 const std::vector<IntVar*>&
VehicleVars()
const {
return vehicle_vars_; }
1217 return vehicle_active_[vehicle];
1222 return vehicle_costs_considered_[vehicle];
1232 int64_t GetArcCostForVehicle(int64_t from_index, int64_t to_index,
1233 int64_t vehicle)
const;
1236 return costs_are_homogeneous_across_vehicles_;
1241 return GetArcCostForVehicle(from_index, to_index, 0);
1245 int64_t GetArcCostForFirstSolution(int64_t from_index,
1246 int64_t to_index)
const;
1253 int64_t GetArcCostForClass(int64_t from_index, int64_t to_index,
1254 int64_t cost_class_index)
const;
1259 DCHECK_LT(vehicle, cost_class_index_of_vehicle_.size());
1260 DCHECK_GE(cost_class_index_of_vehicle_[vehicle], 0);
1261 return cost_class_index_of_vehicle_[vehicle];
1267 if (cost_class_index == kCostClassIndexOfZeroCost) {
1268 return has_vehicle_with_zero_cost_class_;
1270 return cost_class_index < cost_classes_.size();
1276 return std::max(0, GetCostClassesCount() - 1);
1280 return vehicle_class_index_of_vehicle_[vehicle];
1287 return same_vehicle_groups_[same_vehicle_group_[node]];
1292 return vehicle_type_container_;
1313 bool ArcIsMoreConstrainedThanArc(int64_t from, int64_t to1, int64_t to2);
1318 std::string DebugOutputAssignment(
1320 const std::string& dimension_to_print)
const;
1327 std::vector<std::vector<std::pair<int64_t, int64_t>>> GetCumulBounds(
1343 return limit_->AbsoluteSolverDeadline() - solver_->Now();
1352 int64_t
Size()
const {
return nodes_ + vehicles_ - start_end_count_; }
1356 int64_t GetNumberOfDecisionsInFirstSolution(
1357 const RoutingSearchParameters& search_parameters)
const;
1358 int64_t GetNumberOfRejectsInFirstSolution(
1359 const RoutingSearchParameters& search_parameters)
const;
1363 return automatic_first_solution_strategy_;
1367 bool IsMatchingModel()
const;
1373 std::function<std::vector<operations_research::IntVar*>(
RoutingModel*)>;
1393 std::function<int64_t(int64_t)> initializer);
1400 static std::unique_ptr<LocalSearchOperator> MakeGreedyDescentLSOperator(
1401 std::vector<IntVar*> variables);
1421 enum RoutingLocalSearchOperator {
1424 LIGHT_RELOCATE_PAIR,
1432 GLOBAL_CHEAPEST_INSERTION_CLOSE_NODES_LNS,
1433 LOCAL_CHEAPEST_INSERTION_CLOSE_NODES_LNS,
1434 GLOBAL_CHEAPEST_INSERTION_PATH_LNS,
1435 LOCAL_CHEAPEST_INSERTION_PATH_LNS,
1436 RELOCATE_PATH_GLOBAL_CHEAPEST_INSERTION_INSERT_UNPERFORMED,
1437 GLOBAL_CHEAPEST_INSERTION_EXPENSIVE_CHAIN_LNS,
1438 LOCAL_CHEAPEST_INSERTION_EXPENSIVE_CHAIN_LNS,
1439 RELOCATE_EXPENSIVE_CHAIN,
1443 RELOCATE_AND_MAKE_ACTIVE,
1444 MAKE_ACTIVE_AND_RELOCATE,
1446 MAKE_CHAIN_INACTIVE,
1448 EXTENDED_SWAP_ACTIVE,
1454 EXCHANGE_RELOCATE_PAIR,
1457 LOCAL_SEARCH_OPERATOR_COUNTER
1463 template <
typename T>
1464 struct ValuedNodes {
1465 std::vector<int64_t> indices;
1468 struct DisjunctionValues {
1470 int64_t max_cardinality;
1472 typedef ValuedNodes<DisjunctionValues> Disjunction;
1476 struct CostCacheElement {
1483 CostClassIndex cost_class_index;
1489 void AddNoCycleConstraintInternal();
1490 bool AddDimensionWithCapacityInternal(
1491 const std::vector<int>& evaluator_indices, int64_t slack_max,
1492 std::vector<int64_t> vehicle_capacities,
bool fix_start_cumul_to_zero,
1493 const std::string&
name);
1494 bool AddDimensionDependentDimensionWithVehicleCapacityInternal(
1495 const std::vector<int>& pure_transits,
1496 const std::vector<int>& dependent_transits,
1497 const RoutingDimension* base_dimension, int64_t slack_max,
1498 std::vector<int64_t> vehicle_capacities,
bool fix_start_cumul_to_zero,
1499 const std::string&
name);
1500 bool InitializeDimensionInternal(
1501 const std::vector<int>& evaluator_indices,
1502 const std::vector<int>& state_dependent_evaluator_indices,
1503 int64_t slack_max,
bool fix_start_cumul_to_zero,
1504 RoutingDimension* dimension);
1505 DimensionIndex GetDimensionIndex(
const std::string& dimension_name)
const;
1534 void StoreDimensionCumulOptimizers(
const RoutingSearchParameters&
parameters);
1536 void ComputeCostClasses(
const RoutingSearchParameters&
parameters);
1537 void ComputeVehicleClasses();
1545 void ComputeVehicleTypes();
1555 void FinalizeVisitTypes();
1557 void TopologicallySortVisitTypes();
1558 int64_t GetArcCostForClassInternal(int64_t from_index, int64_t to_index,
1559 CostClassIndex cost_class_index)
const;
1560 void AppendHomogeneousArcCosts(
const RoutingSearchParameters&
parameters,
1562 std::vector<IntVar*>* cost_elements);
1563 void AppendArcCosts(
const RoutingSearchParameters&
parameters,
int node_index,
1564 std::vector<IntVar*>* cost_elements);
1565 Assignment* DoRestoreAssignment();
1566 static const CostClassIndex kCostClassIndexOfZeroCost;
1567 int64_t SafeGetCostClassInt64OfVehicle(int64_t vehicle)
const {
1569 return (vehicle >= 0 ? GetCostClassIndexOfVehicle(vehicle)
1570 : kCostClassIndexOfZeroCost)
1573 int64_t GetDimensionTransitCostSum(int64_t i, int64_t j,
1574 const CostClass& cost_class)
const;
1576 IntVar* CreateDisjunction(DisjunctionIndex disjunction);
1578 void AddPickupAndDeliverySetsInternal(
const std::vector<int64_t>& pickups,
1579 const std::vector<int64_t>& deliveries);
1582 IntVar* CreateSameVehicleCost(
int vehicle_index);
1585 int FindNextActive(
int index,
const std::vector<int64_t>& indices)
const;
1589 bool RouteCanBeUsedByVehicle(
const Assignment& assignment,
int start_index,
1598 bool ReplaceUnusedVehicle(
int unused_vehicle,
int active_vehicle,
1599 Assignment* compact_assignment)
const;
1601 void QuietCloseModel();
1602 void QuietCloseModelWithParameters(
1610 bool SolveMatchingModel(Assignment* assignment,
1614 bool AppendAssignmentIfFeasible(
1615 const Assignment& assignment,
1616 std::vector<std::unique_ptr<Assignment>>* assignments);
1619 void LogSolution(
const RoutingSearchParameters&
parameters,
1620 const std::string& description, int64_t solution_cost,
1621 int64_t start_time_ms);
1624 Assignment* CompactAssignmentInternal(
const Assignment& assignment,
1625 bool check_compact_assignment)
const;
1630 std::string FindErrorInSearchParametersForModel(
1631 const RoutingSearchParameters& search_parameters)
const;
1633 void SetupSearch(
const RoutingSearchParameters& search_parameters);
1636 Assignment* GetOrCreateAssignment();
1637 Assignment* GetOrCreateTmpAssignment();
1638 RegularLimit* GetOrCreateLimit();
1639 RegularLimit* GetOrCreateLocalSearchLimit();
1640 RegularLimit* GetOrCreateLargeNeighborhoodSearchLimit();
1641 RegularLimit* GetOrCreateFirstSolutionLargeNeighborhoodSearchLimit();
1642 LocalSearchOperator* CreateInsertionOperator();
1643 LocalSearchOperator* CreateMakeInactiveOperator();
1645 LocalSearchOperator* CreateCPOperator(
const T& operator_factory) {
1646 return operator_factory(solver_.get(), nexts_,
1647 CostsAreHomogeneousAcrossVehicles()
1648 ? std::vector<IntVar*>()
1650 vehicle_start_class_callback_);
1653 LocalSearchOperator* CreateCPOperator() {
1654 return CreateCPOperator(absl::bind_front(MakeLocalSearchOperator<T>));
1656 template <
class T,
class Arg>
1657 LocalSearchOperator* CreateOperator(
const Arg& arg) {
1658 return solver_->RevAlloc(
new T(nexts_,
1659 CostsAreHomogeneousAcrossVehicles()
1660 ? std::vector<IntVar*>()
1662 vehicle_start_class_callback_, arg));
1665 LocalSearchOperator* CreatePairOperator() {
1666 return CreateOperator<T>(pickup_delivery_pairs_);
1668 void CreateNeighborhoodOperators(
const RoutingSearchParameters&
parameters);
1669 LocalSearchOperator* ConcatenateOperators(
1670 const RoutingSearchParameters& search_parameters,
1671 const std::vector<LocalSearchOperator*>& operators)
const;
1672 LocalSearchOperator* GetNeighborhoodOperators(
1673 const RoutingSearchParameters& search_parameters)
const;
1674 std::vector<LocalSearchFilterManager::FilterEvent>
1675 GetOrCreateLocalSearchFilters(
const RoutingSearchParameters&
parameters,
1676 bool filter_cost =
true);
1677 LocalSearchFilterManager* GetOrCreateLocalSearchFilterManager(
1679 std::vector<LocalSearchFilterManager::FilterEvent>
1680 GetOrCreateFeasibilityFilters(
const RoutingSearchParameters&
parameters);
1681 LocalSearchFilterManager* GetOrCreateFeasibilityFilterManager(
1683 LocalSearchFilterManager* GetOrCreateStrongFeasibilityFilterManager(
1685 DecisionBuilder* CreateSolutionFinalizer(SearchLimit* lns_limit);
1686 DecisionBuilder* CreateFinalizerForMinimizedAndMaximizedVariables();
1687 void CreateFirstSolutionDecisionBuilders(
1688 const RoutingSearchParameters& search_parameters);
1689 DecisionBuilder* GetFirstSolutionDecisionBuilder(
1690 const RoutingSearchParameters& search_parameters)
const;
1691 IntVarFilteredDecisionBuilder* GetFilteredFirstSolutionDecisionBuilderOrNull(
1692 const RoutingSearchParameters&
parameters)
const;
1693 LocalSearchPhaseParameters* CreateLocalSearchParameters(
1694 const RoutingSearchParameters& search_parameters);
1695 DecisionBuilder* CreateLocalSearchDecisionBuilder(
1696 const RoutingSearchParameters& search_parameters);
1697 void SetupDecisionBuilders(
const RoutingSearchParameters& search_parameters);
1698 void SetupMetaheuristics(
const RoutingSearchParameters& search_parameters);
1699 void SetupAssignmentCollector(
1700 const RoutingSearchParameters& search_parameters);
1701 void SetupTrace(
const RoutingSearchParameters& search_parameters);
1702 void SetupImprovementLimit(
const RoutingSearchParameters& search_parameters);
1703 void SetupSearchMonitors(
const RoutingSearchParameters& search_parameters);
1704 bool UsesLightPropagation(
1705 const RoutingSearchParameters& search_parameters)
const;
1706 GetTabuVarsCallback tabu_var_callback_;
1712 void DetectImplicitPickupAndDeliveries();
1714 int GetVehicleStartClass(int64_t start)
const;
1716 void InitSameVehicleGroups(
int number_of_groups) {
1717 same_vehicle_group_.assign(Size(), 0);
1718 same_vehicle_groups_.assign(number_of_groups, {});
1720 void SetSameVehicleGroup(
int index,
int group) {
1721 same_vehicle_group_[
index] = group;
1722 same_vehicle_groups_[group].push_back(
index);
1726 std::unique_ptr<Solver> solver_;
1729 int max_active_vehicles_;
1730 Constraint* no_cycle_constraint_ =
nullptr;
1732 std::vector<IntVar*> nexts_;
1733 std::vector<IntVar*> vehicle_vars_;
1734 std::vector<IntVar*> active_;
1736 std::vector<IntVar*> vehicle_active_;
1737 std::vector<IntVar*> vehicle_costs_considered_;
1742 std::vector<IntVar*> is_bound_to_end_;
1743 mutable RevSwitch is_bound_to_end_ct_added_;
1745 absl::flat_hash_map<std::string, DimensionIndex> dimension_name_to_index_;
1751 std::vector<std::unique_ptr<GlobalDimensionCumulOptimizer> >
1752 global_dimension_optimizers_;
1754 std::vector<std::unique_ptr<LocalDimensionCumulOptimizer> >
1755 local_dimension_optimizers_;
1756 std::vector<std::unique_ptr<LocalDimensionCumulOptimizer> >
1757 local_dimension_mp_optimizers_;
1760 std::string primary_constrained_dimension_;
1762 IntVar* cost_ =
nullptr;
1763 std::vector<int> vehicle_to_transit_cost_;
1764 std::vector<int64_t> fixed_cost_of_vehicle_;
1765 std::vector<CostClassIndex> cost_class_index_of_vehicle_;
1766 bool has_vehicle_with_zero_cost_class_;
1767 std::vector<int64_t> linear_cost_factor_of_vehicle_;
1768 std::vector<int64_t> quadratic_cost_factor_of_vehicle_;
1769 bool vehicle_amortized_cost_factors_set_;
1780 std::vector<bool> consider_empty_route_costs_;
1784 bool costs_are_homogeneous_across_vehicles_;
1785 bool cache_callbacks_;
1786 mutable std::vector<CostCacheElement> cost_cache_;
1787 std::vector<VehicleClassIndex> vehicle_class_index_of_vehicle_;
1791 VehicleTypeContainer vehicle_type_container_;
1792 std::function<int(int64_t)> vehicle_start_class_callback_;
1795 std::vector<std::vector<DisjunctionIndex> > index_to_disjunctions_;
1797 std::vector<ValuedNodes<int64_t> > same_vehicle_costs_;
1800 std::vector<absl::flat_hash_set<int>> allowed_vehicles_;
1803 IndexPairs pickup_delivery_pairs_;
1804 IndexPairs implicit_pickup_delivery_pairs_without_alternatives_;
1805 std::vector<std::pair<DisjunctionIndex, DisjunctionIndex> >
1806 pickup_delivery_disjunctions_;
1811 std::vector<std::vector<std::pair<int, int> > > index_to_pickup_index_pairs_;
1813 std::vector<std::vector<std::pair<int, int> > >
1814 index_to_delivery_index_pairs_;
1816 std::vector<PickupAndDeliveryPolicy> vehicle_pickup_delivery_policy_;
1818 std::vector<int> same_vehicle_group_;
1820 std::vector<std::vector<int>> same_vehicle_groups_;
1823 std::vector<int> index_to_visit_type_;
1825 std::vector<VisitTypePolicy> index_to_type_policy_;
1827 std::vector<std::vector<int> > single_nodes_of_type_;
1828 std::vector<std::vector<int> > pair_indices_of_type_;
1830 std::vector<absl::flat_hash_set<int> >
1831 hard_incompatible_types_per_type_index_;
1832 bool has_hard_type_incompatibilities_;
1833 std::vector<absl::flat_hash_set<int> >
1834 temporal_incompatible_types_per_type_index_;
1835 bool has_temporal_type_incompatibilities_;
1837 std::vector<std::vector<absl::flat_hash_set<int> > >
1838 same_vehicle_required_type_alternatives_per_type_index_;
1839 bool has_same_vehicle_type_requirements_;
1840 std::vector<std::vector<absl::flat_hash_set<int> > >
1841 required_type_alternatives_when_adding_type_index_;
1842 std::vector<std::vector<absl::flat_hash_set<int> > >
1843 required_type_alternatives_when_removing_type_index_;
1844 bool has_temporal_type_requirements_;
1845 absl::flat_hash_map<int, absl::flat_hash_set<VisitTypePolicy> >
1846 trivially_infeasible_visit_types_to_policies_;
1863 std::vector<std::vector<int> > topologically_sorted_visit_types_;
1865 int num_visit_types_;
1868 std::vector<int> index_to_equivalence_class_;
1869 std::vector<int> index_to_vehicle_;
1870 std::vector<int64_t> starts_;
1871 std::vector<int64_t> ends_;
1874 RoutingIndexManager manager_;
1875 int start_end_count_;
1877 bool closed_ =
false;
1878 Status status_ = ROUTING_NOT_SOLVED;
1879 bool enable_deep_serialization_ =
true;
1882 std::vector<DecisionBuilder*> first_solution_decision_builders_;
1883 std::vector<IntVarFilteredDecisionBuilder*>
1884 first_solution_filtered_decision_builders_;
1885 Solver::IndexEvaluator2 first_solution_evaluator_;
1887 FirstSolutionStrategy::UNSET;
1888 std::vector<LocalSearchOperator*> local_search_operators_;
1889 std::vector<SearchMonitor*> monitors_;
1890 SolutionCollector* collect_assignments_ =
nullptr;
1891 SolutionCollector* collect_one_assignment_ =
nullptr;
1892 SolutionCollector* packed_dimensions_assignment_collector_ =
nullptr;
1893 DecisionBuilder* solve_db_ =
nullptr;
1894 DecisionBuilder* improve_db_ =
nullptr;
1895 DecisionBuilder* restore_assignment_ =
nullptr;
1896 DecisionBuilder* restore_tmp_assignment_ =
nullptr;
1897 Assignment* assignment_ =
nullptr;
1898 Assignment* preassignment_ =
nullptr;
1899 Assignment* tmp_assignment_ =
nullptr;
1900 std::vector<IntVar*> extra_vars_;
1901 std::vector<IntervalVar*> extra_intervals_;
1902 std::vector<LocalSearchOperator*> extra_operators_;
1903 LocalSearchFilterManager* local_search_filter_manager_ =
nullptr;
1904 LocalSearchFilterManager* feasibility_filter_manager_ =
nullptr;
1905 LocalSearchFilterManager* strong_feasibility_filter_manager_ =
nullptr;
1906 std::vector<LocalSearchFilterManager::FilterEvent> extra_filters_;
1908 std::vector<std::pair<IntVar*, int64_t>> finalizer_variable_cost_pairs_;
1909 std::vector<std::pair<IntVar*, int64_t>> finalizer_variable_target_pairs_;
1910 absl::flat_hash_map<IntVar*, int> finalizer_variable_cost_index_;
1911 absl::flat_hash_set<IntVar*> finalizer_variable_target_set_;
1912 std::unique_ptr<SweepArranger> sweep_arranger_;
1915 RegularLimit*
limit_ =
nullptr;
1916 RegularLimit* ls_limit_ =
nullptr;
1917 RegularLimit* lns_limit_ =
nullptr;
1918 RegularLimit* first_solution_lns_limit_ =
nullptr;
1920 typedef std::pair<int64_t, int64_t> CacheKey;
1921 typedef absl::flat_hash_map<CacheKey, int64_t> TransitCallbackCache;
1922 typedef absl::flat_hash_map<CacheKey, StateDependentTransit>
1923 StateDependentTransitCallbackCache;
1925 std::vector<TransitCallback1> unary_transit_evaluators_;
1926 std::vector<TransitCallback2> transit_evaluators_;
1937 std::vector<bool> is_transit_evaluator_positive_;
1938 std::vector<VariableIndexEvaluator2> state_dependent_transit_evaluators_;
1939 std::vector<std::unique_ptr<StateDependentTransitCallbackCache>>
1940 state_dependent_transit_evaluators_cache_;
1952 static const char kLightElement[];
1953 static const char kLightElement2[];
1954 static const char kRemoveValues[];
1968 int num_chain_tasks = 0;
1978 int64_t span_min = 0;
1984 duration_min.clear();
1985 duration_max.clear();
1988 is_preemptible.clear();
1989 forbidden_intervals.clear();
1990 distance_duration.clear();
1993 num_chain_tasks = 0;
1999 bool Propagate(Tasks* tasks);
2002 bool Precedences(Tasks* tasks);
2005 bool MirrorTasks(Tasks* tasks);
2007 bool EdgeFinding(Tasks* tasks);
2010 bool DetectablePrecedencesWithChain(Tasks* tasks);
2012 bool ForbiddenIntervals(Tasks* tasks);
2014 bool DistanceDuration(Tasks* tasks);
2017 bool ChainSpanMin(Tasks* tasks);
2022 bool ChainSpanMinDynamic(Tasks* tasks);
2029 std::vector<int> tasks_by_start_min_;
2030 std::vector<int> tasks_by_end_max_;
2031 std::vector<int> event_of_task_;
2032 std::vector<int> nonchain_tasks_by_start_max_;
2034 std::vector<int64_t> total_duration_before_;
2052 std::vector<int64_t>* values);
2072 return "GlobalVehicleBreaksConstraint";
2075 void Post()
override;
2076 void InitialPropagate()
override;
2079 void PropagateNode(
int node);
2080 void PropagateVehicle(
int vehicle);
2081 void PropagateMaxBreakDistance(
int vehicle);
2085 std::vector<Demon*> vehicle_demons_;
2086 std::vector<int64_t> path_;
2092 void FillPartialPathOfVehicle(
int vehicle);
2093 void FillPathTravels(
const std::vector<int64_t>& path);
2105 class TaskTranslator {
2107 TaskTranslator(
IntVar* start, int64_t before_start, int64_t after_start)
2109 before_start_(before_start),
2110 after_start_(after_start) {}
2114 void SetStartMin(int64_t
value) {
2115 if (start_ !=
nullptr) {
2117 }
else if (interval_ !=
nullptr) {
2118 interval_->SetStartMin(
value);
2121 void SetStartMax(int64_t
value) {
2122 if (start_ !=
nullptr) {
2124 }
else if (interval_ !=
nullptr) {
2125 interval_->SetStartMax(
value);
2128 void SetDurationMin(int64_t
value) {
2129 if (interval_ !=
nullptr) {
2130 interval_->SetDurationMin(
value);
2133 void SetEndMin(int64_t
value) {
2134 if (start_ !=
nullptr) {
2136 }
else if (interval_ !=
nullptr) {
2137 interval_->SetEndMin(
value);
2140 void SetEndMax(int64_t
value) {
2141 if (start_ !=
nullptr) {
2143 }
else if (interval_ !=
nullptr) {
2144 interval_->SetEndMax(
value);
2149 IntVar* start_ =
nullptr;
2150 int64_t before_start_;
2151 int64_t after_start_;
2152 IntervalVar* interval_ =
nullptr;
2156 std::vector<TaskTranslator> task_translators_;
2159 DisjunctivePropagator disjunctive_propagator_;
2160 DisjunctivePropagator::Tasks tasks_;
2163 TravelBounds travel_bounds_;
2171 bool CheckVehicle(
int vehicle,
2172 const std::function<int64_t(int64_t)>& next_accessor);
2183 int num_type_added_to_vehicle = 0;
2189 int num_type_removed_from_vehicle = 0;
2194 int position_of_last_type_on_vehicle_up_to_visit = -1;
2201 bool TypeOccursOnRoute(
int type)
const;
2208 bool TypeCurrentlyOnRoute(
int type,
int pos)
const;
2210 void InitializeCheck(
int vehicle,
2211 const std::function<int64_t(int64_t)>& next_accessor);
2221 std::vector<TypePolicyOccurrence> occurrences_of_type_;
2222 std::vector<int64_t> current_route_visits_;
2229 bool check_hard_incompatibilities);
2233 bool HasRegulationsToCheck()
const override;
2234 bool CheckTypeRegulations(
int type, VisitTypePolicy policy,
int pos)
override;
2238 bool check_hard_incompatibilities_;
2249 bool HasRegulationsToCheck()
const override;
2250 void OnInitializeCheck()
override {
2251 types_with_same_vehicle_requirements_on_route_.clear();
2256 bool CheckRequiredTypesCurrentlyOnRoute(
2257 const std::vector<absl::flat_hash_set<int> >& required_type_alternatives,
2260 bool CheckTypeRegulations(
int type, VisitTypePolicy policy,
int pos)
override;
2261 bool FinalizeCheck()
const override;
2263 absl::flat_hash_set<int> types_with_same_vehicle_requirements_on_route_;
2310 void Post()
override;
2311 void InitialPropagate()
override;
2314 void PropagateNodeRegulations(
int node);
2315 void CheckRegulationsOnVehicle(
int vehicle);
2320 std::vector<Demon*> vehicle_demons_;
2342 : bound_costs_(num_bounds, default_bound_cost) {}
2345 int Size() {
return bound_costs_.size(); }
2350 std::vector<BoundCost> bound_costs_;
2382 int64_t GetTransitValue(int64_t from_index, int64_t to_index,
2383 int64_t vehicle)
const;
2388 return model_->TransitCallback(class_evaluators_[
vehicle_class])(from_index,
2396 return fixed_transits_[
index];
2400 #if !defined(SWIGPYTHON)
2405 const std::vector<IntVar*>&
transits()
const {
return transits_; }
2406 const std::vector<IntVar*>&
slacks()
const {
return slacks_; }
2407 #if !defined(SWIGCSHARP) && !defined(SWIGJAVA)
2410 return forbidden_intervals_;
2414 int64_t
index, int64_t min_value, int64_t max_value)
const;
2418 int64_t min_value)
const {
2421 forbidden_intervals_[
index];
2422 const auto first_forbidden_interval_it =
2424 if (first_forbidden_interval_it != forbidden_intervals.
end() &&
2425 min_value >= first_forbidden_interval_it->start) {
2427 return CapAdd(first_forbidden_interval_it->end, 1);
2437 int64_t max_value)
const {
2440 forbidden_intervals_[
index];
2441 const auto last_forbidden_interval_it =
2443 if (last_forbidden_interval_it != forbidden_intervals.
end() &&
2444 max_value <= last_forbidden_interval_it->end) {
2446 return CapSub(last_forbidden_interval_it->start, 1);
2453 return vehicle_capacities_;
2458 return model_->TransitCallback(
2459 class_evaluators_[vehicle_to_class_[vehicle]]);
2465 int vehicle)
const {
2466 return model_->UnaryTransitCallbackOrNull(
2467 class_evaluators_[vehicle_to_class_[vehicle]]);
2472 return model()->is_transit_evaluator_positive_
2473 [class_evaluators_[vehicle_to_class_[vehicle]]];
2481 void SetSpanUpperBoundForVehicle(int64_t
upper_bound,
int vehicle);
2488 void SetSpanCostCoefficientForVehicle(int64_t
coefficient,
int vehicle);
2489 void SetSpanCostCoefficientForAllVehicles(int64_t
coefficient);
2496 void SetGlobalSpanCostCoefficient(int64_t
coefficient);
2503 void SetCumulVarPiecewiseLinearCost(int64_t
index,
2507 bool HasCumulVarPiecewiseLinearCost(int64_t
index)
const;
2511 int64_t
index)
const;
2526 bool HasCumulVarSoftUpperBound(int64_t
index)
const;
2530 int64_t GetCumulVarSoftUpperBound(int64_t
index)
const;
2534 int64_t GetCumulVarSoftUpperBoundCoefficient(int64_t
index)
const;
2549 bool HasCumulVarSoftLowerBound(int64_t
index)
const;
2553 int64_t GetCumulVarSoftLowerBound(int64_t
index)
const;
2557 int64_t GetCumulVarSoftLowerBoundCoefficient(int64_t
index)
const;
2574 #if !defined(SWIGPYTHON)
2575 void SetBreakIntervalsOfVehicle(std::vector<IntervalVar*> breaks,
int vehicle,
2576 int pre_travel_evaluator,
2577 int post_travel_evaluator);
2581 void SetBreakIntervalsOfVehicle(std::vector<IntervalVar*> breaks,
int vehicle,
2582 std::vector<int64_t> node_visit_transits);
2588 void SetBreakDistanceDurationOfVehicle(int64_t
distance, int64_t duration,
2592 void InitializeBreaks();
2594 bool HasBreakConstraints()
const;
2595 #if !defined(SWIGPYTHON)
2598 void SetBreakIntervalsOfVehicle(
2599 std::vector<IntervalVar*> breaks,
int vehicle,
2600 std::vector<int64_t> node_visit_transits,
2601 std::function<int64_t(int64_t, int64_t)> delays);
2604 const std::vector<IntervalVar*>& GetBreakIntervalsOfVehicle(
2609 const std::vector<std::pair<int64_t, int64_t> >&
2610 GetBreakDistanceDurationOfVehicle(
int vehicle)
const;
2613 int GetPreTravelEvaluatorOfVehicle(
int vehicle)
const;
2614 int GetPostTravelEvaluatorOfVehicle(
int vehicle)
const;
2625 int64_t ShortestTransitionSlack(int64_t node)
const;
2628 const std::string&
name()
const {
return name_; }
2633 return path_precedence_graph_;
2648 void SetPickupToDeliveryLimitFunctionForPair(
2651 bool HasPickupToDeliveryLimits()
const;
2653 int64_t GetPickupToDeliveryLimitForPair(
int pair_index,
int pickup,
2654 int delivery)
const;
2663 node_precedences_.push_back(precedence);
2666 return node_precedences_;
2672 AddNodePrecedence({first_node, second_node, offset});
2676 return vehicle_span_upper_bounds_[vehicle];
2680 return vehicle_span_upper_bounds_;
2684 return vehicle_span_cost_coefficients_[vehicle];
2688 return vehicle_span_cost_coefficients_;
2692 return global_span_cost_coefficient_;
2697 return global_optimizer_offset_;
2700 if (vehicle >= local_optimizer_offset_for_vehicle_.size()) {
2703 DCHECK_GE(local_optimizer_offset_for_vehicle_[vehicle], 0);
2704 return local_optimizer_offset_for_vehicle_[vehicle];
2711 if (!HasSoftSpanUpperBounds()) {
2712 vehicle_soft_span_upper_bound_ = absl::make_unique<SimpleBoundCosts>(
2715 vehicle_soft_span_upper_bound_->bound_cost(vehicle) = bound_cost;
2718 return vehicle_soft_span_upper_bound_ !=
nullptr;
2721 int vehicle)
const {
2722 DCHECK(HasSoftSpanUpperBounds());
2723 return vehicle_soft_span_upper_bound_->bound_cost(vehicle);
2729 if (!HasQuadraticCostSoftSpanUpperBounds()) {
2730 vehicle_quadratic_cost_soft_span_upper_bound_ =
2731 absl::make_unique<SimpleBoundCosts>(
2734 vehicle_quadratic_cost_soft_span_upper_bound_->bound_cost(vehicle) =
2738 return vehicle_quadratic_cost_soft_span_upper_bound_ !=
nullptr;
2741 int vehicle)
const {
2742 DCHECK(HasQuadraticCostSoftSpanUpperBounds());
2743 return vehicle_quadratic_cost_soft_span_upper_bound_->bound_cost(vehicle);
2754 struct PiecewiseLinearCost {
2755 PiecewiseLinearCost() :
var(nullptr),
cost(nullptr) {}
2757 std::unique_ptr<PiecewiseLinearFunction>
cost;
2761 RoutingDimension(RoutingModel*
model, std::vector<int64_t> vehicle_capacities,
2762 const std::string&
name,
2763 const RoutingDimension* base_dimension);
2764 RoutingDimension(RoutingModel*
model, std::vector<int64_t> vehicle_capacities,
2765 const std::string&
name, SelfBased);
2766 void Initialize(
const std::vector<int>& transit_evaluators,
2767 const std::vector<int>& state_dependent_transit_evaluators,
2769 void InitializeCumuls();
2770 void InitializeTransits(
2771 const std::vector<int>& transit_evaluators,
2772 const std::vector<int>& state_dependent_transit_evaluators,
2774 void InitializeTransitVariables(int64_t slack_max);
2776 void SetupCumulVarSoftUpperBoundCosts(
2777 std::vector<IntVar*>* cost_elements)
const;
2779 void SetupCumulVarSoftLowerBoundCosts(
2780 std::vector<IntVar*>* cost_elements)
const;
2781 void SetupCumulVarPiecewiseLinearCosts(
2782 std::vector<IntVar*>* cost_elements)
const;
2785 void SetupGlobalSpanCost(std::vector<IntVar*>* cost_elements)
const;
2786 void SetupSlackAndDependentTransitCosts()
const;
2788 void CloseModel(
bool use_light_propagation);
2790 void SetOffsetForGlobalOptimizer(int64_t offset) {
2794 void SetVehicleOffsetsForLocalOptimizer(std::vector<int64_t> offsets) {
2796 std::transform(offsets.begin(), offsets.end(), offsets.begin(),
2797 [](int64_t offset) { return std::max(Zero(), offset); });
2798 local_optimizer_offset_for_vehicle_ = std::move(offsets);
2802 std::vector<SortedDisjointIntervalList> forbidden_intervals_;
2803 std::vector<IntVar*> capacity_vars_;
2804 const std::vector<int64_t> vehicle_capacities_;
2805 std::vector<IntVar*> transits_;
2806 std::vector<IntVar*> fixed_transits_;
2809 std::vector<int> class_evaluators_;
2810 std::vector<int64_t> vehicle_to_class_;
2812 ReverseArcListGraph<int, int> path_precedence_graph_;
2818 std::vector<NodePrecedence> node_precedences_;
2823 const RoutingDimension*
const base_dimension_;
2828 std::vector<int> state_dependent_class_evaluators_;
2829 std::vector<int64_t> state_dependent_vehicle_to_class_;
2834 std::vector<PickupToDeliveryLimitFunction>
2835 pickup_to_delivery_limits_per_pair_index_;
2838 bool break_constraints_are_initialized_ =
false;
2840 std::vector<std::vector<IntervalVar*> > vehicle_break_intervals_;
2841 std::vector<std::vector<std::pair<int64_t, int64_t> > >
2842 vehicle_break_distance_duration_;
2847 std::vector<int> vehicle_pre_travel_evaluators_;
2848 std::vector<int> vehicle_post_travel_evaluators_;
2850 std::vector<IntVar*> slacks_;
2851 std::vector<IntVar*> dependent_transits_;
2852 std::vector<int64_t> vehicle_span_upper_bounds_;
2853 int64_t global_span_cost_coefficient_;
2854 std::vector<int64_t> vehicle_span_cost_coefficients_;
2855 std::vector<SoftBound> cumul_var_soft_upper_bound_;
2856 std::vector<SoftBound> cumul_var_soft_lower_bound_;
2857 std::vector<PiecewiseLinearCost> cumul_var_piecewise_linear_cost_;
2858 RoutingModel*
const model_;
2859 const std::string name_;
2860 int64_t global_optimizer_offset_;
2861 std::vector<int64_t> local_optimizer_offset_for_vehicle_;
2863 std::unique_ptr<SimpleBoundCosts> vehicle_soft_span_upper_bound_;
2864 std::unique_ptr<SimpleBoundCosts>
2865 vehicle_quadratic_cost_soft_span_upper_bound_;
2869 const std::vector<RoutingDimension*>& dimensions,
2870 const RoutingSearchParameters&
parameters,
bool filter_objective_cost,
2871 std::vector<LocalSearchFilterManager::FilterEvent>* filters);
2879 std::vector<IntVar*> variables,
2880 std::vector<int64_t> targets);
2887 const RoutingSearchParameters& search_parameters,
#define CHECK_LT(val1, val2)
#define DCHECK_GE(val1, val2)
#define DCHECK_LT(val1, val2)
#define DCHECK(condition)
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...
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 SetQuadraticCostSoftSpanUpperBoundForVehicle(SimpleBoundCosts::BoundCost bound_cost, int vehicle)
If the span of vehicle on this dimension is larger than bound, the cost will be increased by cost * (...
SimpleBoundCosts::BoundCost GetSoftSpanUpperBoundForVehicle(int vehicle) const
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
void SetSoftSpanUpperBoundForVehicle(SimpleBoundCosts::BoundCost bound_cost, int vehicle)
If the span of vehicle on this dimension is larger than bound, the cost will be increased by cost * (...
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.
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 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...
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
SimpleBoundCosts::BoundCost GetQuadraticCostSoftSpanUpperBoundForVehicle(int vehicle) const
const std::vector< SortedDisjointIntervalList > & forbidden_intervals() const
Returns forbidden intervals for each node.
Manager for any NodeIndex <-> variable index conversion.
const std::vector< std::pair< DisjunctionIndex, DisjunctionIndex > > & GetPickupAndDeliveryDisjunctions() const
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.
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.
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
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
int GetNumberOfVisitTypes() 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; ...
Assignment * MutablePreAssignment()
IntVar * ActiveVar(int64_t index) const
Returns the active variable of the node corresponding to index.
bool CheckLimit()
Returns true if the search limit has been crossed.
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)
const std::vector< int64_t > & GetAmortizedQuadraticCostFactorOfVehicles() const
const std::vector< std::unique_ptr< LocalDimensionCumulOptimizer > > & GetLocalDimensionCumulOptimizers() 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...
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.
LocalDimensionCumulOptimizer * GetMutableLocalCumulOptimizer(const RoutingDimension &dimension) const
int RegisterUnaryTransitVector(std::vector< int64_t > values)
Registers 'callback' and returns its index.
void AddLocalSearchFilter(LocalSearchFilter *filter)
Adds a custom local search filter to the list of filters used to speed up local search by pruning unf...
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 Solver::IndexEvaluator2 & first_solution_evaluator() const
Gets/sets the evaluator used during the search.
Status
Status of the search.
@ 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_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.
const std::vector< int64_t > & GetDisjunctionIndices(DisjunctionIndex index) const
Returns the variable indices of the nodes in the disjunction of index 'index'.
std::vector< RoutingDimension * > GetDimensionsWithSoftOrSpanCosts() const
Returns dimensions with soft or vehicle span costs.
RoutingIndexPairs IndexPairs
IntVar * VehicleCostsConsideredVar(int vehicle) const
Returns the variable specifying whether or not costs are considered for vehicle.
void ConsiderEmptyRouteCostsForVehicle(bool consider_costs, int vehicle)
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...
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.
int RegisterTransitCallback(TransitCallback2 callback)
const std::vector< std::unique_ptr< LocalDimensionCumulOptimizer > > & GetLocalDimensionCumulMPOptimizers() const
int GetMaximumNumberOfActiveVehicles() const
Returns the maximum number of active vehicles.
RoutingDimensionIndex DimensionIndex
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.
GlobalDimensionCumulOptimizer * GetMutableGlobalCumulOptimizer(const RoutingDimension &dimension) const
Returns the global/local dimension cumul optimizer for a given dimension, or nullptr if there is none...
bool AddDimensionWithVehicleCapacity(int evaluator_index, int64_t slack_max, std::vector< int64_t > vehicle_capacities, bool fix_start_cumul_to_zero, const std::string &name)
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
const std::vector< std::unique_ptr< GlobalDimensionCumulOptimizer > > & GetGlobalDimensionCumulOptimizers() const
Returns [global|local]_dimension_optimizers_, which are empty if the model has not been closed.
operations_research::FirstSolutionStrategy::Value GetAutomaticFirstSolutionStrategy() const
Returns the automatic first solution strategy selected.
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...
const Assignment *const PreAssignment() const
Returns an assignment used to fix some of the variables of the problem.
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...
bool AreEmptyRouteCostsConsideredForVehicle(int vehicle) const
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.
A structure meant to store soft bounds and associated violation constants.
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 by their distance and their angles from the depot.
Checker for type incompatibilities.
~TypeIncompatibilityChecker() override
virtual bool HasRegulationsToCheck() const =0
virtual ~TypeRegulationsChecker()
virtual bool CheckTypeRegulations(int type, VisitTypePolicy policy, int pos)=0
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
TypeRequirementChecker(const RoutingModel &model)
const std::vector< IntVar * > cumuls_
static const int64_t kint64max
#define DISALLOW_COPY_AND_ASSIGN(TypeName)
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.
CpSolverResponse Solve(const CpModelProto &model_proto)
Solves the given CpModelProto and returns an instance of CpSolverResponse.
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.
void AppendDimensionCumulFilters(const std::vector< RoutingDimension * > &dimensions, const RoutingSearchParameters ¶meters, bool filter_objective_cost, std::vector< LocalSearchFilterManager::FilterEvent > *filters)
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 * 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)
std::vector< RoutingIndexPair > RoutingIndexPairs
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
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
uint64_t unvisitable_nodes_fprint
Fingerprint of unvisitable non-start/end nodes.
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