Google OR-Tools: ortools/constraint_solver/routing.h Source File
211 const int num_indices = manager.num_indices();
212 const int num_paths = manager.num_vehicles();
213 path_of_node_.resize(num_indices, -1);
214 is_start_.resize(num_indices, false);
215 is_end_.resize(num_indices, false);
216 start_of_path_.resize(num_paths);
217 end_of_path_.resize(num_paths);
218 for (int v = 0; v < num_paths; ++v) {
220 start_of_path_[v] = start;
224 end_of_path_[v] = end;
225 path_of_node_[end] = v;
226 is_end_[end] = true;
230 bool IsStart(int64_t node) const { return is_start_[node]; }
231 bool IsEnd(int64_t node) const { return is_end_[node]; }
235 int NumPaths() const { return start_of_path_.size(); }
236 const std::vector<int64_t>& Paths() const { return path_of_node_; }
237 const std::vector<int64_t>& Starts() const { return start_of_path_; }
238 int64_t Start(int path) const { return start_of_path_[path]; }
239 int64_t End(int path) const { return end_of_path_[path]; }
240 const std::vector<int64_t>& Ends() const { return end_of_path_; }
243 std::vector<bool> is_start_;
244 std::vector<bool> is_end_;
245 std::vector<int64_t> start_of_path_;
246 std::vector<int64_t> end_of_path_;
410 class ResourceGroup {
435 Domain start_domain_;
441 class Resource {
445 return index < dimension_attributes_per_index_.size()
453 SetDimensionAttributes(std::move(attributes), dimension);
460 absl::flat_hash_map<DimensionIndex, int> dimension_attributes_;
462 dimension_attributes_per_index_;
486 int vehicle, const std::vector<int>& allowed_resource_indices) {
491 DCHECK(!allowed_resource_indices.empty());
492 DCHECK(vehicle_requires_resource_[vehicle]);
493 DCHECK_LT(vehicle, vehicle_allowed_resources_.size());
494 vehicle_allowed_resources_[vehicle].clear();
495 vehicle_allowed_resources_[vehicle].insert(
496 allowed_resource_indices.begin(), allowed_resource_indices.end());
499 DCHECK_LT(vehicle, vehicle_allowed_resources_.size());
504 DCHECK_LT(vehicle, vehicle_allowed_resources_.size());
508 DCHECK_LT(vehicle, vehicle_allowed_resources_.size());
509 return vehicle_allowed_resources_[vehicle].empty() ||
513 const std::vector<Resource>& GetResources() const { return resources_; }
528 DCHECK_LT(resource_class, resource_indices_per_class_.size());
538 DCHECK_LT(resource_index, resource_class_indices_.size());
543 DCHECK_LT(rc_index, resource_indices_per_class_.size());
544 const std::vector<int>& resource_indices =
545 resource_indices_per_class_[rc_index];
546 DCHECK(!resource_indices.empty());
547 return resources_[resource_indices[0]].GetDimensionAttributes(
551 int Size() const { return resources_.size(); }
552 int Index() const { return index_; }
558 vehicle_requires_resource_(model->vehicles(), false),
559 vehicle_allowed_resources_(model->vehicles()) {}
561 void ComputeResourceClasses();
565 std::vector<Resource> resources_;
568 std::vector<ResourceClassIndex> resource_class_indices_;
571 resource_indices_per_class_;
574 std::vector<bool> vehicle_requires_resource_;
575 std::vector<int> vehicles_requiring_resource_;
580 std::vector<absl::flat_hash_set<int> > vehicle_allowed_resources_;
583 absl::flat_hash_set<DimensionIndex> affected_dimension_indices_;
600 bool Solve(const std::vector<RoutingModel::VariableValuePair>& in_state,
601 std::vector<RoutingModel::VariableValuePair>* out_state);
606 const int64_t solve_period_ = 0;
609 absl::flat_hash_map<operations_research::IntVar*, int> var_to_index_;
647 int RegisterUnaryTransitVector(std::vector<int64_t> values);
648 int RegisterUnaryTransitCallback(
649 TransitCallback1 callback,
650 TransitEvaluatorSign sign = kTransitEvaluatorSignUnknown);
652 int RegisterTransitMatrix(
653 std::vector<std::vector<int64_t> > values);
654 int RegisterTransitCallback(
655 TransitCallback2 callback,
656 TransitEvaluatorSign sign = kTransitEvaluatorSignUnknown);
657 int RegisterCumulDependentTransitCallback(
658 CumulDependentTransitCallback2 callback);
659 int RegisterStateDependentTransitCallback(VariableIndexEvaluator2 callback);
662 CHECK_LT(callback_index, transit_evaluators_.size());
666 CHECK_LT(callback_index, unary_transit_evaluators_.size());
670 int callback_index) const {
671 CHECK_LT(callback_index, cumul_dependent_transit_evaluators_.size());
672 return cumul_dependent_transit_evaluators_[callback_index];
675 int callback_index) const {
676 CHECK_LT(callback_index, state_dependent_transit_evaluators_.size());
677 return state_dependent_transit_evaluators_[callback_index];
702 bool AddDimension(int evaluator_index, int64_t slack_max, int64_t capacity,
703 bool fix_start_cumul_to_zero, const std::string& name);
704 bool AddDimensionWithVehicleTransits(
705 const std::vector<int>& evaluator_indices, int64_t slack_max,
706 int64_t capacity, bool fix_start_cumul_to_zero, const std::string& name);
707 bool AddDimensionWithVehicleCapacity(int evaluator_index, int64_t slack_max,
708 std::vector<int64_t> vehicle_capacities,
709 bool fix_start_cumul_to_zero,
711 bool AddDimensionWithVehicleTransitAndCapacity(
712 const std::vector<int>& evaluator_indices, int64_t slack_max,
713 std::vector<int64_t> vehicle_capacities, bool fix_start_cumul_to_zero,
721 bool AddDimensionWithCumulDependentVehicleTransitAndCapacity(
722 const std::vector<int>& fixed_evaluator_indices,
723 const std::vector<int>& cumul_dependent_evaluator_indices,
724 int64_t slack_max, std::vector<int64_t> vehicle_capacities,
725 bool fix_start_cumul_to_zero, const std::string& name);
735 std::pair<int, bool> AddConstantDimensionWithSlack(
736 int64_t value, int64_t capacity, int64_t slack_max,
737 bool fix_start_cumul_to_zero, const std::string& name);
739 bool fix_start_cumul_to_zero,
740 const std::string& name) {
753 std::pair<int, bool> AddVectorDimension(std::vector<int64_t> values,
755 bool fix_start_cumul_to_zero,
766 std::pair<int, bool> AddMatrixDimension(
767 std::vector<std::vector<int64_t> > values,
768 int64_t capacity, bool fix_start_cumul_to_zero, const std::string& name);
776 const std::vector<int>& pure_transits,
777 const std::vector<int>& dependent_transits,
779 std::vector<int64_t> vehicle_capacities, bool fix_start_cumul_to_zero,
780 const std::string& name) {
781 return AddDimensionDependentDimensionWithVehicleCapacityInternal(
782 pure_transits, dependent_transits, base_dimension, slack_max,
783 std::move(vehicle_capacities), fix_start_cumul_to_zero, name);
787 bool AddDimensionDependentDimensionWithVehicleCapacity(
788 const std::vector<int>& transits, const RoutingDimension* base_dimension,
789 int64_t slack_max, std::vector<int64_t> vehicle_capacities,
790 bool fix_start_cumul_to_zero, const std::string& name);
792 bool AddDimensionDependentDimensionWithVehicleCapacity(
793 int transit, const RoutingDimension* base_dimension, int64_t slack_max,
794 int64_t vehicle_capacity, bool fix_start_cumul_to_zero,
796 bool AddDimensionDependentDimensionWithVehicleCapacity(
797 int pure_transit, int dependent_transit,
799 int64_t vehicle_capacity, bool fix_start_cumul_to_zero,
804 const std::function<int64_t(int64_t)>& f, int64_t domain_start,
809 std::vector<std::string> GetAllDimensionNames() const;
811 const std::vector<RoutingDimension*>& GetDimensions() const {
815 std::vector<RoutingDimension*> GetDimensionsWithSoftOrSpanCosts() const;
817 std::vector<RoutingDimension*> GetUnaryDimensions() const;
820 std::vector<const RoutingDimension*> GetDimensionsWithGlobalCumulOptimizers()
822 std::vector<const RoutingDimension*> GetDimensionsWithLocalCumulOptimizers()
844 bool HasDimension(absl::string_view dimension_name) const;
847 const std::string& dimension_name) const;
851 const std::string& dimension_name) const;
857 DCHECK(dimension_name.empty() || HasDimension(dimension_name));
866 ResourceGroup* AddResourceGroup();
880 const std::vector<int>& GetDimensionResourceGroupIndices(
916 DisjunctionIndex AddDisjunction(const std::vector<int64_t>& indices,
917 int64_t penalty = kNoPenalty,
918 int64_t max_cardinality = 1,
919 PenaltyCostBehavior penalty_cost_behavior =
920 PenaltyCostBehavior::PENALIZE_ONCE);
922 const std::vector<DisjunctionIndex>& GetDisjunctionIndices(
930 void ForEachNodeInDisjunctionWithMaxCardinalityFromIndex(
931 int64_t index, int64_t max_cardinality, F f) const {
933 if (disjunctions_[disjunction].value.max_cardinality == max_cardinality) {
934 for (const int64_t d_index : disjunctions_[disjunction].indices) {
943 const std::vector<int64_t>& GetDisjunctionNodeIndices(
949 int64_t GetDisjunctionPenalty(DisjunctionIndex index) const {
950 return disjunctions_[index].value.penalty;
954 int64_t GetDisjunctionMaxCardinality(DisjunctionIndex index) const {
955 return disjunctions_[index].value.max_cardinality;
959 PenaltyCostBehavior GetDisjunctionPenaltyCostBehavior(
964 int GetNumberOfDisjunctions() const { return disjunctions_.size(); }
991 return same_vehicle_costs_.size();
995 const std::vector<int64_t>& GetSoftSameVehicleIndices(int index) const {
996 return same_vehicle_costs_[index].indices;
999 int64_t GetSoftSameVehicleCost(int index) const {
1007 void SetAllowedVehiclesForIndex(absl::Span<const int> vehicles,
1011 bool IsVehicleAllowedForIndex(int vehicle, int64_t index) const {
1012 return allowed_vehicles_[index].empty() ||
1031 void AddPickupAndDelivery(int64_t pickup, int64_t delivery);
1035 void AddPickupAndDeliverySets(DisjunctionIndex pickup_disjunction,
1036 DisjunctionIndex delivery_disjunction);
1039 struct PickupDeliveryPosition {
1048 int64_t node_index) const;
1051 int64_t node_index) const;
1053 bool IsPickup(int64_t node_index) const {
1054 return index_to_pickup_position_[node_index].pd_pair_index != -1;
1056 bool IsDelivery(int64_t node_index) const {
1057 return index_to_delivery_position_[node_index].pd_pair_index != -1;
1062 void SetPickupAndDeliveryPolicyOfAllVehicles(PickupAndDeliveryPolicy policy);
1063 void SetPickupAndDeliveryPolicyOfVehicle(PickupAndDeliveryPolicy policy,
1065 PickupAndDeliveryPolicy GetPickupAndDeliveryPolicyOfVehicle(
1070 int GetNumOfSingletonNodes() const;
1074 const std::vector<PickupDeliveryPair>& GetPickupAndDeliveryPairs() const {
1075 return pickup_delivery_pairs_;
1079 return pickup_delivery_disjunctions_;
1085 const std::vector<PickupDeliveryPair>&
1086 GetImplicitUniquePickupAndDeliveryPairs() const {
1094 std::optional<int64_t> GetFirstMatchingPickupDeliverySibling(
1095 int64_t node, const std::function<bool(int64_t)>& is_match) const;
1131 return visit_type_components_;
1138 DCHECK(closed_);
1139 return topologically_sorted_visit_types_;
1141 const std::vector<std::vector<std::vector<int>>>&
1154 void AddHardTypeIncompatibility(int type1, int type2);
1164 return !hard_incompatible_types_per_type_index_.empty();
1166 bool HasTemporalTypeIncompatibilities() const {
1167 return !temporal_incompatible_types_per_type_index_.empty();
1183 int dependent_type, absl::flat_hash_set<int> required_type_alternatives);
1189 int dependent_type, absl::flat_hash_set<int> required_type_alternatives);
1196 int dependent_type, absl::flat_hash_set<int> required_type_alternatives);
1200 const std::vector<absl::flat_hash_set<int> >&
1203 const std::vector<absl::flat_hash_set<int> >&
1206 const std::vector<absl::flat_hash_set<int> >&
1212 return !same_vehicle_required_type_alternatives_per_type_index_.empty();
1214 bool HasTemporalTypeRequirements() const {
1215 return !required_type_alternatives_when_adding_type_index_.empty() ||
1236 int64_t var_index) const;
1247 max_active_vehicles_ = max_active_vehicles;
1250 int GetMaximumNumberOfActiveVehicles() const { return max_active_vehicles_; }
1274 const std::string& distance,
1275 int64_t cost_per_unit, int vehicle);
1283 const std::string& distance,
1285 int64_t cost_per_unit_below_threshold,
1286 int64_t cost_per_unit_above_threshold,
1305 int64_t quadratic_cost_factor);
1308 int64_t quadratic_cost_factor,
1312 return linear_cost_factor_of_vehicle_;
1314 const std::vector<int64_t>& GetAmortizedQuadraticCostFactorOfVehicles()
1316 return quadratic_cost_factor_of_vehicle_;
1325 absl::AnyInvocable<std::optional<int64_t>(const std::vector<int64_t>&)>
1327 bool costs_are_homogeneous_across_vehicles = false);
1329 std::optional<int64_t> GetRouteCost(const std::vector<int64_t>& route) const {
1331 for (auto& evaluator : route_evaluators_) {
1332 std::optional<int64_t> cost = evaluator(route);
1333 if (!cost.has_value()) return std::nullopt;
1334 CapAddTo(cost.value(), &route_cost);
1336 return route_cost;
1339 void SetVehicleUsedWhenEmpty(bool is_used, int vehicle) {
1340 DCHECK_LT(vehicle, vehicles_);
1345 DCHECK_LT(vehicle, vehicles_);
1358 first_solution_evaluator_ = std::move(evaluator);
1385 bool track_unchecked_neighbors = false);
1412 int64_t target, int64_t cost);
1441 std::vector<const operations_research::Assignment*>* solutions = nullptr);
1447 std::vector<const operations_research::Assignment*>* solutions = nullptr);
1455 bool check_solution_in_cp,
1456 absl::flat_hash_set<operations_research::IntVar*>* touched = nullptr);
1460 const std::vector<const operations_research::Assignment*>& assignments,
1462 std::vector<const operations_research::Assignment*>* solutions = nullptr);
1491 const RoutingSearchStats& search_stats() const { return search_stats_; }
1493 bool enable_deep_serialization() const { return enable_deep_serialization_; }
1541 const std::vector<std::vector<int64_t>>& routes,
1542 bool ignore_inactive_indices);
1559 bool RoutesToAssignment(const std::vector<std::vector<int64_t>>& routes,
1560 bool ignore_inactive_indices, bool close_routes,
1566 std::vector<std::vector<int64_t>>* routes) const;
1615 absl::Duration duration_limit, bool* time_limit_was_reached = nullptr);
1648 std::string DebugString(std::string line_prefix = "") const;
1657 std::string DebugString(std::string line_prefix = "") const;
1670 bool add_vehicle_starts_to_neighbors = true;
1671 bool add_vehicle_ends_to_neighbors = false;
1690 return H::combine(std::move(h), params.num_neighbors,
1708 int cost_class, int node_index) const {
1709 if (routing_model_.IsStart(node_index)) return empty_neighbors_;
1711 if (node_index_to_incoming_neighbors_by_cost_class_.empty()) {
1713 return all_incoming_nodes_;
1715 const std::vector<std::vector<int>>& node_index_to_incoming_neighbors =
1716 node_index_to_incoming_neighbors_by_cost_class_[cost_class];
1717 if (node_index_to_incoming_neighbors.empty()) {
1720 return node_index_to_incoming_neighbors[node_index];
1726 const std::vector<int>& GetOutgoingNeighborsOfNodeForCostClass(
1727 int cost_class, int node_index) const {
1728 if (routing_model_.IsEnd(node_index)) return empty_neighbors_;
1730 if (node_index_to_outgoing_neighbors_by_cost_class_.empty()) {
1731 DCHECK(IsFullNeighborhood());
1732 return all_outgoing_nodes_;
1734 const std::vector<std::vector<int>>& node_index_to_outgoing_neighbors =
1735 node_index_to_outgoing_neighbors_by_cost_class_[cost_class];
1736 if (node_index_to_outgoing_neighbors.empty()) {
1739 return node_index_to_outgoing_neighbors[node_index];
1744 bool IsNeighborhoodArcForCostClass(int cost_class, int64_t from,
1745 int64_t to) const {
1746 if (node_index_to_outgoing_neighbor_indicator_by_cost_class_.empty()) {
1750 if (routing_model_.IsEnd(from)) {
1753 return node_index_to_outgoing_neighbor_indicator_by_cost_class_
1754 [cost_class][from][to];
1757 bool IsFullNeighborhood() const { return full_neighborhood_; }
1760 const RoutingModel& routing_model_;
1761#if __cplusplus >= 202002L
1762 static constexpr std::vector<int> empty_neighbors_ = {};
1764 inline static const std::vector<int> empty_neighbors_ = {};
1767 std::vector<std::vector<std::vector<int>>>
1768 node_index_to_incoming_neighbors_by_cost_class_;
1769 std::vector<std::vector<std::vector<int>>>
1770 node_index_to_outgoing_neighbors_by_cost_class_;
1771 std::vector<std::vector<std::vector<bool>>>
1772 node_index_to_outgoing_neighbor_indicator_by_cost_class_;
1774 std::vector<int> all_outgoing_nodes_;
1775 std::vector<int> all_incoming_nodes_;
1777 bool full_neighborhood_ = false;
1785 double neighbors_ratio, int64_t min_neighbors,
1786 double& neighbors_ratio_used, bool add_vehicle_starts_to_neighbors = true,
1787 bool add_vehicle_ends_to_neighbors = false,
1788 bool only_sort_neighbors_for_partial_neighborhoods = true);
1799 CHECK(filter != nullptr);
1801 LOG(WARNING) << "Model is closed, filter addition will be ignored.";
1809 int64_t Start(int vehicle) const { return paths_metadata_.Starts()[vehicle]; }
1811 int64_t End(int vehicle) const { return paths_metadata_.Ends()[vehicle]; }
1813 bool IsStart(int64_t index) const { return paths_metadata_.IsStart(index); }
1815 bool IsEnd(int64_t index) const { return paths_metadata_.IsEnd(index); }
1819 return paths_metadata_.GetPath(index);
1833 const std::vector<operations_research::IntVar*>& Nexts() const {
1838 const std::vector<operations_research::IntVar*>& VehicleVars() const {
1844 const std::vector<operations_research::IntVar*>& ResourceVars(
1845 int resource_group) const {
1852 return nexts_[index];
1867 return vehicle_route_considered_[vehicle];
1872 return vehicle_vars_[index];
1878 int resource_group) const {
1879 DCHECK_LT(resource_group, resource_vars_.size());
1880 DCHECK_LT(vehicle, resource_vars_[resource_group].size());
1892 return costs_are_homogeneous_across_vehicles_;
1896 int64_t GetHomogeneousCost(int64_t from_index, int64_t to_index) const {
1897 return GetArcCostForVehicle(from_index, to_index, 0);
1910 int64_t cost_class_index) const;
1915 DCHECK_LT(vehicle, cost_class_index_of_vehicle_.size());
1916 DCHECK_GE(cost_class_index_of_vehicle_[vehicle], 0);
1917 return cost_class_index_of_vehicle_[vehicle];
1923 if (cost_class_index == kCostClassIndexOfZeroCost) {
1931 int GetNonZeroCostClassesCount() const {
1932 return std::max(0, GetCostClassesCount() - 1);
1934 VehicleClassIndex GetVehicleClassIndexOfVehicle(int64_t vehicle) const {
1936 return vehicle_class_index_of_vehicle_[vehicle];
1949 return vehicle_type_container
1954 int GetVehicleClassesCount() const { return num_vehicle_classes_; }
1956 const std::vector<int>& GetSameVehicleIndicesOfIndex(int node) const {
1958 return same_vehicle_groups_[same_vehicle_group_[node]];
1960 void AddSameActivityGroup(absl::Span<const int> nodes) {
1963 for (auto it = nodes.begin() + 1; it != nodes.end(); ++it) {
1971 return same_active_var_groups_[same_active_var_group_[node]];
1976 return same_active_var_group_[node];
1981 return same_active_var_group_;
1986 return same_active_var_groups_.size();
1991 return same_active_var_groups_[group];
1996 void AddOrderedActivityGroup(std::vector<DisjunctionIndex> disjunctions) {
1997 DCHECK(!closed_);
1998 if (disjunctions.size() <= 1) return;
1999 ordered_activity_groups_.push_back(std::move(disjunctions));
2002 const std::vector<std::vector<DisjunctionIndex>>& GetOrderedActivityGroups()
2004 return ordered_activity_groups_;
2007 const VehicleTypeContainer& GetVehicleTypeContainer() const {
2009 return vehicle_type_container_;
2037 const std::string& dimension_to_print) const;
2044 std::vector<std::vector<std::pair<int64_t, int64_t>>> GetCumulBounds(
2051 bool call_at_solution_monitors);
2054 Solver* solver() const { return solver_.get(); }
2058 bool CheckLimit(absl::Duration offset = absl::ZeroDuration()) {
2059 DCHECK(limit_ != nullptr);
2060 return limit_->CheckWithOffset(offset);
2065 DCHECK(limit_ != nullptr);
2070 void UpdateTimeLimit(absl::Duration time_limit) {
2072 limit->UpdateLimits(time_limit, std::numeric_limits<int64_t>::max(),
2078 absl::Duration TimeBuffer() const { return time_buffer_; }
2081 std::atomic<bool>* GetMutableCPSatInterrupt() { return &interrupt_cp_sat_; }
2083 std::atomic<bool>* GetMutableCPInterrupt() { return &interrupt_cp_; }
2086 interrupt_cp_sat_ = true;
2092 int nodes() const { return nodes_; }
2094 int vehicles() const { return vehicles_; }
2096 int64_t Size() const { return nodes_ + vehicles_ - start_end_count_; }
2107 return automatic_first_solution_strategy_;
2111 bool IsMatchingModel() const;
2121 std::function<std::vector<operations_research::IntVar*>(RoutingModel*)>;
2141 std::function<int64_t(int64_t)> initializer);
2149 std::vector<operations_research::IntVar*> variables);
2173 BinCapacities* GetBinCapacities() { return bin_capacities_.get(); }
2177 void SetSecondaryModel(RoutingModel* secondary_model,
2178 RoutingSearchParameters secondary_parameters) {
2180 secondary_model_ = secondary_model;
2181 secondary_parameters_ = std::move(secondary_parameters);
2195 int64_t from_index, int64_t to_index) const;
2199 enum RoutingLocalSearchOperator {
2210 GLOBAL_CHEAPEST_INSERTION_VISIT_TYPES_LNS,
2211 LOCAL_CHEAPEST_INSERTION_VISIT_TYPES_LNS,
2212 GLOBAL_CHEAPEST_INSERTION_CLOSE_NODES_LNS,
2213 LOCAL_CHEAPEST_INSERTION_CLOSE_NODES_LNS,
2214 GLOBAL_CHEAPEST_INSERTION_PATH_LNS,
2215 LOCAL_CHEAPEST_INSERTION_PATH_LNS,
2216 RELOCATE_PATH_GLOBAL_CHEAPEST_INSERTION_INSERT_UNPERFORMED,
2217 GLOBAL_CHEAPEST_INSERTION_EXPENSIVE_CHAIN_LNS,
2218 LOCAL_CHEAPEST_INSERTION_EXPENSIVE_CHAIN_LNS,
2219 RELOCATE_EXPENSIVE_CHAIN,
2223 RELOCATE_AND_MAKE_ACTIVE,
2224 MAKE_ACTIVE_AND_RELOCATE,
2225 EXCHANGE_AND_MAKE_ACTIVE,
2226 EXCHANGE_PATH_START_ENDS_AND_MAKE_ACTIVE,
2232 SHORTEST_PATH_SWAP_ACTIVE,
2242 LOCAL_SEARCH_OPERATOR_COUNTER
2250 std::vector<int64_t> indices;
2253 struct DisjunctionValues {
2256 PenaltyCostBehavior penalty_cost_behavior;
2258 typedef ValuedNodes<DisjunctionValues> Disjunction;
2262 struct CostCacheElement {
2269 CostClassIndex cost_class_index;
2275 template <class DimensionCumulOptimizer>
2276 struct DimensionCumulOptimizers {
2277 std::unique_ptr<DimensionCumulOptimizer> lp_optimizer;
2278 std::unique_ptr<DimensionCumulOptimizer> mp_optimizer;
2283 void AddNoCycleConstraintInternal();
2284 bool AddDimensionWithCapacityInternal(
2285 const std::vector<int>& evaluator_indices,
2286 const std::vector<int>& cumul_dependent_evaluator_indices,
2287 int64_t slack_max, std::vector<int64_t> vehicle_capacities,
2288 bool fix_start_cumul_to_zero, const std::string& name);
2289 bool AddDimensionDependentDimensionWithVehicleCapacityInternal(
2290 const std::vector<int>& pure_transits,
2291 const std::vector<int>& dependent_transits,
2293 std::vector<int64_t> vehicle_capacities, bool fix_start_cumul_to_zero,
2294 const std::string& name);
2295 bool InitializeDimensionInternal(
2296 const std::vector<int>& evaluator_indices,
2297 const std::vector<int>& cumul_dependent_evaluator_indices,
2298 const std::vector<int>& state_dependent_evaluator_indices,
2299 int64_t slack_max, bool fix_start_cumul_to_zero,
2301 DimensionIndex GetDimensionIndex(absl::string_view dimension_name) const;
2337 void FinalizeAllowedVehicles();
2340 void ComputeVehicleClasses();
2348 void ComputeVehicleTypes();
2350 void ComputeResourceClasses();
2360 void FinalizeVisitTypes();
2361 void ComputeVisitTypesConnectedComponents();
2363 void TopologicallySortVisitTypes();
2367 void FinalizePrecedences();
2368 int64_t GetArcCostForClassInternal(int64_t from_index, int64_t to_index,
2369 CostClassIndex cost_class_index) const;
2370 int64_t GetArcCostWithGuidedLocalSearchPenalties(int64_t from_index,
2374 GetArcCostForVehicle(from_index, to_index, vehicle),
2375 solver()->GetGuidedLocalSearchPenalty(from_index, to_index, vehicle));
2377 std::function<int64_t(int64_t, int64_t, int64_t)>
2378 GetLocalSearchArcCostCallback(
2380 int64_t GetHomogeneousArcCostWithGuidedLocalSearchPenalties(
2381 int64_t from_index, int64_t to_index) const {
2382 return GetArcCostWithGuidedLocalSearchPenalties(from_index, to_index,
2385 std::function<int64_t(int64_t, int64_t)>
2386 GetLocalSearchHomogeneousArcCostCallback(
2388 void AppendHomogeneousArcCosts(
2390 std::vector<operations_research::IntVar*>* cost_elements);
2392 std::vector<operations_research::IntVar*>* cost_elements);
2393 operations_research::Assignment* DoRestoreAssignment();
2394 static const CostClassIndex kCostClassIndexOfZeroCost;
2395 int64_t SafeGetCostClassInt64OfVehicle(int64_t vehicle) const {
2397 return (vehicle >= 0 ? GetCostClassIndexOfVehicle(vehicle)
2398 : kCostClassIndexOfZeroCost)
2401 int64_t GetDimensionTransitCostSum(int64_t i, int64_t j,
2402 const CostClass& cost_class) const;
2404 operations_research::IntVar* CreateDisjunction(DisjunctionIndex disjunction);
2406 void AddPickupAndDeliverySetsInternal(const std::vector<int64_t>& pickups,
2407 const std::vector<int64_t>& deliveries);
2410 operations_research::IntVar* CreateSameVehicleCost(int vehicle_index);
2413 int FindNextActive(int index, absl::Span<const int64_t> indices) const;
2417 bool RouteCanBeUsedByVehicle(
2418 const operations_research::Assignment& assignment, int start_index,
2427 bool ReplaceUnusedVehicle(
2428 int unused_vehicle, int active_vehicle,
2429 operations_research::Assignment* compact_assignment) const;
2432 void QuietCloseModelWithParameters(
2435 CloseModelWithParameters(parameters);
2440 bool SolveMatchingModel(operations_research::Assignment* assignment,
2444 bool AppendAssignmentIfFeasible(
2445 const operations_research::Assignment& assignment,
2446 std::vector<std::unique_ptr<operations_research::Assignment>>*
2448 bool call_at_solution_monitors = true);
2452 absl::string_view description, int64_t solution_cost,
2456 operations_research::Assignment* CompactAssignmentInternal(
2457 const operations_research::Assignment& assignment,
2458 bool check_compact_assignment) const;
2461 std::string FindErrorInSearchParametersForModel(
2466 void UpdateSearchFromParametersIfNeeded(
2470 operations_research::Assignment* GetOrCreateAssignment();
2471 operations_research::Assignment* GetOrCreateTmpAssignment();
2474 RegularLimit* GetOrCreateLocalSearchLimit();
2475 RegularLimit* GetOrCreateLargeNeighborhoodSearchLimit();
2476 RegularLimit* GetOrCreateFirstSolutionLargeNeighborhoodSearchLimit();
2482 const std::vector<LocalSearchOperator*>& operators) const;
2485 const absl::flat_hash_set<RoutingLocalSearchOperator>&
2486 operators_to_consider) const;
2490 bool filter_with_cp_solver;
2492 bool operator==(const FilterOptions& other) const {
2493 return other.filter_objective == filter_objective &&
2494 other.filter_with_cp_solver == filter_with_cp_solver;
2497 friend H AbslHashValue(H h, const FilterOptions& options) {
2498 return H::combine(std::move(h), options.filter_objective,
2499 options.filter_with_cp_solver);
2502 std::vector<LocalSearchFilterManager::FilterEvent> CreateLocalSearchFilters(
2508 void CreateFirstSolutionDecisionBuilders(
2515 template <typename Heuristic, typename... Args>
2521 DecisionBuilder* CreatePrimaryLocalSearchDecisionBuilder(
2525 void SetupAssignmentCollector(
2530 bool UsesLightPropagation(
2532 GetTabuVarsCallback tabu_var_callback_;
2538 void DetectImplicitPickupAndDeliveries();
2540 int GetVehicleStartClass(int64_t start) const;
2542 void InitSameVehicleGroups(int number_of_groups) {
2543 same_vehicle_group_.assign(Size(), 0);
2544 same_vehicle_groups_.assign(number_of_groups, {});
2546 void SetSameVehicleGroup(int index, int group) {
2547 same_vehicle_group_[index] = group;
2548 same_vehicle_groups_[group].push_back(index);
2551 void InitSameActiveVarGroups(int number_of_groups) {
2552 same_active_var_group_.assign(Size(), 0);
2553 same_active_var_groups_.assign(number_of_groups, {});
2555 void SetSameActiveVarGroup(int index, int group) {
2556 same_active_var_group_[index] = group;
2557 same_active_var_groups_[group].push_back(index);
2562 int GetGlobalCumulOptimizerIndex(const RoutingDimension& dimension) const;
2563 int GetLocalCumulOptimizerIndex(const RoutingDimension& dimension) const;
2566 std::unique_ptr<Solver> solver_;
2569 int max_active_vehicles_;
2570 Constraint* no_cycle_constraint_ = nullptr;
2572 std::vector<operations_research::IntVar*> nexts_;
2573 std::vector<operations_research::IntVar*> vehicle_vars_;
2574 std::vector<operations_research::IntVar*> active_;
2581 std::vector<std::vector<operations_research::IntVar*> > resource_vars_;
2584 std::vector<operations_research::IntVar*> vehicle_active_;
2585 std::vector<operations_research::IntVar*> vehicle_route_considered_;
2590 std::vector<operations_research::IntVar*> is_bound_to_end_;
2591 mutable RevSwitch is_bound_to_end_ct_added_;
2593 absl::flat_hash_map<std::string, DimensionIndex> dimension_name_to_index_;
2594 util_intops::StrongVector<DimensionIndex, RoutingDimension*> dimensions_;
2600 std::vector<std::unique_ptr<ResourceGroup> > resource_groups_;
2602 util_intops::StrongVector<DimensionIndex, std::vector<int> >
2603 dimension_resource_group_indices_;
2608 std::vector<DimensionCumulOptimizers<GlobalDimensionCumulOptimizer> >
2609 global_dimension_optimizers_;
2610 util_intops::StrongVector<DimensionIndex, int> global_optimizer_index_;
2611 std::vector<DimensionCumulOptimizers<LocalDimensionCumulOptimizer> >
2612 local_dimension_optimizers_;
2613 util_intops::StrongVector<DimensionIndex, int> local_optimizer_index_;
2615 std::string primary_constrained_dimension_;
2617 operations_research::IntVar* cost_ = nullptr;
2618 std::vector<int> vehicle_to_transit_cost_;
2619 std::vector<int64_t> fixed_cost_of_vehicle_;
2620 std::vector<CostClassIndex> cost_class_index_of_vehicle_;
2621 bool has_vehicle_with_zero_cost_class_;
2622 std::vector<int64_t> linear_cost_factor_of_vehicle_;
2623 std::vector<int64_t> quadratic_cost_factor_of_vehicle_;
2624 bool vehicle_amortized_cost_factors_set_;
2626 absl::AnyInvocable<std::optional<int64_t>(const std::vector<int64_t>&)>>
2639 std::vector<bool> vehicle_used_when_empty_;
2642 std::pair<std::string, std::string>,
2643 std::vector<Solver::PathEnergyCostConstraintSpecification::EnergyCost>,
2644 absl::Hash<std::pair<std::string, std::string>>>
2645 force_distance_to_energy_costs_;
2646 util_intops::StrongVector<CostClassIndex, CostClass> cost_classes_;
2648 bool costs_are_homogeneous_across_vehicles_;
2650 mutable std::vector<CostCacheElement> cost_cache_;
2651 std::vector<VehicleClassIndex> vehicle_class_index_of_vehicle_;
2652 int num_vehicle_classes_;
2654 VehicleTypeContainer vehicle_type_container_;
2655 std::function<int(int64_t)> vehicle_start_class_callback_;
2657 util_intops::StrongVector<DisjunctionIndex, Disjunction> disjunctions_;
2659 std::vector<std::vector<DisjunctionIndex> > index_to_disjunctions_;
2661 std::vector<ValuedNodes<int64_t> > same_vehicle_costs_;
2664 std::vector<absl::flat_hash_set<int>> allowed_vehicles_;
2667 std::vector<PickupDeliveryPair> pickup_delivery_pairs_;
2668 std::vector<PickupDeliveryPair>
2669 implicit_pickup_delivery_pairs_without_alternatives_;
2670 std::vector<std::pair<DisjunctionIndex, DisjunctionIndex> >
2671 pickup_delivery_disjunctions_;
2676 std::vector<PickupDeliveryPosition> index_to_pickup_position_;
2678 std::vector<PickupDeliveryPosition> index_to_delivery_position_;
2680 std::vector<PickupAndDeliveryPolicy> vehicle_pickup_delivery_policy_;
2682 std::vector<int> same_vehicle_group_;
2684 std::vector<std::vector<int>> same_vehicle_groups_;
2686 std::vector<int> same_active_var_group_;
2688 std::vector<std::vector<int>> same_active_var_groups_;
2690 std::vector<std::vector<DisjunctionIndex>> ordered_activity_groups_;
2693 std::vector<int> index_to_visit_type_;
2695 std::vector<VisitTypePolicy> index_to_type_policy_;
2697 std::vector<std::vector<int> > single_nodes_of_type_;
2698 std::vector<std::vector<int> > pair_indices_of_type_;
2700 std::vector<absl::flat_hash_set<int> >
2701 hard_incompatible_types_per_type_index_;
2702 std::vector<absl::flat_hash_set<int> >
2703 temporal_incompatible_types_per_type_index_;
2704 const absl::flat_hash_set<int> empty_incompatibility_set_;
2706 std::vector<std::vector<absl::flat_hash_set<int> > >
2707 same_vehicle_required_type_alternatives_per_type_index_;
2708 std::vector<std::vector<absl::flat_hash_set<int> > >
2709 required_type_alternatives_when_adding_type_index_;
2710 std::vector<std::vector<absl::flat_hash_set<int> > >
2711 required_type_alternatives_when_removing_type_index_;
2712 const std::vector<absl::flat_hash_set<int>> empty_required_type_alternatives_;
2713 absl::flat_hash_map<int, absl::flat_hash_set<VisitTypePolicy> >
2714 trivially_infeasible_visit_types_to_policies_;
2731 std::vector<std::vector<int> > topologically_sorted_visit_types_;
2732 std::vector<std::vector<int>> visit_type_components_;
2735 std::vector<std::vector<std::vector<int>>>
2736 topologically_sorted_node_precedences_;
2739 std::vector<int> index_to_equivalence_class_;
2748 bool enable_deep_serialization_ = true;
2753 std::unique_ptr<SecondaryOptimizer> secondary_optimizer_;
2756 std::vector<DecisionBuilder*> first_solution_decision_builders_;
2757 std::vector<IntVarFilteredDecisionBuilder*>
2758 first_solution_filtered_decision_builders_;
2762 const operations_research::Assignment* hint_ = nullptr;
2763 std::vector<LocalSearchOperator*> local_search_operators_;
2764 std::vector<SearchMonitor*> monitors_;
2765 std::vector<SearchMonitor*> secondary_ls_monitors_;
2766 std::vector<SearchMonitor*> at_solution_monitors_;
2767 std::vector<std::function<void()>> restore_dimension_values_reset_callbacks_;
2768 int monitors_before_setup_ = 0;
2769 int monitors_after_setup_ = 0;
2772 bool local_optimum_reached_ = false;
2774 int64_t objective_lower_bound_ = kint64min;
2778 SolutionCollector* optimized_dimensions_assignment_collector_ = nullptr;
2785 operations_research::Assignment* assignment_ = nullptr;
2786 operations_research::Assignment* preassignment_ = nullptr;
2787 operations_research::Assignment* tmp_assignment_ = nullptr;
2790 std::vector<operations_research::IntVar*> extra_vars_;
2791 std::vector<IntervalVar*> extra_intervals_;
2792 std::vector<LocalSearchOperator*> extra_operators_;
2793 absl::flat_hash_map<FilterOptions, LocalSearchFilterManager*>
2794 local_search_filter_managers_;
2795 std::vector<LocalSearchFilterManager::FilterEvent> extra_filters_;
2796 absl::flat_hash_map<NodeNeighborsParameters,
2797 std::unique_ptr<NodeNeighborsByCostClass>>
2798 node_neighbors_by_cost_class_per_size_;
2799 std::unique_ptr<FinalizerVariables> finalizer_variables_;
2801 std::unique_ptr<SweepArranger> sweep_arranger_;
2808 RegularLimit* first_solution_lns_limit_ = nullptr;
2809 absl::Duration time_buffer_;
2813 std::atomic<bool> interrupt_cp_sat_;
2814 std::atomic<bool> interrupt_cp_;
2816 typedef std::pair<int64_t, int64_t> CacheKey;
2817 typedef absl::flat_hash_map<CacheKey, int64_t> TransitCallbackCache;
2818 typedef absl::flat_hash_map<CacheKey, StateDependentTransit>
2819 StateDependentTransitCallbackCache;
2829 std::vector<TransitCallback1> unary_transit_evaluators_;
2830 std::vector<TransitCallback2> transit_evaluators_;
2831 std::vector<TransitEvaluatorSign> transit_evaluator_sign_;
2833 std::vector<VariableIndexEvaluator2> state_dependent_transit_evaluators_;
2834 std::vector<std::unique_ptr<StateDependentTransitCallbackCache>>
2835 state_dependent_transit_evaluators_cache_;
2837 std::vector<CumulDependentTransitCallback2>
2838 cumul_dependent_transit_evaluators_;
2841 std::unique_ptr<BinCapacities> bin_capacities_;
2845 friend class ResourceGroup::Resource;
2852 static const char kLightElement[];
2853 static const char kLightElement2[];
2854 static const char kRemoveValues[];
2857#if !defined(SWIG)
2880 int num_type_added_to_vehicle = 0;
2886 int num_type_removed_from_vehicle = 0;
2908 const std::function<int64_t(int64_t)>& next_accessor);
2913 virtual bool FinalizeCheck() const { return true; }
2918 std::vector<TypePolicyOccurrence> occurrences_of_type_;
2919 std::vector<int64_t> current_route_visits_;
2926 bool check_hard_incompatibilities);
2946 bool HasRegulationsToCheck() const override;
2947 void OnInitializeCheck() override {
2948 types_with_same_vehicle_requirements_on_route_.clear();
2953 bool CheckRequiredTypesCurrentlyOnRoute(
2954 absl::Span<const absl::flat_hash_set<int>> required_type_alternatives,
2957 bool CheckTypeRegulations(int type, VisitTypePolicy policy, int pos) override;
2958 bool FinalizeCheck() const override;
2960 absl::flat_hash_set<int> types_with_same_vehicle_requirements_on_route_;
3052 std::vector<BoundCost> bound_costs_;
3093 return model_->TransitCallback(class_evaluators_[vehicle_class])(from_index,
3099 return cumuls_[index];
3105 return fixed_transits_[index];
3130 const std::vector<operations_research::IntVar*>& fixed_transits() const {
3133 const std::vector<operations_research::IntVar*>& transits() const {
3139#if !defined(SWIGCSHARP) && !defined(SWIGJAVA)
3142 return forbidden_intervals_;
3150 int64_t min_value) const {
3151 DCHECK_LT(index, forbidden_intervals_.size());
3153 forbidden_intervals_[index];
3159 return CapAdd(first_forbidden_interval_it->end, 1);
3169 int64_t max_value) const {
3170 DCHECK_LT(index, forbidden_intervals_.size());
3172 forbidden_intervals_[index];
3173 const auto last_forbidden_interval_it =
3176 max_value <= last_forbidden_interval_it->end) {
3178 return CapSub(last_forbidden_interval_it->start, 1);
3184 const std::vector<int64_t>& vehicle_capacities() const {
3185 return vehicle_capacities_;
3190 return model_->TransitCallback(
3191 class_evaluators_[vehicle_to_class_[vehicle]]);
3197 RoutingVehicleClassIndex vehicle_class) const {
3198 const int vehicle = model_->GetVehicleOfClass(vehicle_class);
3206 if (model_->UnaryTransitCallbackOrNull(evaluator_index) == nullptr) {
3218 return model_->UnaryTransitCallbackOrNull(
3223 return model_->TransitCallback(
3224 class_evaluators_[vehicle_to_class_[vehicle]]);
3228 bool AreVehicleTransitsPositive(int vehicle) const {
3229 const int evaluator_index = class_evaluators_[vehicle_to_class_[vehicle]];
3230 return model()->transit_evaluator_sign_[evaluator_index] ==
3233 bool AllTransitEvaluatorSignsAreUnknown() const;
3234 RoutingModel::TransitEvaluatorSign GetTransitEvaluatorSign(
3235 int vehicle) const {
3236 const int evaluator_index = class_evaluators_[vehicle_to_class_[vehicle]];
3237 return model()->transit_evaluator_sign_[evaluator_index];
3239 int vehicle_to_class(int vehicle) const { return vehicle_to_class_[vehicle]; }
3241 if (vehicle_to_cumul_dependent_class_.empty()) {
3244 DCHECK_LT(vehicle, vehicle_to_cumul_dependent_class_.size());
3245 return vehicle_to_cumul_dependent_class_[vehicle];
3291 int64_t index) const;
3356 int pre_travel_evaluator,
3357 int post_travel_evaluator);
3362 std::vector<int64_t> node_visit_transits);
3379 std::vector<IntervalVar*> breaks, int vehicle,
3380 std::vector<int64_t> node_visit_transits,
3381 std::function<int64_t(int64_t, int64_t)> delays);
3389 const std::vector<std::pair<int64_t, int64_t> >&
3405 int64_t ShortestTransitionSlack(int64_t node) const;
3408 operations_research::RoutingDimensionIndex index() const {
3412 const std::string& name() const { return name_; }
3416 const ReverseArcListGraph<int, int>& GetPathPrecedenceGraph() const {
3417 return path_precedence_graph_;
3439 int delivery_alternative_index) const;
3445 enum class PerformedConstraint {
3447 kFirstAndSecondIndependent,
3455 PerformedConstraint performed_constraint;
3458 void AddNodePrecedence(NodePrecedence precedence) {
3459 node_precedences_.push_back(precedence);
3462 return node_precedences_;
3481 if (first_unperformed) {
3485 if (second_unperformed) return PrecedenceStatus::kInactive;
3488 if (second_unperformed) {
3492 if (first_unperformed) return PrecedenceStatus::kInactive;
3494 case NodePrecedence::PerformedConstraint::kFirstAndSecondEqual:
3495 if (first_unperformed != second_unperformed) {
3496 return PrecedenceStatus::kInvalid;
3498 if (first_unperformed) return PrecedenceStatus::kInactive;
3501 return PrecedenceStatus::kActive;
3504 int64_t first_node, int64_t second_node, int64_t offset,
3505 NodePrecedence::PerformedConstraint performed_constraint =
3506 NodePrecedence::PerformedConstraint::kFirstAndSecondIndependent) {
3507 AddNodePrecedence({first_node, second_node, offset, performed_constraint});
3510 void AddNodePrecedence(int64_t first_node, int64_t second_node,
3513 {first_node, second_node, offset,
3514 NodePrecedence::PerformedConstraint::kFirstAndSecondIndependent});
3518 int64_t GetSpanUpperBoundForVehicle(int vehicle) const {
3519 return vehicle_span_upper_bounds_[vehicle];
3522 const std::vector<int64_t>& vehicle_span_upper_bounds() const {
3523 return vehicle_span_upper_bounds_;
3526 int64_t GetSpanCostCoefficientForVehicle(int vehicle) const {
3530 int64_t GetSpanCostCoefficientForVehicleClass(
3531 RoutingVehicleClassIndex vehicle_class) const {
3532 const int vehicle = model_->GetVehicleOfClass(vehicle_class);
3534 return GetSpanCostCoefficientForVehicle(vehicle);
3546#endif
3552 RoutingVehicleClassIndex vehicle_class) const {
3553 const int vehicle = model_->GetVehicleOfClass(vehicle_class);
3562 int64_t GetGlobalOptimizerOffset() const {
3566 int64_t GetLocalOptimizerOffsetForVehicle(int vehicle) const {
3570 DCHECK_GE(local_optimizer_offset_for_vehicle_[vehicle], 0);
3571 return local_optimizer_offset_for_vehicle_[vehicle];
3576 void SetSoftSpanUpperBoundForVehicle(BoundCost bound_cost, int vehicle) {
3577 if (!HasSoftSpanUpperBounds()) {
3578 vehicle_soft_span_upper_bound_ = std::make_unique<SimpleBoundCosts>(
3579 model_->vehicles(), BoundCost{kint64max, 0});
3581 vehicle_soft_span_upper_bound_->bound_cost(vehicle) = bound_cost;
3588 return vehicle_soft_span_upper_bound_->bound_cost(vehicle);
3592 void SetQuadraticCostSoftSpanUpperBoundForVehicle(BoundCost bound_cost,
3594 if (!HasQuadraticCostSoftSpanUpperBounds()) {
3595 vehicle_quadratic_cost_soft_span_upper_bound_ =
3596 std::make_unique<SimpleBoundCosts>(model_->vehicles(),
3599 vehicle_quadratic_cost_soft_span_upper_bound_->bound_cost(vehicle) =
3603 return vehicle_quadratic_cost_soft_span_upper_bound_ != nullptr;
3605 BoundCost GetQuadraticCostSoftSpanUpperBoundForVehicle(int vehicle) const {
3617 struct PiecewiseLinearCost {
3618 PiecewiseLinearCost() : var(nullptr), cost(nullptr) {}
3628 const std::string& name, SelfBased);
3629 void Initialize(absl::Span<const int> transit_evaluators,
3630 absl::Span<const int> cumul_dependent_transit_evaluators,
3631 absl::Span<const int> state_dependent_transit_evaluators,
3635 absl::Span<const int> transit_evaluators,
3636 absl::Span<const int> cumul_dependent_transit_evaluators,
3637 absl::Span<const int> state_dependent_transit_evaluators,
3639 void InitializeTransitVariables(int64_t slack_max);
3641 void SetupCumulVarSoftUpperBoundCosts(
3642 std::vector<operations_research::IntVar*>* cost_elements) const;
3644 void SetupCumulVarSoftLowerBoundCosts(
3645 std::vector<operations_research::IntVar*>* cost_elements) const;
3646 void SetupCumulVarPiecewiseLinearCosts(
3647 std::vector<operations_research::IntVar*>* cost_elements) const;
3650 void SetupGlobalSpanCost(
3651 std::vector<operations_research::IntVar*>* cost_elements) const;
3652 void SetupSlackAndDependentTransitCosts() const;
3654 void CloseModel(bool use_light_propagation);
3656 void SetOffsetForGlobalOptimizer(int64_t offset) {
3657 global_optimizer_offset_ = std::max(Zero(), offset);
3660 void SetVehicleOffsetsForLocalOptimizer(std::vector<int64_t> offsets) {
3662 std::transform(offsets.begin(), offsets.end(), offsets.begin(),
3663 [](int64_t offset) { return std::max(Zero(), offset); });
3664 local_optimizer_offset_for_vehicle_ = std::move(offsets);
3667 std::vector<operations_research::IntVar*> cumuls_;
3668 std::vector<SortedDisjointIntervalList> forbidden_intervals_;
3669 std::vector<operations_research::IntVar*> capacity_vars_;
3670 const std::vector<int64_t> vehicle_capacities_;
3671 std::vector<operations_research::IntVar*> transits_;
3672 std::vector<operations_research::IntVar*> fixed_transits_;
3675 std::vector<int> class_evaluators_;
3676 std::vector<int> vehicle_to_class_;
3681 std::vector<int> cumul_dependent_class_evaluators_;
3682 std::vector<int> vehicle_to_cumul_dependent_class_;
3690 std::vector<NodePrecedence> node_precedences_;
3695 const RoutingDimension* const base_dimension_;
3699 std::vector<int> state_dependent_class_evaluators_;
3700 std::vector<int> state_dependent_vehicle_to_class_;
3705 std::vector<PickupToDeliveryLimitFunction>
3706 pickup_to_delivery_limits_per_pair_index_;
3709 bool break_constraints_are_initialized_ = false;
3711 std::vector<std::vector<IntervalVar*> > vehicle_break_intervals_;
3712 std::vector<std::vector<std::pair<int64_t, int64_t> > >
3713 vehicle_break_distance_duration_;
3718 std::vector<int> vehicle_pre_travel_evaluators_;
3719 std::vector<int> vehicle_post_travel_evaluators_;
3721 std::vector<operations_research::IntVar*> slacks_;
3722 std::vector<operations_research::IntVar*> dependent_transits_;
3723 std::vector<int64_t> vehicle_span_upper_bounds_;
3724 int64_t global_span_cost_coefficient_;
3725 std::vector<int64_t> vehicle_span_cost_coefficients_;
3726 std::vector<int64_t> vehicle_slack_cost_coefficients_;
3727 std::vector<SoftBound> cumul_var_soft_upper_bound_;
3728 std::vector<SoftBound> cumul_var_soft_lower_bound_;
3729 std::vector<PiecewiseLinearCost> cumul_var_piecewise_linear_cost_;
3730 RoutingModel* const model_;
3731 const operations_research::RoutingDimensionIndex index_;
3733 int64_t global_optimizer_offset_;
3734 std::vector<int64_t> local_optimizer_offset_for_vehicle_;
3736 std::unique_ptr<SimpleBoundCosts> vehicle_soft_span_upper_bound_;
3737 std::unique_ptr<SimpleBoundCosts>
3738 vehicle_quadratic_cost_soft_span_upper_bound_;
3739 friend class RoutingModel;
3740 friend class RoutingModelInspector;
3747bool SolveModelWithSat(RoutingModel* model, RoutingSearchStats* search_stats,