157 #ifndef OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_H_
158 #define OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_H_
162 #include <functional>
169 #include "absl/container/flat_hash_map.h"
170 #include "absl/container/flat_hash_set.h"
171 #include "absl/functional/bind_front.h"
172 #include "absl/hash/hash.h"
173 #include "absl/time/time.h"
198 class GlobalDimensionCumulOptimizer;
199 class LocalDimensionCumulOptimizer;
200 class LocalSearchOperator;
202 class IntVarFilteredDecisionBuilder;
203 class IntVarFilteredHeuristic;
204 class IndexNeighborFinder;
206 class RoutingDimension;
308 std::vector<DimensionCost>
316 if (
a.evaluator_index !=
b.evaluator_index) {
317 return a.evaluator_index <
b.evaluator_index;
319 return a.dimension_transit_evaluator_class_and_cost_coefficient <
320 b.dimension_transit_evaluator_class_and_cost_coefficient;
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 slack_max,
450 std::vector<int64> vehicle_capacities,
451 bool fix_start_cumul_to_zero,
452 const std::string&
name);
454 const std::vector<int>& evaluator_indices,
int64 slack_max,
455 std::vector<int64> vehicle_capacities,
bool fix_start_cumul_to_zero,
456 const std::string&
name);
465 bool fix_start_cumul_to_zero,
466 const std::string&
name);
468 bool fix_start_cumul_to_zero,
469 const std::string&
name) {
471 fix_start_cumul_to_zero,
name);
481 bool fix_start_cumul_to_zero,
482 const std::string&
name);
491 std::vector<std::vector<int64> > values,
500 const std::vector<int>& pure_transits,
501 const std::vector<int>& dependent_transits,
503 std::vector<int64> vehicle_capacities,
bool fix_start_cumul_to_zero,
504 const std::string&
name) {
505 return AddDimensionDependentDimensionWithVehicleCapacityInternal(
506 pure_transits, dependent_transits, base_dimension, slack_max,
507 std::move(vehicle_capacities), fix_start_cumul_to_zero,
name);
513 int64 slack_max, std::vector<int64> vehicle_capacities,
514 bool fix_start_cumul_to_zero,
const std::string&
name);
518 int64 vehicle_capacity,
bool fix_start_cumul_to_zero,
519 const std::string&
name);
521 int pure_transit,
int dependent_transit,
523 int64 vehicle_capacity,
bool fix_start_cumul_to_zero,
524 const std::string&
name);
541 std::vector<IntVar*> spans,
542 std::vector<IntVar*> total_slacks);
549 return dimensions_.get();
556 const std::vector<std::unique_ptr<GlobalDimensionCumulOptimizer> >&
558 return global_dimension_optimizers_;
560 const std::vector<std::unique_ptr<LocalDimensionCumulOptimizer> >&
562 return local_dimension_optimizers_;
564 const std::vector<std::unique_ptr<LocalDimensionCumulOptimizer> >&
566 return local_dimension_mp_optimizers_;
580 bool HasDimension(
const std::string& dimension_name)
const;
583 const std::string& dimension_name)
const;
587 const std::string& dimension_name)
const;
594 primary_constrained_dimension_ = dimension_name;
598 return primary_constrained_dimension_;
618 int64 max_cardinality = 1);
622 return index_to_disjunctions_[
index];
627 template <
typename F>
631 if (disjunctions_[disjunction].
value.max_cardinality == max_cardinality) {
632 for (
const int64 d_index : disjunctions_[disjunction].indices) {
638 #if !defined(SWIGPYTHON)
643 return disjunctions_[
index].indices;
647 int64 GetDisjunctionPenalty(DisjunctionIndex index) const {
648 return disjunctions_[
index].value.penalty;
653 return disjunctions_[
index].value.max_cardinality;
661 std::vector<std::pair<int64, int64>> GetPerfectBinaryDisjunctions()
const;
667 void IgnoreDisjunctionsAlreadyForcedToZero();
672 void AddSoftSameVehicleConstraint(
const std::vector<int64>& indices,
679 void SetAllowedVehiclesForIndex(
const std::vector<int>& vehicles,
684 return allowed_vehicles_[
index].empty() ||
685 allowed_vehicles_[
index].find(vehicle) !=
686 allowed_vehicles_[
index].end();
704 void AddPickupAndDelivery(
int64 pickup,
int64 delivery);
708 void AddPickupAndDeliverySets(DisjunctionIndex pickup_disjunction,
709 DisjunctionIndex delivery_disjunction);
714 const std::vector<std::pair<int, int> >&
715 GetPickupIndexPairs(
int64 node_index)
const;
717 const std::vector<std::pair<int, int> >&
718 GetDeliveryIndexPairs(
int64 node_index)
const;
723 void SetPickupAndDeliveryPolicyOfAllVehicles(PickupAndDeliveryPolicy policy);
724 void SetPickupAndDeliveryPolicyOfVehicle(PickupAndDeliveryPolicy policy,
726 PickupAndDeliveryPolicy GetPickupAndDeliveryPolicyOfVehicle(
731 int GetNumOfSingletonNodes()
const;
736 return pickup_delivery_pairs_;
738 const std::vector<std::pair<DisjunctionIndex, DisjunctionIndex>>&
740 return pickup_delivery_disjunctions_;
748 return implicit_pickup_delivery_pairs_without_alternatives_;
762 enum VisitTypePolicy {
777 TYPE_SIMULTANEOUSLY_ADDED_AND_REMOVED
780 void SetVisitType(
int64 index,
int type, VisitTypePolicy type_policy);
782 const std::vector<int>& GetSingleNodesOfType(
int type)
const;
783 const std::vector<int>& GetPairIndicesOfType(
int type)
const;
784 VisitTypePolicy GetVisitTypePolicy(
int64 index)
const;
789 void CloseVisitTypes();
795 return topologically_sorted_visit_types_;
802 void AddHardTypeIncompatibility(int type1, int type2);
803 void AddTemporalTypeIncompatibility(
int type1,
int type2);
805 const absl::flat_hash_set<int>& GetHardTypeIncompatibilitiesOfType(
807 const absl::flat_hash_set<int>& GetTemporalTypeIncompatibilitiesOfType(
812 return has_hard_type_incompatibilities_;
815 return has_temporal_type_incompatibilities_;
827 void AddSameVehicleRequiredTypeAlternatives(
828 int dependent_type, absl::flat_hash_set<int> required_type_alternatives);
833 void AddRequiredTypeAlternativesWhenAddingType(
834 int dependent_type, absl::flat_hash_set<int> required_type_alternatives);
840 void AddRequiredTypeAlternativesWhenRemovingType(
841 int dependent_type, absl::flat_hash_set<int> required_type_alternatives);
845 const std::vector<absl::flat_hash_set<int> >&
846 GetSameVehicleRequiredTypeAlternativesOfType(
int type)
const;
848 const std::vector<absl::flat_hash_set<int> >&
849 GetRequiredTypeAlternativesWhenAddingType(
int type)
const;
851 const std::vector<absl::flat_hash_set<int> >&
852 GetRequiredTypeAlternativesWhenRemovingType(
int type)
const;
857 return has_same_vehicle_type_requirements_;
860 return has_temporal_type_requirements_;
866 return HasTemporalTypeIncompatibilities() ||
867 HasHardTypeIncompatibilities() || HasSameVehicleTypeRequirements() ||
868 HasTemporalTypeRequirements();
875 int64 UnperformedPenalty(
int64 var_index)
const;
879 int64 UnperformedPenaltyOrValue(
int64 default_value,
int64 var_index)
const;
883 int64 GetDepot()
const;
890 max_active_vehicles_ = max_active_vehicles;
897 void SetArcCostEvaluatorOfAllVehicles(
int evaluator_index);
899 void SetArcCostEvaluatorOfVehicle(
int evaluator_index,
int vehicle);
902 void SetFixedCostOfAllVehicles(
int64 cost);
904 void SetFixedCostOfVehicle(
int64 cost,
int vehicle);
908 int64 GetFixedCostOfVehicle(
int vehicle)
const;
925 void SetAmortizedCostFactorsOfAllVehicles(
int64 linear_cost_factor,
926 int64 quadratic_cost_factor);
928 void SetAmortizedCostFactorsOfVehicle(
int64 linear_cost_factor,
929 int64 quadratic_cost_factor,
933 return linear_cost_factor_of_vehicle_;
936 return quadratic_cost_factor_of_vehicle_;
941 consider_empty_route_costs_[vehicle] = consider_costs;
946 return consider_empty_route_costs_[vehicle];
953 return first_solution_evaluator_;
958 first_solution_evaluator_ = std::move(evaluator);
968 void AddAtSolutionCallback(std::function<
void()>
callback);
973 void AddVariableMinimizedByFinalizer(
IntVar*
var);
976 void AddVariableMaximizedByFinalizer(
IntVar*
var);
992 void CloseModelWithParameters(
993 const RoutingSearchParameters& search_parameters);
1009 const RoutingSearchParameters& search_parameters,
1010 std::vector<const Assignment*>* solutions =
nullptr);
1011 const Assignment* SolveFromAssignmentWithParameters(
1013 const RoutingSearchParameters& search_parameters,
1014 std::vector<const Assignment*>* solutions =
nullptr);
1020 void SetAssignmentFromOtherModelAssignment(
1029 int64 ComputeLowerBound();
1040 IntVar* ApplyLocks(
const std::vector<int64>& locks);
1049 bool ApplyLocksToAllVehicles(
const std::vector<std::vector<int64>>& locks,
1060 bool WriteAssignment(
const std::string& file_name)
const;
1064 Assignment* ReadAssignment(
const std::string& file_name);
1074 const std::vector<std::vector<int64>>& routes,
1075 bool ignore_inactive_indices);
1092 bool RoutesToAssignment(
const std::vector<std::vector<int64>>& routes,
1093 bool ignore_inactive_indices,
bool close_routes,
1098 void AssignmentToRoutes(
const Assignment& assignment,
1099 std::vector<std::vector<int64>>*
const routes)
const;
1105 std::vector<std::vector<int64>> GetRoutesFromAssignment(
1131 void AddToAssignment(
IntVar*
const var);
1143 const Assignment* PackCumulsOfOptimizerDimensionsFromAssignment(
1144 const Assignment* original_assignment, absl::Duration duration_limit);
1148 sweep_arranger_.reset(sweep_arranger);
1159 CHECK(filter !=
nullptr);
1161 LOG(
WARNING) <<
"Model is closed, filter addition will be ignored.";
1163 extra_filters_.push_back({filter, LocalSearchFilterManager::kRelax});
1164 extra_filters_.push_back({filter, LocalSearchFilterManager::kAccept});
1171 int64 End(
int vehicle)
const {
return ends_[vehicle]; }
1184 bool IsVehicleUsed(
const Assignment& assignment,
int vehicle)
const;
1186 #if !defined(SWIGPYTHON)
1189 const std::vector<IntVar*>&
Nexts()
const {
return nexts_; }
1192 const std::vector<IntVar*>&
VehicleVars()
const {
return vehicle_vars_; }
1202 return vehicle_active_[vehicle];
1207 return vehicle_costs_considered_[vehicle];
1218 int64 vehicle)
const;
1221 return costs_are_homogeneous_across_vehicles_;
1226 return GetArcCostForVehicle(from_index, to_index, 0);
1230 int64 GetArcCostForFirstSolution(
int64 from_index,
int64 to_index)
const;
1238 int64 cost_class_index)
const;
1243 DCHECK_LT(vehicle, cost_class_index_of_vehicle_.size());
1244 DCHECK_GE(cost_class_index_of_vehicle_[vehicle], 0);
1245 return cost_class_index_of_vehicle_[vehicle];
1251 if (cost_class_index == kCostClassIndexOfZeroCost) {
1252 return has_vehicle_with_zero_cost_class_;
1254 return cost_class_index < cost_classes_.size();
1260 return std::max(0, GetCostClassesCount() - 1);
1264 return vehicle_class_index_of_vehicle_[vehicle];
1271 return same_vehicle_groups_[same_vehicle_group_[node]];
1276 return vehicle_type_container_;
1302 std::string DebugOutputAssignment(
1304 const std::string& dimension_to_print)
const;
1311 std::vector<std::vector<std::pair<int64, int64>>> GetCumulBounds(
1327 return limit_->AbsoluteSolverDeadline() - solver_->Now();
1336 int64 Size()
const {
return nodes_ + vehicles_ - start_end_count_; }
1340 int64 GetNumberOfDecisionsInFirstSolution(
1341 const RoutingSearchParameters& search_parameters)
const;
1342 int64 GetNumberOfRejectsInFirstSolution(
1343 const RoutingSearchParameters& search_parameters)
const;
1347 return automatic_first_solution_strategy_;
1351 bool IsMatchingModel()
const;
1357 std::function<std::vector<operations_research::IntVar*>(
RoutingModel*)>;
1384 static std::unique_ptr<LocalSearchOperator> MakeGreedyDescentLSOperator(
1385 std::vector<IntVar*> variables);
1405 enum RoutingLocalSearchOperator {
1408 LIGHT_RELOCATE_PAIR,
1416 GLOBAL_CHEAPEST_INSERTION_CLOSE_NODES_LNS,
1417 LOCAL_CHEAPEST_INSERTION_CLOSE_NODES_LNS,
1418 GLOBAL_CHEAPEST_INSERTION_PATH_LNS,
1419 LOCAL_CHEAPEST_INSERTION_PATH_LNS,
1420 RELOCATE_PATH_GLOBAL_CHEAPEST_INSERTION_INSERT_UNPERFORMED,
1421 GLOBAL_CHEAPEST_INSERTION_EXPENSIVE_CHAIN_LNS,
1422 LOCAL_CHEAPEST_INSERTION_EXPENSIVE_CHAIN_LNS,
1423 RELOCATE_EXPENSIVE_CHAIN,
1427 RELOCATE_AND_MAKE_ACTIVE,
1428 MAKE_ACTIVE_AND_RELOCATE,
1430 MAKE_CHAIN_INACTIVE,
1432 EXTENDED_SWAP_ACTIVE,
1438 EXCHANGE_RELOCATE_PAIR,
1441 LOCAL_SEARCH_OPERATOR_COUNTER
1447 template <
typename T>
1448 struct ValuedNodes {
1449 std::vector<int64> indices;
1452 struct DisjunctionValues {
1454 int64 max_cardinality;
1456 typedef ValuedNodes<DisjunctionValues> Disjunction;
1460 struct CostCacheElement {
1466 CostClassIndex cost_class_index;
1472 void AddNoCycleConstraintInternal();
1473 bool AddDimensionWithCapacityInternal(
1474 const std::vector<int>& evaluator_indices,
int64 slack_max,
1475 std::vector<int64> vehicle_capacities,
bool fix_start_cumul_to_zero,
1476 const std::string&
name);
1477 bool AddDimensionDependentDimensionWithVehicleCapacityInternal(
1478 const std::vector<int>& pure_transits,
1479 const std::vector<int>& dependent_transits,
1480 const RoutingDimension* base_dimension,
int64 slack_max,
1481 std::vector<int64> vehicle_capacities,
bool fix_start_cumul_to_zero,
1482 const std::string&
name);
1483 bool InitializeDimensionInternal(
1484 const std::vector<int>& evaluator_indices,
1485 const std::vector<int>& state_dependent_evaluator_indices,
1486 int64 slack_max,
bool fix_start_cumul_to_zero,
1487 RoutingDimension* dimension);
1488 DimensionIndex GetDimensionIndex(
const std::string& dimension_name)
const;
1517 void StoreDimensionCumulOptimizers(
const RoutingSearchParameters&
parameters);
1519 void ComputeCostClasses(
const RoutingSearchParameters&
parameters);
1520 void ComputeVehicleClasses();
1528 void ComputeVehicleTypes();
1538 void FinalizeVisitTypes();
1540 void TopologicallySortVisitTypes();
1542 CostClassIndex cost_class_index)
const;
1543 void AppendHomogeneousArcCosts(
const RoutingSearchParameters&
parameters,
1545 std::vector<IntVar*>* cost_elements);
1546 void AppendArcCosts(
const RoutingSearchParameters&
parameters,
int node_index,
1547 std::vector<IntVar*>* cost_elements);
1548 Assignment* DoRestoreAssignment();
1549 static const CostClassIndex kCostClassIndexOfZeroCost;
1550 int64 SafeGetCostClassInt64OfVehicle(
int64 vehicle)
const {
1552 return (vehicle >= 0 ? GetCostClassIndexOfVehicle(vehicle)
1553 : kCostClassIndexOfZeroCost)
1557 const CostClass& cost_class)
const;
1559 IntVar* CreateDisjunction(DisjunctionIndex disjunction);
1561 void AddPickupAndDeliverySetsInternal(
const std::vector<int64>& pickups,
1562 const std::vector<int64>& deliveries);
1565 IntVar* CreateSameVehicleCost(
int vehicle_index);
1568 int FindNextActive(
int index,
const std::vector<int64>& indices)
const;
1572 bool RouteCanBeUsedByVehicle(
const Assignment& assignment,
int start_index,
1581 bool ReplaceUnusedVehicle(
int unused_vehicle,
int active_vehicle,
1582 Assignment* compact_assignment)
const;
1584 void QuietCloseModel();
1585 void QuietCloseModelWithParameters(
1593 bool SolveMatchingModel(Assignment* assignment,
1597 bool AppendAssignmentIfFeasible(
1598 const Assignment& assignment,
1599 std::vector<std::unique_ptr<Assignment>>* assignments);
1602 void LogSolution(
const RoutingSearchParameters&
parameters,
1603 const std::string& description,
int64 solution_cost,
1604 int64 start_time_ms);
1607 Assignment* CompactAssignmentInternal(
const Assignment& assignment,
1608 bool check_compact_assignment)
const;
1613 std::string FindErrorInSearchParametersForModel(
1614 const RoutingSearchParameters& search_parameters)
const;
1616 void SetupSearch(
const RoutingSearchParameters& search_parameters);
1619 Assignment* GetOrCreateAssignment();
1620 Assignment* GetOrCreateTmpAssignment();
1621 RegularLimit* GetOrCreateLimit();
1622 RegularLimit* GetOrCreateLocalSearchLimit();
1623 RegularLimit* GetOrCreateLargeNeighborhoodSearchLimit();
1624 RegularLimit* GetOrCreateFirstSolutionLargeNeighborhoodSearchLimit();
1625 LocalSearchOperator* CreateInsertionOperator();
1626 LocalSearchOperator* CreateMakeInactiveOperator();
1628 LocalSearchOperator* CreateCPOperator(
const T& operator_factory) {
1629 return operator_factory(solver_.get(), nexts_,
1630 CostsAreHomogeneousAcrossVehicles()
1631 ? std::vector<IntVar*>()
1633 vehicle_start_class_callback_);
1636 LocalSearchOperator* CreateCPOperator() {
1637 return CreateCPOperator(absl::bind_front(MakeLocalSearchOperator<T>));
1639 template <
class T,
class Arg>
1640 LocalSearchOperator* CreateOperator(
const Arg& arg) {
1641 return solver_->RevAlloc(
new T(nexts_,
1642 CostsAreHomogeneousAcrossVehicles()
1643 ? std::vector<IntVar*>()
1645 vehicle_start_class_callback_, arg));
1648 LocalSearchOperator* CreatePairOperator() {
1649 return CreateOperator<T>(pickup_delivery_pairs_);
1651 void CreateNeighborhoodOperators(
const RoutingSearchParameters&
parameters);
1652 LocalSearchOperator* ConcatenateOperators(
1653 const RoutingSearchParameters& search_parameters,
1654 const std::vector<LocalSearchOperator*>& operators)
const;
1655 LocalSearchOperator* GetNeighborhoodOperators(
1656 const RoutingSearchParameters& search_parameters)
const;
1657 std::vector<LocalSearchFilterManager::FilterEvent>
1658 GetOrCreateLocalSearchFilters(
const RoutingSearchParameters&
parameters,
1659 bool filter_cost =
true);
1660 LocalSearchFilterManager* GetOrCreateLocalSearchFilterManager(
1662 std::vector<LocalSearchFilterManager::FilterEvent>
1663 GetOrCreateFeasibilityFilters(
const RoutingSearchParameters&
parameters);
1664 LocalSearchFilterManager* GetOrCreateFeasibilityFilterManager(
1666 LocalSearchFilterManager* GetOrCreateStrongFeasibilityFilterManager(
1668 DecisionBuilder* CreateSolutionFinalizer(SearchLimit* lns_limit);
1669 DecisionBuilder* CreateFinalizerForMinimizedAndMaximizedVariables();
1670 void CreateFirstSolutionDecisionBuilders(
1671 const RoutingSearchParameters& search_parameters);
1672 DecisionBuilder* GetFirstSolutionDecisionBuilder(
1673 const RoutingSearchParameters& search_parameters)
const;
1674 IntVarFilteredDecisionBuilder* GetFilteredFirstSolutionDecisionBuilderOrNull(
1675 const RoutingSearchParameters&
parameters)
const;
1676 LocalSearchPhaseParameters* CreateLocalSearchParameters(
1677 const RoutingSearchParameters& search_parameters);
1678 DecisionBuilder* CreateLocalSearchDecisionBuilder(
1679 const RoutingSearchParameters& search_parameters);
1680 void SetupDecisionBuilders(
const RoutingSearchParameters& search_parameters);
1681 void SetupMetaheuristics(
const RoutingSearchParameters& search_parameters);
1682 void SetupAssignmentCollector(
1683 const RoutingSearchParameters& search_parameters);
1684 void SetupTrace(
const RoutingSearchParameters& search_parameters);
1685 void SetupImprovementLimit(
const RoutingSearchParameters& search_parameters);
1686 void SetupSearchMonitors(
const RoutingSearchParameters& search_parameters);
1687 bool UsesLightPropagation(
1688 const RoutingSearchParameters& search_parameters)
const;
1689 GetTabuVarsCallback tabu_var_callback_;
1695 void DetectImplicitPickupAndDeliveries();
1697 int GetVehicleStartClass(
int64 start)
const;
1699 void InitSameVehicleGroups(
int number_of_groups) {
1700 same_vehicle_group_.assign(Size(), 0);
1701 same_vehicle_groups_.assign(number_of_groups, {});
1703 void SetSameVehicleGroup(
int index,
int group) {
1704 same_vehicle_group_[
index] = group;
1705 same_vehicle_groups_[group].push_back(
index);
1709 std::unique_ptr<Solver> solver_;
1712 int max_active_vehicles_;
1713 Constraint* no_cycle_constraint_ =
nullptr;
1715 std::vector<IntVar*> nexts_;
1716 std::vector<IntVar*> vehicle_vars_;
1717 std::vector<IntVar*> active_;
1719 std::vector<IntVar*> vehicle_active_;
1720 std::vector<IntVar*> vehicle_costs_considered_;
1725 std::vector<IntVar*> is_bound_to_end_;
1726 mutable RevSwitch is_bound_to_end_ct_added_;
1728 absl::flat_hash_map<std::string, DimensionIndex> dimension_name_to_index_;
1734 std::vector<std::unique_ptr<GlobalDimensionCumulOptimizer> >
1735 global_dimension_optimizers_;
1737 std::vector<std::unique_ptr<LocalDimensionCumulOptimizer> >
1738 local_dimension_optimizers_;
1739 std::vector<std::unique_ptr<LocalDimensionCumulOptimizer> >
1740 local_dimension_mp_optimizers_;
1743 std::string primary_constrained_dimension_;
1745 IntVar* cost_ =
nullptr;
1746 std::vector<int> vehicle_to_transit_cost_;
1747 std::vector<int64> fixed_cost_of_vehicle_;
1748 std::vector<CostClassIndex> cost_class_index_of_vehicle_;
1749 bool has_vehicle_with_zero_cost_class_;
1750 std::vector<int64> linear_cost_factor_of_vehicle_;
1751 std::vector<int64> quadratic_cost_factor_of_vehicle_;
1752 bool vehicle_amortized_cost_factors_set_;
1763 std::vector<bool> consider_empty_route_costs_;
1767 bool costs_are_homogeneous_across_vehicles_;
1768 bool cache_callbacks_;
1769 mutable std::vector<CostCacheElement> cost_cache_;
1770 std::vector<VehicleClassIndex> vehicle_class_index_of_vehicle_;
1774 VehicleTypeContainer vehicle_type_container_;
1775 std::function<int(
int64)> vehicle_start_class_callback_;
1778 std::vector<std::vector<DisjunctionIndex> > index_to_disjunctions_;
1780 std::vector<ValuedNodes<int64> > same_vehicle_costs_;
1783 std::vector<absl::flat_hash_set<int>> allowed_vehicles_;
1786 IndexPairs pickup_delivery_pairs_;
1787 IndexPairs implicit_pickup_delivery_pairs_without_alternatives_;
1788 std::vector<std::pair<DisjunctionIndex, DisjunctionIndex> >
1789 pickup_delivery_disjunctions_;
1794 std::vector<std::vector<std::pair<int, int> > > index_to_pickup_index_pairs_;
1796 std::vector<std::vector<std::pair<int, int> > >
1797 index_to_delivery_index_pairs_;
1799 std::vector<PickupAndDeliveryPolicy> vehicle_pickup_delivery_policy_;
1801 std::vector<int> same_vehicle_group_;
1803 std::vector<std::vector<int>> same_vehicle_groups_;
1806 std::vector<int> index_to_visit_type_;
1808 std::vector<VisitTypePolicy> index_to_type_policy_;
1810 std::vector<std::vector<int> > single_nodes_of_type_;
1811 std::vector<std::vector<int> > pair_indices_of_type_;
1813 std::vector<absl::flat_hash_set<int> >
1814 hard_incompatible_types_per_type_index_;
1815 bool has_hard_type_incompatibilities_;
1816 std::vector<absl::flat_hash_set<int> >
1817 temporal_incompatible_types_per_type_index_;
1818 bool has_temporal_type_incompatibilities_;
1820 std::vector<std::vector<absl::flat_hash_set<int> > >
1821 same_vehicle_required_type_alternatives_per_type_index_;
1822 bool has_same_vehicle_type_requirements_;
1823 std::vector<std::vector<absl::flat_hash_set<int> > >
1824 required_type_alternatives_when_adding_type_index_;
1825 std::vector<std::vector<absl::flat_hash_set<int> > >
1826 required_type_alternatives_when_removing_type_index_;
1827 bool has_temporal_type_requirements_;
1828 absl::flat_hash_map<int, absl::flat_hash_set<VisitTypePolicy> >
1829 trivially_infeasible_visit_types_to_policies_;
1846 std::vector<std::vector<int> > topologically_sorted_visit_types_;
1848 int num_visit_types_;
1851 std::vector<int> index_to_equivalence_class_;
1852 std::vector<int> index_to_vehicle_;
1853 std::vector<int64> starts_;
1854 std::vector<int64> ends_;
1857 RoutingIndexManager manager_;
1858 int start_end_count_;
1860 bool closed_ =
false;
1861 Status status_ = ROUTING_NOT_SOLVED;
1862 bool enable_deep_serialization_ =
true;
1865 std::vector<DecisionBuilder*> first_solution_decision_builders_;
1866 std::vector<IntVarFilteredDecisionBuilder*>
1867 first_solution_filtered_decision_builders_;
1868 Solver::IndexEvaluator2 first_solution_evaluator_;
1870 FirstSolutionStrategy::UNSET;
1871 std::vector<LocalSearchOperator*> local_search_operators_;
1872 std::vector<SearchMonitor*> monitors_;
1873 SolutionCollector* collect_assignments_ =
nullptr;
1874 SolutionCollector* collect_one_assignment_ =
nullptr;
1875 SolutionCollector* packed_dimensions_assignment_collector_ =
nullptr;
1876 DecisionBuilder* solve_db_ =
nullptr;
1877 DecisionBuilder* improve_db_ =
nullptr;
1878 DecisionBuilder* restore_assignment_ =
nullptr;
1879 DecisionBuilder* restore_tmp_assignment_ =
nullptr;
1880 Assignment* assignment_ =
nullptr;
1881 Assignment* preassignment_ =
nullptr;
1882 Assignment* tmp_assignment_ =
nullptr;
1883 std::vector<IntVar*> extra_vars_;
1884 std::vector<IntervalVar*> extra_intervals_;
1885 std::vector<LocalSearchOperator*> extra_operators_;
1886 LocalSearchFilterManager* local_search_filter_manager_ =
nullptr;
1887 LocalSearchFilterManager* feasibility_filter_manager_ =
nullptr;
1888 LocalSearchFilterManager* strong_feasibility_filter_manager_ =
nullptr;
1889 std::vector<LocalSearchFilterManager::FilterEvent> extra_filters_;
1891 std::vector<std::pair<IntVar*, int64>> finalizer_variable_cost_pairs_;
1892 std::vector<std::pair<IntVar*, int64>> finalizer_variable_target_pairs_;
1893 absl::flat_hash_map<IntVar*, int> finalizer_variable_cost_index_;
1894 absl::flat_hash_set<IntVar*> finalizer_variable_target_set_;
1895 std::unique_ptr<SweepArranger> sweep_arranger_;
1898 RegularLimit*
limit_ =
nullptr;
1899 RegularLimit* ls_limit_ =
nullptr;
1900 RegularLimit* lns_limit_ =
nullptr;
1901 RegularLimit* first_solution_lns_limit_ =
nullptr;
1903 typedef std::pair<int64, int64> CacheKey;
1904 typedef absl::flat_hash_map<CacheKey, int64> TransitCallbackCache;
1905 typedef absl::flat_hash_map<CacheKey, StateDependentTransit>
1906 StateDependentTransitCallbackCache;
1908 std::vector<TransitCallback1> unary_transit_evaluators_;
1909 std::vector<TransitCallback2> transit_evaluators_;
1920 std::vector<bool> is_transit_evaluator_positive_;
1921 std::vector<VariableIndexEvaluator2> state_dependent_transit_evaluators_;
1922 std::vector<std::unique_ptr<StateDependentTransitCallbackCache>>
1923 state_dependent_transit_evaluators_cache_;
1935 static const char kLightElement[];
1936 static const char kLightElement2[];
1937 static const char kRemoveValues[];
1951 int num_chain_tasks = 0;
1967 duration_min.clear();
1968 duration_max.clear();
1971 is_preemptible.clear();
1972 forbidden_intervals.clear();
1973 distance_duration.clear();
1976 num_chain_tasks = 0;
1982 bool Propagate(Tasks* tasks);
1985 bool Precedences(Tasks* tasks);
1988 bool MirrorTasks(Tasks* tasks);
1990 bool EdgeFinding(Tasks* tasks);
1993 bool DetectablePrecedencesWithChain(Tasks* tasks);
1995 bool ForbiddenIntervals(Tasks* tasks);
1997 bool DistanceDuration(Tasks* tasks);
2000 bool ChainSpanMin(Tasks* tasks);
2005 bool ChainSpanMinDynamic(Tasks* tasks);
2012 std::vector<int> tasks_by_start_min_;
2013 std::vector<int> tasks_by_end_max_;
2014 std::vector<int> event_of_task_;
2015 std::vector<int> nonchain_tasks_by_start_max_;
2017 std::vector<int64> total_duration_before_;
2035 std::vector<int64>* values);
2055 return "GlobalVehicleBreaksConstraint";
2058 void Post()
override;
2059 void InitialPropagate()
override;
2062 void PropagateNode(
int node);
2063 void PropagateVehicle(
int vehicle);
2064 void PropagateMaxBreakDistance(
int vehicle);
2068 std::vector<Demon*> vehicle_demons_;
2069 std::vector<int64> path_;
2075 void FillPartialPathOfVehicle(
int vehicle);
2076 void FillPathTravels(
const std::vector<int64>& path);
2088 class TaskTranslator {
2092 before_start_(before_start),
2093 after_start_(after_start) {}
2098 if (start_ !=
nullptr) {
2100 }
else if (interval_ !=
nullptr) {
2101 interval_->SetStartMin(
value);
2105 if (start_ !=
nullptr) {
2107 }
else if (interval_ !=
nullptr) {
2108 interval_->SetStartMax(
value);
2112 if (interval_ !=
nullptr) {
2113 interval_->SetDurationMin(
value);
2117 if (start_ !=
nullptr) {
2119 }
else if (interval_ !=
nullptr) {
2120 interval_->SetEndMin(
value);
2124 if (start_ !=
nullptr) {
2126 }
else if (interval_ !=
nullptr) {
2127 interval_->SetEndMax(
value);
2132 IntVar* start_ =
nullptr;
2133 int64 before_start_;
2135 IntervalVar* interval_ =
nullptr;
2139 std::vector<TaskTranslator> task_translators_;
2142 DisjunctivePropagator disjunctive_propagator_;
2143 DisjunctivePropagator::Tasks tasks_;
2146 TravelBounds travel_bounds_;
2154 bool CheckVehicle(
int vehicle,
2155 const std::function<
int64(
int64)>& next_accessor);
2166 int num_type_added_to_vehicle = 0;
2172 int num_type_removed_from_vehicle = 0;
2177 int position_of_last_type_on_vehicle_up_to_visit = -1;
2184 bool TypeOccursOnRoute(
int type)
const;
2191 bool TypeCurrentlyOnRoute(
int type,
int pos)
const;
2193 void InitializeCheck(
int vehicle,
2194 const std::function<
int64(
int64)>& next_accessor);
2204 std::vector<TypePolicyOccurrence> occurrences_of_type_;
2205 std::vector<int64> current_route_visits_;
2212 bool check_hard_incompatibilities);
2216 bool HasRegulationsToCheck()
const override;
2217 bool CheckTypeRegulations(
int type, VisitTypePolicy policy,
int pos)
override;
2221 bool check_hard_incompatibilities_;
2232 bool HasRegulationsToCheck()
const override;
2233 void OnInitializeCheck()
override {
2234 types_with_same_vehicle_requirements_on_route_.clear();
2239 bool CheckRequiredTypesCurrentlyOnRoute(
2240 const std::vector<absl::flat_hash_set<int> >& required_type_alternatives,
2243 bool CheckTypeRegulations(
int type, VisitTypePolicy policy,
int pos)
override;
2244 bool FinalizeCheck()
const override;
2246 absl::flat_hash_set<int> types_with_same_vehicle_requirements_on_route_;
2293 void Post()
override;
2294 void InitialPropagate()
override;
2297 void PropagateNodeRegulations(
int node);
2298 void CheckRegulationsOnVehicle(
int vehicle);
2303 std::vector<Demon*> vehicle_demons_;
2325 : bound_costs_(num_bounds, default_bound_cost) {}
2328 int Size() {
return bound_costs_.size(); }
2333 std::vector<BoundCost> bound_costs_;
2369 int64 vehicle_class)
const {
2370 return model_->TransitCallback(class_evaluators_[vehicle_class])(from_index,
2380 #if !defined(SWIGPYTHON)
2385 const std::vector<IntVar*>&
transits()
const {
return transits_; }
2386 const std::vector<IntVar*>&
slacks()
const {
return slacks_; }
2387 #if !defined(SWIGCSHARP) && !defined(SWIGJAVA)
2390 return forbidden_intervals_;
2395 int64 max_value)
const;
2399 int64 min_value)
const {
2402 forbidden_intervals_[
index];
2403 const auto first_forbidden_interval_it =
2405 if (first_forbidden_interval_it != forbidden_intervals.
end() &&
2406 min_value >= first_forbidden_interval_it->start) {
2408 return CapAdd(first_forbidden_interval_it->end, 1);
2418 int64 max_value)
const {
2421 forbidden_intervals_[
index];
2422 const auto last_forbidden_interval_it =
2424 if (last_forbidden_interval_it != forbidden_intervals.
end() &&
2425 max_value <= last_forbidden_interval_it->end) {
2427 return CapSub(last_forbidden_interval_it->start, 1);
2434 return vehicle_capacities_;
2439 return model_->TransitCallback(
2440 class_evaluators_[vehicle_to_class_[vehicle]]);
2446 int vehicle)
const {
2447 return model_->UnaryTransitCallbackOrNull(
2448 class_evaluators_[vehicle_to_class_[vehicle]]);
2453 return model()->is_transit_evaluator_positive_
2454 [class_evaluators_[vehicle_to_class_[vehicle]]];
2462 void SetSpanUpperBoundForVehicle(
int64 upper_bound,
int vehicle);
2484 void SetCumulVarPiecewiseLinearCost(
int64 index,
2488 bool HasCumulVarPiecewiseLinearCost(
int64 index)
const;
2507 bool HasCumulVarSoftUpperBound(
int64 index)
const;
2530 bool HasCumulVarSoftLowerBound(
int64 index)
const;
2555 #if !defined(SWIGPYTHON)
2556 void SetBreakIntervalsOfVehicle(std::vector<IntervalVar*> breaks,
int vehicle,
2557 int pre_travel_evaluator,
2558 int post_travel_evaluator);
2562 void SetBreakIntervalsOfVehicle(std::vector<IntervalVar*> breaks,
int vehicle,
2563 std::vector<int64> node_visit_transits);
2569 void SetBreakDistanceDurationOfVehicle(
int64 distance,
int64 duration,
2573 void InitializeBreaks();
2575 bool HasBreakConstraints()
const;
2576 #if !defined(SWIGPYTHON)
2579 void SetBreakIntervalsOfVehicle(
2580 std::vector<IntervalVar*> breaks,
int vehicle,
2581 std::vector<int64> node_visit_transits,
2585 const std::vector<IntervalVar*>& GetBreakIntervalsOfVehicle(
2590 const std::vector<std::pair<int64, int64> >&
2591 GetBreakDistanceDurationOfVehicle(
int vehicle)
const;
2594 int GetPreTravelEvaluatorOfVehicle(
int vehicle)
const;
2595 int GetPostTravelEvaluatorOfVehicle(
int vehicle)
const;
2606 int64 ShortestTransitionSlack(
int64 node)
const;
2609 const std::string&
name()
const {
return name_; }
2614 return path_precedence_graph_;
2629 void SetPickupToDeliveryLimitFunctionForPair(
2632 bool HasPickupToDeliveryLimits()
const;
2634 int64 GetPickupToDeliveryLimitForPair(
int pair_index,
int pickup,
2635 int delivery)
const;
2644 node_precedences_.push_back(precedence);
2647 return node_precedences_;
2652 AddNodePrecedence({first_node, second_node, offset});
2656 return vehicle_span_upper_bounds_[vehicle];
2660 return vehicle_span_upper_bounds_;
2664 return vehicle_span_cost_coefficients_[vehicle];
2668 return vehicle_span_cost_coefficients_;
2672 return global_span_cost_coefficient_;
2677 return global_optimizer_offset_;
2680 if (vehicle >= local_optimizer_offset_for_vehicle_.size()) {
2683 DCHECK_GE(local_optimizer_offset_for_vehicle_[vehicle], 0);
2684 return local_optimizer_offset_for_vehicle_[vehicle];
2691 if (!HasSoftSpanUpperBounds()) {
2692 vehicle_soft_span_upper_bound_ = absl::make_unique<SimpleBoundCosts>(
2695 vehicle_soft_span_upper_bound_->bound_cost(vehicle) = bound_cost;
2698 return vehicle_soft_span_upper_bound_ !=
nullptr;
2701 int vehicle)
const {
2702 DCHECK(HasSoftSpanUpperBounds());
2703 return vehicle_soft_span_upper_bound_->bound_cost(vehicle);
2709 if (!HasQuadraticCostSoftSpanUpperBounds()) {
2710 vehicle_quadratic_cost_soft_span_upper_bound_ =
2711 absl::make_unique<SimpleBoundCosts>(
2714 vehicle_quadratic_cost_soft_span_upper_bound_->bound_cost(vehicle) =
2718 return vehicle_quadratic_cost_soft_span_upper_bound_ !=
nullptr;
2721 int vehicle)
const {
2722 DCHECK(HasQuadraticCostSoftSpanUpperBounds());
2723 return vehicle_quadratic_cost_soft_span_upper_bound_->bound_cost(vehicle);
2734 struct PiecewiseLinearCost {
2735 PiecewiseLinearCost() :
var(nullptr),
cost(nullptr) {}
2737 std::unique_ptr<PiecewiseLinearFunction>
cost;
2741 RoutingDimension(RoutingModel*
model, std::vector<int64> vehicle_capacities,
2742 const std::string&
name,
2743 const RoutingDimension* base_dimension);
2744 RoutingDimension(RoutingModel*
model, std::vector<int64> vehicle_capacities,
2745 const std::string&
name, SelfBased);
2746 void Initialize(
const std::vector<int>& transit_evaluators,
2747 const std::vector<int>& state_dependent_transit_evaluators,
2749 void InitializeCumuls();
2750 void InitializeTransits(
2751 const std::vector<int>& transit_evaluators,
2752 const std::vector<int>& state_dependent_transit_evaluators,
2754 void InitializeTransitVariables(
int64 slack_max);
2756 void SetupCumulVarSoftUpperBoundCosts(
2757 std::vector<IntVar*>* cost_elements)
const;
2759 void SetupCumulVarSoftLowerBoundCosts(
2760 std::vector<IntVar*>* cost_elements)
const;
2761 void SetupCumulVarPiecewiseLinearCosts(
2762 std::vector<IntVar*>* cost_elements)
const;
2765 void SetupGlobalSpanCost(std::vector<IntVar*>* cost_elements)
const;
2766 void SetupSlackAndDependentTransitCosts()
const;
2768 void CloseModel(
bool use_light_propagation);
2770 void SetOffsetForGlobalOptimizer(
int64 offset) {
2774 void SetVehicleOffsetsForLocalOptimizer(std::vector<int64> offsets) {
2776 std::transform(offsets.begin(), offsets.end(), offsets.begin(),
2777 [](
int64 offset) { return std::max(Zero(), offset); });
2778 local_optimizer_offset_for_vehicle_ = std::move(offsets);
2782 std::vector<SortedDisjointIntervalList> forbidden_intervals_;
2783 std::vector<IntVar*> capacity_vars_;
2784 const std::vector<int64> vehicle_capacities_;
2785 std::vector<IntVar*> transits_;
2786 std::vector<IntVar*> fixed_transits_;
2789 std::vector<int> class_evaluators_;
2790 std::vector<int64> vehicle_to_class_;
2792 ReverseArcListGraph<int, int> path_precedence_graph_;
2798 std::vector<NodePrecedence> node_precedences_;
2803 const RoutingDimension*
const base_dimension_;
2808 std::vector<int> state_dependent_class_evaluators_;
2809 std::vector<int64> state_dependent_vehicle_to_class_;
2814 std::vector<PickupToDeliveryLimitFunction>
2815 pickup_to_delivery_limits_per_pair_index_;
2818 bool break_constraints_are_initialized_ =
false;
2820 std::vector<std::vector<IntervalVar*> > vehicle_break_intervals_;
2821 std::vector<std::vector<std::pair<int64, int64> > >
2822 vehicle_break_distance_duration_;
2827 std::vector<int> vehicle_pre_travel_evaluators_;
2828 std::vector<int> vehicle_post_travel_evaluators_;
2830 std::vector<IntVar*> slacks_;
2831 std::vector<IntVar*> dependent_transits_;
2832 std::vector<int64> vehicle_span_upper_bounds_;
2833 int64 global_span_cost_coefficient_;
2834 std::vector<int64> vehicle_span_cost_coefficients_;
2835 std::vector<SoftBound> cumul_var_soft_upper_bound_;
2836 std::vector<SoftBound> cumul_var_soft_lower_bound_;
2837 std::vector<PiecewiseLinearCost> cumul_var_piecewise_linear_cost_;
2838 RoutingModel*
const model_;
2839 const std::string name_;
2840 int64 global_optimizer_offset_;
2841 std::vector<int64> local_optimizer_offset_for_vehicle_;
2843 std::unique_ptr<SimpleBoundCosts> vehicle_soft_span_upper_bound_;
2844 std::unique_ptr<SimpleBoundCosts>
2845 vehicle_quadratic_cost_soft_span_upper_bound_;
2849 const std::vector<RoutingDimension*>& dimensions,
2850 const RoutingSearchParameters&
parameters,
bool filter_objective_cost,
2851 std::vector<LocalSearchFilterManager::FilterEvent>* filters);
2861 explicit SweepArranger(
const std::vector<std::pair<int64, int64>>& points);
2863 void ArrangeIndices(std::vector<int64>* indices);
2867 std::vector<int> coordinates_;
2877 std::vector<IntVar*> variables,
2878 std::vector<int64> targets);
2888 : vehicle_type_container_(&vehicle_type_container) {}
2890 int NumTypes()
const {
return vehicle_type_container_->NumTypes(); }
2892 int Type(
int vehicle)
const {
return vehicle_type_container_->Type(vehicle); }
2896 void Reset(
const std::function<
bool(
int)>& store_vehicle);
2900 void Update(
const std::function<
bool(
int)>& remove_vehicle);
2904 const std::set<VehicleClassEntry>& vehicle_classes =
2905 sorted_vehicle_classes_per_type_[type];
2906 if (vehicle_classes.empty()) {
2909 const int vehicle_class = (vehicle_classes.begin())->vehicle_class;
2910 DCHECK(!vehicles_per_vehicle_class_[vehicle_class].empty());
2911 return vehicles_per_vehicle_class_[vehicle_class][0];
2916 std::vector<int>& vehicles = vehicles_per_vehicle_class_[vehicle_class];
2917 if (vehicles.empty()) {
2920 std::set<VehicleClassEntry>& vehicle_classes =
2921 sorted_vehicle_classes_per_type_[Type(vehicle)];
2922 const auto& insertion =
2923 vehicle_classes.insert({vehicle_class, fixed_cost});
2924 DCHECK(insertion.second);
2926 vehicles.push_back(vehicle);
2937 std::pair<int, int> GetCompatibleVehicleOfType(
2938 int type, std::function<
bool(
int)> vehicle_is_compatible,
2939 std::function<
bool(
int)> stop_and_return_vehicle);
2942 using VehicleClassEntry =
2946 std::vector<std::set<VehicleClassEntry> > sorted_vehicle_classes_per_type_;
2947 std::vector<std::vector<int> > vehicles_per_vehicle_class_;
2970 std::unique_ptr<IntVarFilteredHeuristic> heuristic);
2976 std::string DebugString()
const override;
2979 int64 number_of_decisions()
const;
2980 int64 number_of_rejects()
const;
2983 const std::unique_ptr<IntVarFilteredHeuristic> heuristic_;
3003 virtual std::string
DebugString()
const {
return "IntVarFilteredHeuristic"; }
3007 void ResetSolution();
3021 if (!is_in_delta_[
index]) {
3023 delta_indices_.push_back(
index);
3024 is_in_delta_[
index] =
true;
3032 return assignment_->IntVarContainer().Element(
index).Value();
3036 return assignment_->IntVarContainer().Element(
index).Var() !=
nullptr;
3044 void SynchronizeFilters();
3051 bool FilterAccept();
3054 const std::vector<IntVar*>
vars_;
3056 std::vector<int> delta_indices_;
3057 std::vector<bool> is_in_delta_;
3061 int64 number_of_decisions_;
3062 int64 number_of_rejects_;
3073 const std::function<
int64(
int64)>& next_accessor);
3081 void MakeDisjunctionNodesUnperformed(
int64 node);
3083 void MakeUnassignedNodesUnperformed();
3088 void MakePartiallyPerformedPairsUnperformed();
3100 bool InitializeSolution()
override;
3103 std::vector<int64> start_chain_ends_;
3104 std::vector<int64> end_chain_starts_;
3112 std::function<
int64(
int64)> penalty_evaluator,
3123 return std::tie(distance, vehicle) <
3135 std::vector<std::vector<StartEndValue> >
3136 ComputeStartEndDistanceForVehicles(
const std::vector<int>& vehicles);
3142 template <
class Queue>
3144 std::vector<std::vector<StartEndValue> >* start_end_distances_per_node,
3145 Queue* priority_queue);
3157 void AppendEvaluatedPositionsAfter(
3159 std::vector<ValuedPosition>* valued_positions);
3166 int64 GetInsertionCostForNodeAtPosition(
int64 node_to_insert,
3168 int64 insert_before,
3172 int64 GetUnperformedValue(
int64 node_to_insert)
const;
3215 std::function<
int64(
int64)> penalty_evaluator,
3219 bool BuildSolutionInternal()
override;
3221 return "GlobalCheapestInsertionFilteredHeuristic";
3227 typedef absl::flat_hash_set<PairEntry*> PairEntries;
3228 typedef absl::flat_hash_set<NodeEntry*> NodeEntries;
3236 void InsertPairsAndNodesByRequirementTopologicalOrder();
3244 void InsertPairs(
const std::vector<int>& pair_indices);
3252 bool InsertPairEntryUsingEmptyVehicleTypeCurator(
3253 const std::vector<int>& pair_indices, PairEntry*
const pair_entry,
3255 std::vector<PairEntries>* pickup_to_entries,
3256 std::vector<PairEntries>* delivery_to_entries);
3265 void InsertNodesOnRoutes(
const std::vector<int>& nodes,
3266 const absl::flat_hash_set<int>& vehicles);
3275 bool InsertNodeEntryUsingEmptyVehicleTypeCurator(
3276 const std::vector<int>& nodes,
bool all_vehicles,
3277 NodeEntry*
const node_entry,
3279 std::vector<NodeEntries>* position_to_node_entries);
3286 void SequentialInsertNodes(
const std::vector<int>& nodes);
3291 void DetectUsedVehicles(std::vector<bool>* is_vehicle_used,
3292 std::vector<int>* unused_vehicles,
3293 absl::flat_hash_set<int>* used_vehicles);
3298 void InsertFarthestNodesAsSeeds();
3308 template <
class Queue>
3310 std::vector<std::vector<StartEndValue>>* start_end_distances_per_node,
3311 Queue* priority_queue, std::vector<bool>* is_vehicle_used);
3316 void InitializePairPositions(
3317 const std::vector<int>& pair_indices,
3319 std::vector<PairEntries>* pickup_to_entries,
3320 std::vector<PairEntries>* delivery_to_entries);
3326 void InitializeInsertionEntriesPerformingPair(
3329 std::vector<PairEntries>* pickup_to_entries,
3330 std::vector<PairEntries>* delivery_to_entries);
3334 void UpdateAfterPairInsertion(
3335 const std::vector<int>& pair_indices,
int vehicle,
int64 pickup,
3338 std::vector<PairEntries>* pickup_to_entries,
3339 std::vector<PairEntries>* delivery_to_entries);
3342 void UpdatePairPositions(
const std::vector<int>& pair_indices,
int vehicle,
3345 std::vector<PairEntries>* pickup_to_entries,
3346 std::vector<PairEntries>* delivery_to_entries) {
3347 UpdatePickupPositions(pair_indices, vehicle, insert_after, priority_queue,
3348 pickup_to_entries, delivery_to_entries);
3349 UpdateDeliveryPositions(pair_indices, vehicle, insert_after, priority_queue,
3350 pickup_to_entries, delivery_to_entries);
3354 void UpdatePickupPositions(
const std::vector<int>& pair_indices,
int vehicle,
3355 int64 pickup_insert_after,
3357 std::vector<PairEntries>* pickup_to_entries,
3358 std::vector<PairEntries>* delivery_to_entries);
3361 void UpdateDeliveryPositions(
3362 const std::vector<int>& pair_indices,
int vehicle,
3363 int64 delivery_insert_after,
3365 std::vector<PairEntries>* pickup_to_entries,
3366 std::vector<PairEntries>* delivery_to_entries);
3369 void DeletePairEntry(PairEntry* entry,
3371 std::vector<PairEntries>* pickup_to_entries,
3372 std::vector<PairEntries>* delivery_to_entries);
3377 void AddPairEntry(
int64 pickup,
int64 pickup_insert_after,
int64 delivery,
3378 int64 delivery_insert_after,
int vehicle,
3380 std::vector<PairEntries>* pickup_entries,
3381 std::vector<PairEntries>* delivery_entries)
const;
3384 void UpdatePairEntry(
3385 PairEntry*
const pair_entry,
3390 int64 GetInsertionValueForPairAtPositions(
int64 pickup,
3391 int64 pickup_insert_after,
3393 int64 delivery_insert_after,
3398 void InitializePositions(
const std::vector<int>& nodes,
3399 const absl::flat_hash_set<int>& vehicles,
3401 std::vector<NodeEntries>* position_to_node_entries);
3407 void InitializeInsertionEntriesPerformingNode(
3408 int64 node,
const absl::flat_hash_set<int>& vehicles,
3410 std::vector<NodeEntries>* position_to_node_entries);
3413 void UpdatePositions(
const std::vector<int>& nodes,
int vehicle,
3414 int64 insert_after,
bool all_vehicles,
3416 std::vector<NodeEntries>* node_entries);
3419 void DeleteNodeEntry(NodeEntry* entry,
3421 std::vector<NodeEntries>* node_entries);
3426 void AddNodeEntry(
int64 node,
int64 insert_after,
int vehicle,
3429 std::vector<NodeEntries>* node_entries)
const;
3432 void UpdateNodeEntry(
3433 NodeEntry*
const node_entry,
3438 void ComputeNeighborhoods();
3442 bool IsNeighborForCostClass(
int cost_class,
int64 node_index,
3443 int64 neighbor_index)
const;
3446 const std::vector<int64>& GetNeighborsOfNodeForCostClass(
3447 int cost_class,
int64 node_index)
const {
3448 return gci_params_.neighbors_ratio == 1
3450 : node_index_to_neighbors_by_cost_class_[node_index][cost_class]
3451 ->PositionsSetAtLeastOnce();
3454 int64 NumNonStartEndNodes()
const {
3455 return model()->Size() -
model()->vehicles();
3458 int64 NumNeighbors()
const {
3459 return std::max(gci_params_.min_neighbors,
3460 MathUtil::FastInt64Round(gci_params_.neighbors_ratio *
3461 NumNonStartEndNodes()));
3464 void ResetVehicleIndices()
override {
3465 node_index_to_vehicle_.assign(node_index_to_vehicle_.size(), -1);
3468 void SetVehicleIndex(
int64 node,
int vehicle)
override {
3469 DCHECK_LT(node, node_index_to_vehicle_.size());
3470 node_index_to_vehicle_[node] = vehicle;
3475 bool CheckVehicleIndices()
const;
3477 GlobalCheapestInsertionParameters gci_params_;
3479 std::vector<int> node_index_to_vehicle_;
3482 std::vector<std::vector<std::unique_ptr<SparseBitset<int64> > > >
3483 node_index_to_neighbors_by_cost_class_;
3486 std::unique_ptr<VehicleTypeCurator> empty_vehicle_type_curator_;
3491 std::vector<int64> all_nodes_;
3507 bool BuildSolutionInternal()
override;
3509 return "LocalCheapestInsertionFilteredHeuristic";
3518 void ComputeEvaluatorSortedPositions(
int64 node,
3519 std::vector<int64>* sorted_positions);
3524 void ComputeEvaluatorSortedPositionsOnRouteAfter(
3526 std::vector<int64>* sorted_positions);
3528 std::vector<std::vector<StartEndValue>> start_end_distances_per_node_;
3538 bool BuildSolutionInternal()
override;
3541 class PartialRoutesAndLargeVehicleIndicesFirst {
3543 explicit PartialRoutesAndLargeVehicleIndicesFirst(
3545 : builder_(builder) {}
3546 bool operator()(
int vehicle1,
int vehicle2)
const;
3549 const CheapestAdditionFilteredHeuristic& builder_;
3552 template <
typename Iterator>
3553 std::vector<int64> GetPossibleNextsFromIterator(
int64 node, Iterator start,
3554 Iterator end)
const {
3555 const int size =
model()->Size();
3556 std::vector<int64> nexts;
3557 for (Iterator it = start; it != end; ++it) {
3559 if (
next != node && (
next >= size || !Contains(
next))) {
3560 nexts.push_back(
next);
3566 virtual void SortSuccessors(
int64 node, std::vector<int64>* successors) = 0;
3568 const std::vector<int64>& successors) = 0;
3582 return "EvaluatorCheapestAdditionFilteredHeuristic";
3587 void SortSuccessors(
int64 node, std::vector<int64>* successors)
override;
3589 const std::vector<int64>& successors)
override;
3605 return "ComparatorCheapestAdditionFilteredHeuristic";
3610 void SortSuccessors(
int64 node, std::vector<int64>* successors)
override;
3612 const std::vector<int64>& successors)
override;
3630 double neighbors_ratio = 1.0;
3633 double max_memory_usage_bytes = 6e9;
3636 bool add_reverse_arcs =
false;
3639 double arc_coefficient = 1.0;
3647 bool BuildSolutionInternal()
override;
3652 template <
typename S>
3661 return saving.second / size_squared_;
3665 return (saving.second % size_squared_) / Size();
3669 return (saving.second % size_squared_) % Size();
3683 int StartNewRouteWithBestVehicleOfType(
int type,
int64 before_node,
3697 void AddSymmetricArcsToAdjacencyLists(
3698 std::vector<std::vector<int64> >* adjacency_lists);
3707 void ComputeSavings();
3709 Saving BuildSaving(
int64 saving,
int vehicle_type,
int before_node,
3710 int after_node)
const {
3711 return std::make_pair(saving, vehicle_type * size_squared_ +
3712 before_node * Size() + after_node);
3718 int64 MaxNumNeighborsPerNode(
int num_vehicle_types)
const;
3721 const SavingsParameters savings_params_;
3722 int64 size_squared_;
3724 friend class SavingsFilteredHeuristicTestPeer;
3736 return "SequentialSavingsFilteredHeuristic";
3744 void BuildRoutesFromSavings()
override;
3745 double ExtraSavingsMemoryMultiplicativeFactor()
const override {
return 1.0; }
3757 return "ParallelSavingsFilteredHeuristic";
3771 void BuildRoutesFromSavings()
override;
3773 double ExtraSavingsMemoryMultiplicativeFactor()
const override {
return 2.0; }
3779 void MergeRoutes(
int first_vehicle,
int second_vehicle,
int64 before_node,
3783 std::vector<int64> first_node_on_route_;
3784 std::vector<int64> last_node_on_route_;
3788 std::vector<int> vehicle_of_first_or_last_node_;
3799 bool use_minimum_matching);
3801 bool BuildSolutionInternal()
override;
3803 return "ChristofidesFilteredHeuristic";
3807 const bool use_minimum_matching_;
3816 const RoutingSearchParameters& search_parameters,
3817 const Assignment* initial_solution,
3818 Assignment* solution);
3824 BasePathFilter(
const std::vector<IntVar*>& nexts,
int next_domain_size);
3827 int64 objective_min,
int64 objective_max)
override;
3844 return touched_paths_.PositionsSetAtLeastOnce();
3847 return new_synchronized_unperformed_nodes_.PositionsSetAtLeastOnce();
3851 enum Status {
UNKNOWN, ENABLED, DISABLED };
3853 virtual bool DisableFiltering()
const {
return false; }
3854 virtual void OnBeforeSynchronizePaths() {}
3855 virtual void OnAfterSynchronizePaths() {}
3856 virtual void OnSynchronizePathFromStart(
int64 start) {}
3857 virtual void InitializeAcceptPath() {}
3858 virtual bool AcceptPath(
int64 path_start,
int64 chain_start,
3859 int64 chain_end) = 0;
3860 virtual bool FinalizeAcceptPath(
const Assignment*
delta,
int64 objective_min,
3861 int64 objective_max) {
3865 void ComputePathStarts(std::vector<int64>* path_starts,
3866 std::vector<int>* index_to_path);
3867 bool HavePathsChanged();
3868 void SynchronizeFullAssignment();
3869 void UpdateAllRanks();
3870 void UpdatePathRanksFromStart(
int start);
3872 std::vector<int64> node_path_starts_;
3873 std::vector<int64> starts_;
3874 std::vector<int> paths_;
3875 SparseBitset<int64> new_synchronized_unperformed_nodes_;
3876 std::vector<int64> new_nexts_;
3877 std::vector<int> delta_touched_;
3878 SparseBitset<> touched_paths_;
3880 std::vector<std::pair<int64, int64> > touched_path_chain_start_ends_;
3882 std::vector<int> ranks_;
3902 std::string
DebugString()
const override {
return "CPFeasibilityFilter"; }
3904 int64 objective_min,
int64 objective_max)
override;
3921 const RoutingModel& routing_model);
3923 const RoutingModel& routing_model);
3925 const RoutingModel& routing_model);
3927 const RoutingModel& routing_model);
3929 const std::vector<RoutingDimension*>& dimensions,
3930 const RoutingSearchParameters&
parameters,
bool filter_objective_cost,
3931 std::vector<LocalSearchFilterManager::FilterEvent>* filters);
3933 const PathState* path_state,
3934 const std::vector<RoutingDimension*>& dimensions,
3935 std::vector<LocalSearchFilterManager::FilterEvent>* filters);
3937 const RoutingDimension& dimension,
3939 bool propagate_own_objective_value,
bool filter_objective_cost,
3940 bool can_use_lp =
true);
3942 const RoutingDimension& dimension);
3944 GlobalDimensionCumulOptimizer* optimizer,
bool filter_objective_cost);
3946 const RoutingModel& routing_model,
const RoutingModel::IndexPairs& pairs,
3947 const std::vector<RoutingModel::PickupAndDeliveryPolicy>& vehicle_policies);
3949 const RoutingModel& routing_model);
3951 const RoutingModel& routing_model,
const RoutingDimension& dimension);
const std::vector< IntVar * > vars_
#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.
Generic path-based filter class.
const std::vector< int64 > & GetTouchedPathStarts() const
static const int64 kUnassigned
const std::vector< int64 > & GetNewSynchronizedUnperformedNodes() const
~BasePathFilter() override
int Rank(int64 node) const
int64 GetNext(int64 node) const
int GetPath(int64 node) const
This filter accepts deltas for which the assignment satisfies the constraints of the Solver.
std::string DebugString() const override
~CPFeasibilityFilter() override
Filtered-base decision builder based on the addition heuristic, extending a path from its start node ...
~CheapestAdditionFilteredHeuristic() override
std::function< int64(int64)> penalty_evaluator_
std::function< int64(int64, int64, int64)> evaluator_
void InitializePriorityQueue(std::vector< std::vector< StartEndValue > > *start_end_distances_per_node, Queue *priority_queue)
Initializes the priority_queue by inserting the best entry corresponding to each node,...
std::pair< int64, int64 > ValuedPosition
~CheapestInsertionFilteredHeuristic() override
std::pair< StartEndValue, int > Seed
Christofides addition heuristic.
~ChristofidesFilteredHeuristic() override
std::string DebugString() const override
A CheapestAdditionFilteredHeuristic where the notion of 'cheapest arc' comes from an arc comparator.
~ComparatorCheapestAdditionFilteredHeuristic() override
std::string DebugString() const override
A constraint is the main modeling object.
A DecisionBuilder is responsible for creating the search tree.
A Decision represents a choice point in the search tree.
This class acts like a CP propagator: it takes a set of tasks given by their start/duration/end featu...
A CheapestAdditionFilteredHeuristic where the notion of 'cheapest arc' comes from an arc evaluator.
~EvaluatorCheapestAdditionFilteredHeuristic() override
std::string DebugString() const override
Filter-based decision builder which builds a solution by inserting nodes at their cheapest position o...
~GlobalCheapestInsertionFilteredHeuristic() override
std::string DebugString() const override
GlobalVehicleBreaksConstraint ensures breaks constraints are enforced on all vehicles in the dimensio...
std::string DebugString() const override
Decision builder building a solution using heuristics with local search filters to evaluate its feasi...
~IntVarFilteredDecisionBuilder() override
Generic filter-based heuristic applied to IntVars.
virtual bool BuildSolutionInternal()=0
Virtual method to redefine how to build a solution.
int Size() const
Returns the number of variables the decision builder is trying to instantiate.
bool Contains(int64 index) const
Returns true if the variable of index 'index' is in the current solution.
int64 Value(int64 index) const
Returns the value of the variable of index 'index' in the last committed solution.
virtual ~IntVarFilteredHeuristic()
IntVar * Var(int64 index) const
Returns the variable of index 'index'.
virtual bool StopSearch()
Returns true if the search must be stopped.
Assignment *const assignment_
virtual std::string DebugString() const
virtual bool InitializeSolution()
Virtual method to initialize the solution.
int64 number_of_rejects() const
int64 number_of_decisions() const
Returns statistics on search, number of decisions sent to filters, number of decisions rejected by fi...
void SetValue(int64 index, int64 value)
Modifies the current solution by setting the variable of index 'index' to value 'value'.
The class IntVar is a subset of IntExpr.
Interval variables are often used in scheduling.
Filter-base decision builder which builds a solution by inserting nodes at their cheapest position.
~LocalCheapestInsertionFilteredHeuristic() override
std::string DebugString() const override
Local Search Filters are used for fast neighbor pruning.
Filter manager: when a move is made, filters are executed to decide whether the solution is feasible ...
The base class for all local search operators.
ParallelSavingsFilteredHeuristic(RoutingModel *model, const RoutingIndexManager *manager, SavingsParameters parameters, LocalSearchFilterManager *filter_manager)
~ParallelSavingsFilteredHeuristic() override
std::string DebugString() const override
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
void AddNodePrecedence(int64 first_node, int64 second_node, int64 offset)
int64 GetTransitValueFromClass(int64 from_index, int64 to_index, int64 vehicle_class) const
Same as above but taking a vehicle class of the dimension instead of a vehicle (the class of a vehicl...
const std::vector< IntVar * > & cumuls() const
Like CumulVar(), TransitVar(), SlackVar() but return the whole variable vectors instead (indexed by i...
int64 global_span_cost_coefficient() const
int64 GetSpanCostCoefficientForVehicle(int vehicle) 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 GetGlobalOptimizerOffset() const
IntVar * CumulVar(int64 index) const
Get the cumul, transit and slack variables for the given node (given as int64 var index).
const RoutingModel::TransitCallback1 & GetUnaryTransitEvaluator(int vehicle) const
Returns the unary callback evaluating the transit value between two node indices for a given vehicle.
IntVar * FixedTransitVar(int64 index) const
const std::vector< int64 > & vehicle_capacities() const
Returns the capacities for all vehicles.
std::function< int64(int, int)> PickupToDeliveryLimitFunction
Limits, in terms of maximum difference between the cumul variables, between the pickup and delivery a...
bool AreVehicleTransitsPositive(int vehicle) const
Returns true iff the transit evaluator of 'vehicle' is positive for all arcs.
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.
void AddNodePrecedence(NodePrecedence precedence)
int64 GetLocalOptimizerOffsetForVehicle(int vehicle) const
const std::vector< int64 > & vehicle_span_upper_bounds() const
bool HasQuadraticCostSoftSpanUpperBounds() const
int64 GetFirstPossibleGreaterOrEqualValueForNode(int64 index, int64 min_value) const
Returns the smallest value outside the forbidden intervals of node 'index' that is greater than or eq...
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.
int64 GetLastPossibleLessOrEqualValueForNode(int64 index, int64 max_value) const
Returns the largest value outside the forbidden intervals of node 'index' that is less than or equal ...
IntVar * TransitVar(int64 index) const
IntVar * SlackVar(int64 index) const
const std::vector< int64 > & vehicle_span_cost_coefficients() 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
const std::vector< NodePrecedence > & GetNodePrecedences() const
bool HasSoftSpanUpperBounds() const
SimpleBoundCosts::BoundCost GetQuadraticCostSoftSpanUpperBoundForVehicle(int vehicle) const
const std::vector< SortedDisjointIntervalList > & forbidden_intervals() const
Returns forbidden intervals for each node.
int64 GetSpanUpperBoundForVehicle(int vehicle) const
Filter-based heuristic dedicated to routing.
~RoutingFilteredHeuristic() override
int GetStartChainEnd(int vehicle) const
Returns the end of the start chain of vehicle,.
RoutingModel * model() const
int GetEndChainStart(int vehicle) const
Returns the start of the end chain of vehicle,.
virtual void SetVehicleIndex(int64 node, int vehicle)
bool StopSearch() override
Returns true if the search must be stopped.
virtual void ResetVehicleIndices()
bool VehicleIsEmpty(int vehicle) const
Manager for any NodeIndex <-> variable index conversion.
bool AddDimensionWithVehicleTransitAndCapacity(const std::vector< int > &evaluator_indices, int64 slack_max, std::vector< int64 > vehicle_capacities, bool fix_start_cumul_to_zero, const std::string &name)
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.
int64 GetDisjunctionMaxCardinality(DisjunctionIndex index) const
Returns the maximum number of possible active nodes of the node disjunction of index 'index'.
RoutingIndexPair IndexPair
IntVar * ActiveVehicleVar(int vehicle) const
Returns the active variable of the vehicle.
int64 End(int vehicle) const
Returns the variable index of the ending node of a vehicle route.
RoutingTransitCallback1 TransitCallback1
int GetNumberOfVisitTypes() const
const std::vector< std::vector< int > > & GetTopologicallySortedVisitTypes() const
void ForEachNodeInDisjunctionWithMaxCardinalityFromIndex(int64 index, int64 max_cardinality, F f) const
Calls f for each variable index of indices in the same disjunctions as the node corresponding to the ...
CostClassIndex GetCostClassIndexOfVehicle(int64 vehicle) const
Get the cost class index of the given vehicle.
int GetVehicleClassesCount() const
Returns the number of different vehicle classes in the model.
int64 Size() const
Returns the number of next variables in the model.
Assignment * MutablePreAssignment()
bool CheckLimit()
Returns true if the search limit has been crossed.
int RegisterStateDependentTransitCallback(VariableIndexEvaluator2 callback)
bool IsVehicleAllowedForIndex(int vehicle, int64 index)
Returns true if a vehicle is allowed to visit a given node.
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...
bool AddDimensionDependentDimensionWithVehicleCapacity(const std::vector< int > &pure_transits, const std::vector< int > &dependent_transits, const RoutingDimension *base_dimension, int64 slack_max, std::vector< int64 > vehicle_capacities, bool fix_start_cumul_to_zero, const std::string &name)
Creates a dimension with transits depending on the cumuls of another dimension.
static RoutingModel::StateDependentTransit MakeStateDependentTransit(const std::function< int64(int64)> &f, int64 domain_start, int64 domain_end)
Creates a cached StateDependentTransit from an std::function.
Constraint * MakePathSpansAndTotalSlacks(const RoutingDimension *dimension, std::vector< IntVar * > spans, std::vector< IntVar * > total_slacks)
For every vehicle of the routing model:
LocalDimensionCumulOptimizer * GetMutableLocalCumulOptimizer(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...
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.
RoutingTransitCallback2 TransitCallback2
const std::vector< RoutingDimension * > & GetDimensions() const
Returns all dimensions of the model.
std::vector< std::string > GetAllDimensionNames() const
Outputs the names of all dimensions added to the routing engine.
const Solver::IndexEvaluator2 & first_solution_evaluator() const
Gets/sets the evaluator used during the search.
bool AddDimensionWithVehicleTransits(const std::vector< int > &evaluator_indices, int64 slack_max, int64 capacity, bool fix_start_cumul_to_zero, const std::string &name)
IntVar * NextVar(int64 index) const
!defined(SWIGPYTHON)
std::function< StateDependentTransit(int64, int64)> VariableIndexEvaluator2
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.
std::vector< RoutingDimension * > GetDimensionsWithSoftOrSpanCosts() const
Returns dimensions with soft or vehicle span costs.
void SetSweepArranger(SweepArranger *sweep_arranger)
SweepArranger * sweep_arranger() const
Returns the sweep arranger to be used by routing heuristics.
RoutingIndexPairs IndexPairs
VehicleClassIndex GetVehicleClassIndexOfVehicle(int64 vehicle) const
IntVar * VehicleCostsConsideredVar(int vehicle) const
Returns the variable specifying whether or not costs are considered for vehicle.
void ConsiderEmptyRouteCostsForVehicle(bool consider_costs, int vehicle)
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< DisjunctionIndex > & GetDisjunctionIndices(int64 index) const
Returns the indices of the disjunctions to which an index belongs.
static const int64 kNoPenalty
Constant used to express a hard constraint instead of a soft penalty.
int RegisterTransitCallback(TransitCallback2 callback)
IntVar * VehicleVar(int64 index) const
Returns the vehicle variable of the node corresponding to index.
const std::vector< std::unique_ptr< LocalDimensionCumulOptimizer > > & GetLocalDimensionCumulMPOptimizers() const
int GetMaximumNumberOfActiveVehicles() const
Returns the maximum number of active vehicles.
bool AddConstantDimensionWithSlack(int64 value, int64 capacity, int64 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...
RoutingDimensionIndex DimensionIndex
DisjunctionIndex AddDisjunction(const std::vector< int64 > &indices, int64 penalty=kNoPenalty, int64 max_cardinality=1)
Adds a disjunction constraint on the indices: exactly 'max_cardinality' of the indices are active.
LocalDimensionCumulOptimizer * GetMutableLocalCumulMPOptimizer(const RoutingDimension &dimension) const
bool HasHardTypeIncompatibilities() const
Returns true iff any hard (resp.
bool AddMatrixDimension(std::vector< std::vector< int64 > > values, int64 capacity, bool fix_start_cumul_to_zero, const std::string &name)
Creates a dimension where the transit variable is constrained to be equal to 'values[i][next(i)]' for...
const IndexPairs & GetPickupAndDeliveryPairs() const
Returns pickup and delivery pairs currently in the model.
bool AddConstantDimension(int64 value, int64 capacity, bool fix_start_cumul_to_zero, const std::string &name)
const std::vector< int64 > & GetAmortizedLinearCostFactorOfVehicles() const
int64 GetHomogeneousCost(int64 from_index, int64 to_index) const
Returns the cost of the segment between two nodes supposing all vehicle costs are the same (returns t...
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.
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...
const std::vector< int64 > & GetAmortizedQuadraticCostFactorOfVehicles() const
int VehicleIndex(int64 index) const
Returns the vehicle of the given start/end index, and -1 if the given index is not a vehicle start/en...
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
bool AddDimension(int evaluator_index, int64 slack_max, int64 capacity, bool fix_start_cumul_to_zero, const std::string &name)
Model creation.
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 HasSameVehicleTypeRequirements() const
Returns true iff any same-route (resp.
IntVar * CostVar() const
Returns the global cost variable which is being minimized.
void SetPrimaryConstrainedDimension(const std::string &dimension_name)
Set the given dimension as "primary constrained".
const VariableIndexEvaluator2 & StateDependentTransitCallback(int callback_index) const
bool AddDimensionWithVehicleCapacity(int evaluator_index, int64 slack_max, std::vector< int64 > vehicle_capacities, bool fix_start_cumul_to_zero, const std::string &name)
int RegisterUnaryTransitCallback(TransitCallback1 callback)
Registers 'callback' and returns its index.
int64 Start(int vehicle) const
Model inspection.
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.
const std::vector< int64 > & GetDisjunctionIndices(DisjunctionIndex index) const
Returns the variable indices of the nodes in the disjunction of index 'index'.
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.
bool IsEnd(int64 index) const
Returns true if 'index' represents the last node of a route.
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.
bool AreEmptyRouteCostsConsideredForVehicle(int vehicle) const
bool AddVectorDimension(std::vector< int64 > values, int64 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; ...
RoutingModel(const RoutingIndexManager &index_manager)
Constructor taking an index manager.
RoutingDisjunctionIndex DisjunctionIndex
IntVar * ActiveVar(int64 index) const
Returns the active variable of the node corresponding to index.
const RoutingDimension & GetDimensionOrDie(const std::string &dimension_name) const
Returns a dimension from its name. Dies if the dimension does not exist.
Filter-based decision builder which builds a solution by using Clarke & Wright's Savings heuristic.
std::unique_ptr< VehicleTypeCurator > vehicle_type_curator_
std::pair< int64, int64 > Saving
int64 GetVehicleTypeFromSaving(const Saving &saving) const
Returns the cost class from a saving.
std::unique_ptr< SavingsContainer< Saving > > savings_container_
int64 GetSavingValue(const Saving &saving) const
Returns the saving value from a saving.
virtual double ExtraSavingsMemoryMultiplicativeFactor() const =0
int64 GetBeforeNodeFromSaving(const Saving &saving) const
Returns the "before node" from a saving.
int64 GetAfterNodeFromSaving(const Saving &saving) const
Returns the "after node" from a saving.
virtual void BuildRoutesFromSavings()=0
Base class of all search limits.
A search monitor is a simple set of callbacks to monitor all search events.
~SequentialSavingsFilteredHeuristic() override
SequentialSavingsFilteredHeuristic(RoutingModel *model, const RoutingIndexManager *manager, SavingsParameters parameters, LocalSearchFilterManager *filter_manager)
std::string DebugString() const override
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< bool(int64, int64, int64)> VariableValueComparator
std::function< int64(int64, int64)> IndexEvaluator2
This class represents a sorted list of disjoint, closed intervals.
Iterator LastIntervalLessOrEqual(int64 value) const
ConstIterator end() const
Iterator FirstIntervalGreaterOrEqual(int64 value) const
Returns an iterator to either:
Class to arrange indices by by their distance and their angles from the depot.
void SetSectors(int sectors)
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)
Helper class that manages vehicles.
VehicleTypeCurator(const RoutingModel::VehicleTypeContainer &vehicle_type_container)
void ReinjectVehicleOfClass(int vehicle, int vehicle_class, int64 fixed_cost)
int Type(int vehicle) const
int GetLowestFixedCostVehicleOfType(int type) const
const std::vector< IntVar * > cumuls_
static const int64 kint64max
#define DISALLOW_COPY_AND_ASSIGN(TypeName)
std::function< int64(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.
The vehicle routing library lets one model and solve generic vehicle routing problems ranging from th...
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)
std::pair< std::vector< int64 >, std::vector< int64 > > RoutingIndexPair
IntVarLocalSearchFilter * MakePathCumulFilter(const RoutingDimension &dimension, const RoutingSearchParameters ¶meters, bool propagate_own_objective_value, bool filter_objective_cost, bool can_use_lp=true)
IntVarLocalSearchFilter * MakeCumulBoundsPropagatorFilter(const RoutingDimension &dimension)
int64 CapSub(int64 x, int64 y)
void AppendTasksFromPath(const std::vector< int64 > &path, const TravelBounds &travel_bounds, const RoutingDimension &dimension, DisjunctivePropagator::Tasks *tasks)
IntVarLocalSearchFilter * MakeGlobalLPCumulFilter(GlobalDimensionCumulOptimizer *optimizer, bool filter_objective_cost)
IntVarLocalSearchFilter * MakeVehicleBreaksFilter(const RoutingModel &routing_model, const RoutingDimension &dimension)
IntVarLocalSearchFilter * MakeVehicleAmortizedCostFilter(const RoutingModel &routing_model)
void FillTravelBoundsOfVehicle(int vehicle, const std::vector< int64 > &path, const RoutingDimension &dimension, TravelBounds *travel_bounds)
IntVarLocalSearchFilter * MakeCPFeasibilityFilter(RoutingModel *routing_model)
void AppendTasksFromIntervals(const std::vector< IntervalVar * > &intervals, DisjunctivePropagator::Tasks *tasks)
int64 CapAdd(int64 x, int64 y)
IntVarLocalSearchFilter * MakeMaxActiveVehiclesFilter(const RoutingModel &routing_model)
std::function< int64(int64, int64)> RoutingTransitCallback2
IntVarLocalSearchFilter * MakeVehicleVarFilter(const RoutingModel &routing_model)
std::function< int64(int64)> RoutingTransitCallback1
IntVarLocalSearchFilter * MakePickupDeliveryFilter(const RoutingModel &routing_model, const RoutingModel::IndexPairs &pairs, const std::vector< RoutingModel::PickupAndDeliveryPolicy > &vehicle_policies)
void FillPathEvaluation(const std::vector< int64 > &path, const RoutingModel::TransitCallback2 &evaluator, std::vector< int64 > *values)
IntVarLocalSearchFilter * MakeTypeRegulationsFilter(const RoutingModel &routing_model)
static const int kUnassigned
void AppendLightWeightDimensionFilters(const PathState *path_state, const std::vector< RoutingDimension * > &dimensions, std::vector< LocalSearchFilterManager::FilterEvent > *filters)
IntVarLocalSearchFilter * MakeNodeDisjunctionFilter(const RoutingModel &routing_model)
std::vector< RoutingIndexPair > RoutingIndexPairs
DecisionBuilder * MakeSetValuesFromTargets(Solver *solver, std::vector< IntVar * > variables, std::vector< int64 > targets)
A decision builder which tries to assign values to variables as close as possible to target values fi...
std::function< int64(int64, int64)> evaluator_
bool operator<(const StartEndValue &other) const
A structure to hold tasks described by their features.
std::vector< int64 > end_max
std::vector< int64 > start_min
std::vector< int64 > duration_min
std::vector< int64 > start_max
std::vector< const SortedDisjointIntervalList * > forbidden_intervals
std::vector< bool > is_preemptible
std::vector< int64 > duration_max
std::vector< std::pair< int64, int64 > > distance_duration
std::vector< int64 > end_min
double neighbors_ratio
If neighbors_ratio < 1 then for each node only this ratio of its neighbors leading to the smallest ar...
bool is_sequential
Whether the routes are constructed sequentially or in parallel.
double farthest_seeds_ratio
The ratio of routes on which to insert farthest nodes as seeds before starting the cheapest insertion...
bool use_neighbors_ratio_for_initialization
If true, only closest neighbors (see neighbors_ratio and min_neighbors) are considered as insertion p...
bool add_unperformed_entries
If true, entries are created for making the nodes/pairs unperformed, and when the cost of making a no...
SUBTLE: The vehicle's fixed cost is skipped on purpose here, because we can afford to do so:
const RoutingDimension * dimension
int64 transit_evaluator_class
bool operator<(const DimensionCost &cost) const
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 fixed_cost
Contrarily to CostClass, here we need strict equivalence.
absl::StrongVector< DimensionIndex, int64 > dimension_capacities
absl::StrongVector< DimensionIndex, int64 > dimension_evaluator_classes
dimension_evaluators[d]->Run(from, to) is the transit value of arc from->to for a dimension d.
int start_equivalence_class
Vehicle start and end equivalence classes.
absl::StrongVector< DimensionIndex, int64 > dimension_start_cumuls_min
Bounds of cumul variables at start and end vehicle nodes.
absl::StrongVector< DimensionIndex, int64 > dimension_end_cumuls_min
absl::StrongVector< DimensionIndex, int64 > dimension_end_cumuls_max
int end_equivalence_class
uint64 unvisitable_nodes_fprint
Fingerprint of unvisitable non-start/end nodes.
static bool LessThan(const VehicleClass &a, const VehicleClass &b)
Comparator for STL containers and algorithms.
absl::StrongVector< DimensionIndex, int64 > 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 > max_travels
std::vector< int64 > min_travels
std::vector< int64 > post_travels
std::vector< int64 > pre_travels