1 // Copyright 2010-2021 Google LLC
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 //     http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 
14 /// The vehicle routing library lets one model and solve generic vehicle routing
15 /// problems ranging from the Traveling Salesman Problem to more complex
16 /// problems such as the Capacitated Vehicle Routing Problem with Time Windows.
17 ///
18 /// The objective of a vehicle routing problem is to build routes covering a set
19 /// of nodes minimizing the overall cost of the routes (usually proportional to
20 /// the sum of the lengths of each segment of the routes) while respecting some
21 /// problem-specific constraints (such as the length of a route). A route is
22 /// equivalent to a path connecting nodes, starting/ending at specific
23 /// starting/ending nodes.
24 ///
25 /// The term "vehicle routing" is historical and the category of problems solved
26 /// is not limited to the routing of vehicles: any problem involving finding
27 /// routes visiting a given number of nodes optimally falls under this category
28 /// of problems, such as finding the optimal sequence in a playlist.
29 /// The literature around vehicle routing problems is extremely dense but one
30 /// can find some basic introductions in the following links:
31 /// - http://en.wikipedia.org/wiki/Travelling_salesman_problem
32 /// - http://www.tsp.gatech.edu/history/index.html
33 /// - http://en.wikipedia.org/wiki/Vehicle_routing_problem
34 ///
35 /// The vehicle routing library is a vertical layer above the constraint
36 /// programming library (ortools/constraint_programming:cp).
37 /// One has access to all underlying constrained variables of the vehicle
38 /// routing model which can therefore be enriched by adding any constraint
39 /// available in the constraint programming library.
40 ///
41 /// There are two sets of variables available:
42 /// - path variables:
43 ///   * "next(i)" variables representing the immediate successor of the node
44 ///     corresponding to i; use IndexToNode() to get the node corresponding to
45 ///     a "next" variable value; note that node indices are strongly typed
46 ///     integers (cf. ortools/base/int_type.h);
47 ///   * "vehicle(i)" variables representing the vehicle route to which the
48 ///     node corresponding to i belongs;
49 ///   * "active(i)" boolean variables, true if the node corresponding to i is
50 ///     visited and false if not; this can be false when nodes are either
51 ///     optional or part of a disjunction;
52 ///   * The following relationships hold for all i:
53 ///      active(i) == 0 <=> next(i) == i <=> vehicle(i) == -1,
54 ///      next(i) == j => vehicle(j) == vehicle(i).
55 /// - dimension variables, used when one is accumulating quantities along
56 ///   routes, such as weight or volume carried, distance or time:
57 ///   * "cumul(i,d)" variables representing the quantity of dimension d when
58 ///     arriving at the node corresponding to i;
59 ///   * "transit(i,d)" variables representing the quantity of dimension d added
60 ///     after visiting the node corresponding to i.
61 ///   * The following relationship holds for all (i,d):
62 ///       next(i) == j => cumul(j,d) == cumul(i,d) + transit(i,d).
63 /// Solving the vehicle routing problems is mainly done using approximate
64 /// methods (namely local search,
65 /// cf. http://en.wikipedia.org/wiki/Local_search_(optimization) ), potentially
66 /// combined with exact techniques based on dynamic programming and exhaustive
67 /// tree search.
68 // TODO(user): Add a section on costs (vehicle arc costs, span costs,
69 //                disjunctions costs).
70 //
71 /// Advanced tips: Flags are available to tune the search used to solve routing
72 /// problems. Here is a quick overview of the ones one might want to modify:
73 /// - Limiting the search for solutions:
74 ///   * routing_solution_limit (default: kint64max): stop the search after
75 ///     finding 'routing_solution_limit' improving solutions;
76 ///   * routing_time_limit (default: kint64max): stop the search after
77 ///     'routing_time_limit' milliseconds;
78 /// - Customizing search:
79 ///   * routing_first_solution (default: select the first node with an unbound
80 ///     successor and connect it to the first available node): selects the
81 ///     heuristic to build a first solution which will then be improved by local
82 ///     search; possible values are GlobalCheapestArc (iteratively connect two
83 ///     nodes which produce the cheapest route segment), LocalCheapestArc
84 ///     (select the first node with an unbound successor and connect it to the
85 ///     node which produces the cheapest route segment), PathCheapestArc
86 ///     (starting from a route "start" node, connect it to the node which
87 ///     produces the cheapest route segment, then extend the route by iterating
88 ///     on the last node added to the route).
89 ///   * Local search neighborhoods:
90 ///     - routing_no_lns (default: false): forbids the use of Large Neighborhood
91 ///       Search (LNS); LNS can find good solutions but is usually very slow.
92 ///       Refer to the description of PATHLNS in the LocalSearchOperators enum
93 ///       in constraint_solver.h for more information.
94 ///     - routing_no_tsp (default: true): forbids the use of exact methods to
95 ///       solve "sub"-traveling salesman problems (TSPs) of the current model
96 ///       (such as sub-parts of a route, or one route in a multiple route
97 ///       problem). Uses dynamic programming to solve such TSPs with a maximum
98 ///       size (in number of nodes) up to cp_local_search_tsp_opt_size (flag
99 ///       with a default value of 13 nodes). It is not activated by default
100 ///       because it can slow down the search.
101 ///   * Meta-heuristics: used to guide the search out of local minima found by
102 ///     local search. Note that, in general, a search with metaheuristics
103 ///     activated never stops, therefore one must specify a search limit.
104 ///     Several types of metaheuristics are provided:
105 ///     - routing_guided_local_search (default: false): activates guided local
106 ///       search (cf. http://en.wikipedia.org/wiki/Guided_Local_Search);
107 ///       this is generally the most efficient metaheuristic for vehicle
108 ///       routing;
109 ///     - routing_simulated_annealing (default: false): activates simulated
110 ///       annealing (cf. http://en.wikipedia.org/wiki/Simulated_annealing);
111 ///     - routing_tabu_search (default: false): activates tabu search (cf.
112 ///       http://en.wikipedia.org/wiki/Tabu_search).
113 ///
114 /// Code sample:
115 /// Here is a simple example solving a traveling salesman problem given a cost
116 /// function callback (returns the cost of a route segment):
117 ///
118 /// - Define a custom distance/cost function from an index to another; in this
119 ///   example just returns the sum of the indices:
120 ///
121 ///     int64_t MyDistance(int64_t from, int64_t to) {
122 ///       return from + to;
123 ///     }
124 ///
125 /// - Create a routing model for a given problem size (int number of nodes) and
126 ///   number of routes (here, 1):
127 ///
128 ///     RoutingIndexManager manager(...number of nodes..., 1);
129 ///     RoutingModel routing(manager);
130 ///
131 /// - Set the cost function by registering an std::function<int64_t(int64_t,
132 /// int64_t)> in the model and passing its index as the vehicle cost.
133 ///
134 ///    const int cost = routing.RegisterTransitCallback(MyDistance);
135 ///    routing.SetArcCostEvaluatorOfAllVehicles(cost);
136 ///
137 /// - Find a solution using Solve(), returns a solution if any (owned by
138 ///   routing):
139 ///
140 ///    const Assignment* solution = routing.Solve();
141 ///    CHECK(solution != nullptr);
142 ///
143 /// - Inspect the solution cost and route (only one route here):
144 ///
145 ///    LOG(INFO) << "Cost " << solution->ObjectiveValue();
146 ///    const int route_number = 0;
147 ///    for (int64_t node = routing.Start(route_number);
148 ///         !routing.IsEnd(node);
149 ///         node = solution->Value(routing.NextVar(node))) {
150 ///      LOG(INFO) << manager.IndexToNode(node);
151 ///    }
152 ///
153 ///
154 /// Keywords: Vehicle Routing, Traveling Salesman Problem, TSP, VRP, CVRPTW,
155 /// PDP.
156 
157 #ifndef OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_H_
158 #define OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_H_
159 
160 #include <algorithm>
161 #include <deque>
162 #include <functional>
163 #include <memory>
164 #include <set>
165 #include <string>
166 #include <tuple>
167 #include <utility>
168 #include <vector>
169 
170 #include "absl/container/flat_hash_map.h"
171 #include "absl/container/flat_hash_set.h"
172 #include "absl/functional/bind_front.h"
173 #include "absl/memory/memory.h"
174 #include "absl/time/time.h"
175 #include "ortools/base/int_type.h"
176 #include "ortools/base/integral_types.h"
177 #include "ortools/base/logging.h"
178 #include "ortools/base/macros.h"
179 #include "ortools/base/map_util.h"
180 #include "ortools/base/strong_vector.h"
181 #include "ortools/constraint_solver/constraint_solver.h"
182 #include "ortools/constraint_solver/constraint_solveri.h"
183 #include "ortools/constraint_solver/routing_enums.pb.h"
184 #include "ortools/constraint_solver/routing_index_manager.h"
185 #include "ortools/constraint_solver/routing_parameters.pb.h"
186 #include "ortools/constraint_solver/routing_types.h"
187 #include "ortools/graph/graph.h"
188 #include "ortools/sat/theta_tree.h"
189 #include "ortools/util/bitset.h"
190 #include "ortools/util/piecewise_linear_function.h"
191 #include "ortools/util/range_query_function.h"
192 #include "ortools/util/saturated_arithmetic.h"
193 #include "ortools/util/sorted_interval_list.h"
194 
195 namespace operations_research {
196 
197 class GlobalDimensionCumulOptimizer;
198 class LocalDimensionCumulOptimizer;
199 class LocalSearchPhaseParameters;
200 #ifndef SWIG
201 class IndexNeighborFinder;
202 class IntVarFilteredDecisionBuilder;
203 #endif
204 class RoutingDimension;
205 #ifndef SWIG
206 using util::ReverseArcListGraph;
207 class SweepArranger;
208 #endif
209 
210 class RoutingModel {
211  public:
212   /// Status of the search.
213   enum Status {
214     /// Problem not solved yet (before calling RoutingModel::Solve()).
215     ROUTING_NOT_SOLVED,
216     /// Problem solved successfully after calling RoutingModel::Solve().
217     ROUTING_SUCCESS,
218     /// No solution found to the problem after calling RoutingModel::Solve().
219     ROUTING_FAIL,
220     /// Time limit reached before finding a solution with RoutingModel::Solve().
221     ROUTING_FAIL_TIMEOUT,
222     /// Model, model parameters or flags are not valid.
223     ROUTING_INVALID
224   };
225 
226   /// Types of precedence policy applied to pickup and delivery pairs.
227   enum PickupAndDeliveryPolicy {
228     /// Any precedence is accepted.
229     PICKUP_AND_DELIVERY_NO_ORDER,
230     /// Deliveries must be performed in reverse order of pickups.
231     PICKUP_AND_DELIVERY_LIFO,
232     /// Deliveries must be performed in the same order as pickups.
233     PICKUP_AND_DELIVERY_FIFO
234   };
235   typedef RoutingCostClassIndex CostClassIndex;
236   typedef RoutingDimensionIndex DimensionIndex;
237   typedef RoutingDisjunctionIndex DisjunctionIndex;
238   typedef RoutingVehicleClassIndex VehicleClassIndex;
239   typedef RoutingTransitCallback1 TransitCallback1;
240   typedef RoutingTransitCallback2 TransitCallback2;
241 
242 // TODO(user): Remove all SWIG guards by adding the @ignore in .i.
243 #if !defined(SWIG)
244   typedef RoutingIndexPair IndexPair;
245   typedef RoutingIndexPairs IndexPairs;
246 #endif  // SWIG
247 
248 #if !defined(SWIG)
249   /// What follows is relevant for models with time/state dependent transits.
250   /// Such transits, say from node A to node B, are functions f:
251   /// int64_t->int64_t of the cumuls of a dimension. The user is free to
252   /// implement the abstract RangeIntToIntFunction interface, but it is expected
253   /// that the implementation of each method is quite fast. For
254   /// performance-related reasons, StateDependentTransit keeps an additional
255   /// pointer to a RangeMinMaxIndexFunction, with similar functionality to
256   /// RangeIntToIntFunction, for g(x) = f(x)+x, where f is the transit from A to
257   /// B. In most situations the best solutions are problem-specific, but in case
258   /// of doubt the user may use the MakeStateDependentTransit function from the
259   /// routing library, which works out-of-the-box, with very good running time,
260   /// but memory inefficient in some situations.
261   struct StateDependentTransit {
262     RangeIntToIntFunction* transit;                   /// f(x)
263     RangeMinMaxIndexFunction* transit_plus_identity;  /// g(x) = f(x) + x
264   };
265   typedef std::function<StateDependentTransit(int64_t, int64_t)>
266       VariableIndexEvaluator2;
267 #endif  // SWIG
268 
269 #if !defined(SWIG)
270   struct CostClass {
271     /// Index of the arc cost evaluator, registered in the RoutingModel class.
272     int evaluator_index = 0;
273 
274     /// SUBTLE:
275     /// The vehicle's fixed cost is skipped on purpose here, because we
276     /// can afford to do so:
277     /// - We don't really care about creating "strict" equivalence classes;
278     ///   all we care about is to:
279     ///   1) compress the space of cost callbacks so that
280     ///      we can cache them more efficiently.
281     ///   2) have a smaller IntVar domain thanks to using a "cost class var"
282     ///      instead of the vehicle var, so that we reduce the search space.
283     ///   Both of these are an incentive for *fewer* cost classes. Ignoring
284     ///   the fixed costs can only be good in that regard.
285     /// - The fixed costs are only needed when evaluating the cost of the
286     ///   first arc of the route, in which case we know the vehicle, since we
287     ///   have the route's start node.
288 
289     /// Only dimensions that have non-zero cost evaluator and a non-zero cost
290     /// coefficient (in this cost class) are listed here. Since we only need
291     /// their transit evaluator (the raw version that takes var index, not Node
292     /// Index) and their span cost coefficient, we just store those.
293     /// This is sorted by the natural operator < (and *not* by DimensionIndex).
294     struct DimensionCost {
295       int64_t transit_evaluator_class;
296       int64_t cost_coefficient;
297       const RoutingDimension* dimension;
298       bool operator<(const DimensionCost& cost) const {
299         if (transit_evaluator_class != cost.transit_evaluator_class) {
300           return transit_evaluator_class < cost.transit_evaluator_class;
301         }
302         return cost_coefficient < cost.cost_coefficient;
303       }
304     };
305     std::vector<DimensionCost>
306         dimension_transit_evaluator_class_and_cost_coefficient;
307 
CostClassCostClass308     explicit CostClass(int evaluator_index)
309         : evaluator_index(evaluator_index) {}
310 
311     /// Comparator for STL containers and algorithms.
LessThanCostClass312     static bool LessThan(const CostClass& a, const CostClass& b) {
313       if (a.evaluator_index != b.evaluator_index) {
314         return a.evaluator_index < b.evaluator_index;
315       }
316       return a.dimension_transit_evaluator_class_and_cost_coefficient <
317              b.dimension_transit_evaluator_class_and_cost_coefficient;
318     }
319   };
320 
321   struct VehicleClass {
322     /// The cost class of the vehicle.
323     CostClassIndex cost_class_index;
324     /// Contrarily to CostClass, here we need strict equivalence.
325     int64_t fixed_cost;
326     /// Whether or not the vehicle is used when empty.
327     bool used_when_empty;
328     /// Vehicle start and end equivalence classes. Currently if two vehicles
329     /// have different start/end nodes which are "physically" located at the
330     /// same place, these two vehicles will be considered as non-equivalent
331     /// unless the two indices are in the same class.
332     // TODO(user): Find equivalent start/end nodes wrt dimensions and
333     // callbacks.
334     int start_equivalence_class;
335     int end_equivalence_class;
336     /// Bounds of cumul variables at start and end vehicle nodes.
337     /// dimension_{start,end}_cumuls_{min,max}[d] is the bound for dimension d.
338     absl::StrongVector<DimensionIndex, int64_t> dimension_start_cumuls_min;
339     absl::StrongVector<DimensionIndex, int64_t> dimension_start_cumuls_max;
340     absl::StrongVector<DimensionIndex, int64_t> dimension_end_cumuls_min;
341     absl::StrongVector<DimensionIndex, int64_t> dimension_end_cumuls_max;
342     absl::StrongVector<DimensionIndex, int64_t> dimension_capacities;
343     /// dimension_evaluators[d]->Run(from, to) is the transit value of arc
344     /// from->to for a dimension d.
345     absl::StrongVector<DimensionIndex, int64_t> dimension_evaluator_classes;
346     /// Fingerprint of unvisitable non-start/end nodes.
347     uint64_t unvisitable_nodes_fprint;
348     /// Sorted set of resource groups for which the vehicle requires a resource.
349     std::vector<int> required_resource_group_indices;
350 
351     /// Comparator for STL containers and algorithms.
352     static bool LessThan(const VehicleClass& a, const VehicleClass& b);
353   };
354 #endif  // defined(SWIG)
355 
356   /// Struct used to sort and store vehicles by their type. Two vehicles have
357   /// the same "vehicle type" iff they have the same cost class and start/end
358   /// nodes.
359   struct VehicleTypeContainer {
360     struct VehicleClassEntry {
361       int vehicle_class;
362       int64_t fixed_cost;
363 
364       bool operator<(const VehicleClassEntry& other) const {
365         return std::tie(fixed_cost, vehicle_class) <
366                std::tie(other.fixed_cost, other.vehicle_class);
367       }
368     };
369 
NumTypesVehicleTypeContainer370     int NumTypes() const { return sorted_vehicle_classes_per_type.size(); }
371 
TypeVehicleTypeContainer372     int Type(int vehicle) const {
373       DCHECK_LT(vehicle, type_index_of_vehicle.size());
374       return type_index_of_vehicle[vehicle];
375     }
376 
377     std::vector<int> type_index_of_vehicle;
378     // clang-format off
379     std::vector<std::set<VehicleClassEntry> > sorted_vehicle_classes_per_type;
380     std::vector<std::deque<int> > vehicles_per_vehicle_class;
381     // clang-format on
382   };
383 
384   /// A ResourceGroup defines a set of available Resources with attributes on
385   /// one or multiple dimensions.
386   /// For every ResourceGroup in the model, each (used) vehicle in the solution
387   /// which requires a resource (see NotifyVehicleRequiresResource()) from this
388   /// group must be assigned to exactly 1 resource, and each resource can in
389   /// turn be assigned to at most 1 vehicle requiring it. This
390   /// vehicle-to-resource assignment will apply the corresponding Attributes to
391   /// the dimensions affected by the resource group. NOTE: As of 2021/07, each
392   /// ResourceGroup can only affect a single RoutingDimension at a time, i.e.
393   /// all Resources in a group must apply attributes to the same single
394   /// dimension.
395   class ResourceGroup {
396    public:
397     /// Attributes for a dimension.
398     class Attributes {
399      public:
400       Attributes();
401       Attributes(Domain start_domain, Domain end_domain);
402 
start_domain()403       const Domain& start_domain() const { return start_domain_; }
end_domain()404       const Domain& end_domain() const { return end_domain_; }
405 
406      private:
407       /// The following domains constrain the dimension start/end cumul of the
408       /// the vehicle assigned to this resource:
409       /// start_domain_.Min() <= cumul[Start(v)] <= start_domain_.Max()
410       Domain start_domain_;
411       /// end_domain_.Min() <= cumul[End(v)] <= end_domain_.Max()
412       Domain end_domain_;
413     };
414 
415     /// A Resource sets attributes (costs/constraints) for a set of dimensions.
416     class Resource {
417      public:
418       const ResourceGroup::Attributes& GetDimensionAttributes(
419           const RoutingDimension* dimension) const;
420 
421      private:
Resource(const RoutingModel * model)422       explicit Resource(const RoutingModel* model) : model_(model) {}
423 
424       void SetDimensionAttributes(ResourceGroup::Attributes attributes,
425                                   const RoutingDimension* dimension);
426       const ResourceGroup::Attributes& GetDefaultAttributes() const;
427 
428       const RoutingModel* const model_;
429       absl::flat_hash_map<DimensionIndex, ResourceGroup::Attributes>
430           dimension_attributes_;
431 
432       friend class ResourceGroup;
433     };
434 
ResourceGroup(const RoutingModel * model)435     explicit ResourceGroup(const RoutingModel* model)
436         : model_(model), vehicle_requires_resource_(model->vehicles(), false) {}
437 
438     /// Adds a Resource with the given attributes for the corresponding
439     /// dimension. Returns the index of the added resource in resources_.
440     int AddResource(Attributes attributes, const RoutingDimension* dimension);
441 
442     /// Notifies that the given vehicle index requires a resource from this
443     /// group if the vehicle is used (i.e. if its route is non-empty or
444     /// vehicle_used_when_empty_[vehicle] is true).
445     void NotifyVehicleRequiresAResource(int vehicle);
446 
GetVehiclesRequiringAResource()447     const std::vector<int>& GetVehiclesRequiringAResource() const {
448       return vehicles_requiring_resource_;
449     }
450 
VehicleRequiresAResource(int vehicle)451     bool VehicleRequiresAResource(int vehicle) const {
452       return vehicle_requires_resource_[vehicle];
453     }
454 
GetResources()455     const std::vector<Resource>& GetResources() const { return resources_; }
GetResource(int resource_index)456     const Resource& GetResource(int resource_index) const {
457       DCHECK_LT(resource_index, resources_.size());
458       return resources_[resource_index];
459     }
GetAffectedDimensionIndices()460     const absl::flat_hash_set<DimensionIndex>& GetAffectedDimensionIndices()
461         const {
462       return affected_dimension_indices_;
463     }
Size()464     int Size() const { return resources_.size(); }
465 
466    private:
467     const RoutingModel* const model_;
468     std::vector<Resource> resources_;
469     std::vector<bool> vehicle_requires_resource_;
470     std::vector<int> vehicles_requiring_resource_;
471     /// All indices of dimensions affected by this resource group.
472     absl::flat_hash_set<DimensionIndex> affected_dimension_indices_;
473   };
474 
475   /// Constant used to express a hard constraint instead of a soft penalty.
476   static const int64_t kNoPenalty;
477 
478   /// Constant used to express the "no disjunction" index, returned when a node
479   /// does not appear in any disjunction.
480   static const DisjunctionIndex kNoDisjunction;
481 
482   /// Constant used to express the "no dimension" index, returned when a
483   /// dimension name does not correspond to an actual dimension.
484   static const DimensionIndex kNoDimension;
485 
486   /// Constructor taking an index manager. The version which does not take
487   /// RoutingModelParameters is equivalent to passing
488   /// DefaultRoutingModelParameters().
489   explicit RoutingModel(const RoutingIndexManager& index_manager);
490   RoutingModel(const RoutingIndexManager& index_manager,
491                const RoutingModelParameters& parameters);
492   ~RoutingModel();
493 
494   /// Registers 'callback' and returns its index.
495   int RegisterUnaryTransitVector(std::vector<int64_t> values);
496   int RegisterUnaryTransitCallback(TransitCallback1 callback);
497   int RegisterPositiveUnaryTransitCallback(TransitCallback1 callback);
498 
499   int RegisterTransitMatrix(
500       std::vector<std::vector<int64_t> /*needed_for_swig*/> values);
501   int RegisterTransitCallback(TransitCallback2 callback);
502   int RegisterPositiveTransitCallback(TransitCallback2 callback);
503 
504   int RegisterStateDependentTransitCallback(VariableIndexEvaluator2 callback);
TransitCallback(int callback_index)505   const TransitCallback2& TransitCallback(int callback_index) const {
506     CHECK_LT(callback_index, transit_evaluators_.size());
507     return transit_evaluators_[callback_index];
508   }
UnaryTransitCallbackOrNull(int callback_index)509   const TransitCallback1& UnaryTransitCallbackOrNull(int callback_index) const {
510     CHECK_LT(callback_index, unary_transit_evaluators_.size());
511     return unary_transit_evaluators_[callback_index];
512   }
StateDependentTransitCallback(int callback_index)513   const VariableIndexEvaluator2& StateDependentTransitCallback(
514       int callback_index) const {
515     CHECK_LT(callback_index, state_dependent_transit_evaluators_.size());
516     return state_dependent_transit_evaluators_[callback_index];
517   }
518 
519   /// Model creation
520 
521   /// Methods to add dimensions to routes; dimensions represent quantities
522   /// accumulated at nodes along the routes. They represent quantities such as
523   /// weights or volumes carried along the route, or distance or times.
524   /// Quantities at a node are represented by "cumul" variables and the increase
525   /// or decrease of quantities between nodes are represented by "transit"
526   /// variables. These variables are linked as follows:
527   /// if j == next(i), cumul(j) = cumul(i) + transit(i) + slack(i)
528   /// where slack is a positive slack variable (can represent waiting times for
529   /// a time dimension).
530   /// Setting the value of fix_start_cumul_to_zero to true will force the
531   /// "cumul" variable of the start node of all vehicles to be equal to 0.
532 
533   /// Creates a dimension where the transit variable is constrained to be
534   /// equal to evaluator(i, next(i)); 'slack_max' is the upper bound of the
535   /// slack variable and 'capacity' is the upper bound of the cumul variables.
536   /// 'name' is the name used to reference the dimension; this name is used to
537   /// get cumul and transit variables from the routing model.
538   /// Returns false if a dimension with the same name has already been created
539   /// (and doesn't create the new dimension).
540   /// Takes ownership of the callback 'evaluator'.
541   bool AddDimension(int evaluator_index, int64_t slack_max, int64_t capacity,
542                     bool fix_start_cumul_to_zero, const std::string& name);
543   bool AddDimensionWithVehicleTransits(
544       const std::vector<int>& evaluator_indices, int64_t slack_max,
545       int64_t capacity, bool fix_start_cumul_to_zero, const std::string& name);
546   bool AddDimensionWithVehicleCapacity(int evaluator_index, int64_t slack_max,
547                                        std::vector<int64_t> vehicle_capacities,
548                                        bool fix_start_cumul_to_zero,
549                                        const std::string& name);
550   bool AddDimensionWithVehicleTransitAndCapacity(
551       const std::vector<int>& evaluator_indices, int64_t slack_max,
552       std::vector<int64_t> vehicle_capacities, bool fix_start_cumul_to_zero,
553       const std::string& name);
554   /// Creates a dimension where the transit variable is constrained to be
555   /// equal to 'value'; 'capacity' is the upper bound of the cumul variables.
556   /// 'name' is the name used to reference the dimension; this name is used to
557   /// get cumul and transit variables from the routing model.
558   /// Returns a pair consisting of an index to the registered unary transit
559   /// callback and a bool denoting whether the dimension has been created.
560   /// It is false if a dimension with the same name has already been created
561   /// (and doesn't create the new dimension but still register a new callback).
562   std::pair<int, bool> AddConstantDimensionWithSlack(
563       int64_t value, int64_t capacity, int64_t slack_max,
564       bool fix_start_cumul_to_zero, const std::string& name);
AddConstantDimension(int64_t value,int64_t capacity,bool fix_start_cumul_to_zero,const std::string & name)565   std::pair<int, bool> AddConstantDimension(int64_t value, int64_t capacity,
566                                             bool fix_start_cumul_to_zero,
567                                             const std::string& name) {
568     return AddConstantDimensionWithSlack(value, capacity, 0,
569                                          fix_start_cumul_to_zero, name);
570   }
571   /// Creates a dimension where the transit variable is constrained to be
572   /// equal to 'values[i]' for node i; 'capacity' is the upper bound of
573   /// the cumul variables. 'name' is the name used to reference the dimension;
574   /// this name is used to get cumul and transit variables from the routing
575   /// model.
576   /// Returns a pair consisting of an index to the registered unary transit
577   /// callback and a bool denoting whether the dimension has been created.
578   /// It is false if a dimension with the same name has already been created
579   /// (and doesn't create the new dimension but still register a new callback).
580   std::pair<int, bool> AddVectorDimension(std::vector<int64_t> values,
581                                           int64_t capacity,
582                                           bool fix_start_cumul_to_zero,
583                                           const std::string& name);
584   /// Creates a dimension where the transit variable is constrained to be
585   /// equal to 'values[i][next(i)]' for node i; 'capacity' is the upper bound of
586   /// the cumul variables. 'name' is the name used to reference the dimension;
587   /// this name is used to get cumul and transit variables from the routing
588   /// model.
589   /// Returns a pair consisting of an index to the registered transit callback
590   /// and a bool denoting whether the dimension has been created.
591   /// It is false if a dimension with the same name has already been created
592   /// (and doesn't create the new dimension but still register a new callback).
593   std::pair<int, bool> AddMatrixDimension(
594       std::vector<std::vector<int64_t> /*needed_for_swig*/> values,
595       int64_t capacity, bool fix_start_cumul_to_zero, const std::string& name);
596   /// Creates a dimension with transits depending on the cumuls of another
597   /// dimension. 'pure_transits' are the per-vehicle fixed transits as above.
598   /// 'dependent_transits' is a vector containing for each vehicle an index to a
599   /// registered state dependent transit callback. 'base_dimension' indicates
600   /// the dimension from which the cumul variable is taken. If 'base_dimension'
601   /// is nullptr, then the newly created dimension is self-based.
AddDimensionDependentDimensionWithVehicleCapacity(const std::vector<int> & pure_transits,const std::vector<int> & dependent_transits,const RoutingDimension * base_dimension,int64_t slack_max,std::vector<int64_t> vehicle_capacities,bool fix_start_cumul_to_zero,const std::string & name)602   bool AddDimensionDependentDimensionWithVehicleCapacity(
603       const std::vector<int>& pure_transits,
604       const std::vector<int>& dependent_transits,
605       const RoutingDimension* base_dimension, int64_t slack_max,
606       std::vector<int64_t> vehicle_capacities, bool fix_start_cumul_to_zero,
607       const std::string& name) {
608     return AddDimensionDependentDimensionWithVehicleCapacityInternal(
609         pure_transits, dependent_transits, base_dimension, slack_max,
610         std::move(vehicle_capacities), fix_start_cumul_to_zero, name);
611   }
612 
613   /// As above, but pure_transits are taken to be zero evaluators.
614   bool AddDimensionDependentDimensionWithVehicleCapacity(
615       const std::vector<int>& transits, const RoutingDimension* base_dimension,
616       int64_t slack_max, std::vector<int64_t> vehicle_capacities,
617       bool fix_start_cumul_to_zero, const std::string& name);
618   /// Homogeneous versions of the functions above.
619   bool AddDimensionDependentDimensionWithVehicleCapacity(
620       int transit, const RoutingDimension* base_dimension, int64_t slack_max,
621       int64_t vehicle_capacity, bool fix_start_cumul_to_zero,
622       const std::string& name);
623   bool AddDimensionDependentDimensionWithVehicleCapacity(
624       int pure_transit, int dependent_transit,
625       const RoutingDimension* base_dimension, int64_t slack_max,
626       int64_t vehicle_capacity, bool fix_start_cumul_to_zero,
627       const std::string& name);
628 
629   /// Creates a cached StateDependentTransit from an std::function.
630   static RoutingModel::StateDependentTransit MakeStateDependentTransit(
631       const std::function<int64_t(int64_t)>& f, int64_t domain_start,
632       int64_t domain_end);
633 
634   /// For every vehicle of the routing model:
635   /// - if total_slacks[vehicle] is not nullptr, constrains it to be the sum of
636   ///   slacks on that vehicle, that is,
637   ///   dimension->CumulVar(end) - dimension->CumulVar(start) -
638   ///   sum_{node in path of vehicle} dimension->FixedTransitVar(node).
639   /// - if spans[vehicle] is not nullptr, constrains it to be
640   ///   dimension->CumulVar(end) - dimension->CumulVar(start)
641   /// This does stronger propagation than a decomposition, and takes breaks into
642   /// account.
643   Constraint* MakePathSpansAndTotalSlacks(const RoutingDimension* dimension,
644                                           std::vector<IntVar*> spans,
645                                           std::vector<IntVar*> total_slacks);
646 
647   /// Outputs the names of all dimensions added to the routing engine.
648   // TODO(user): rename.
649   std::vector<std::string> GetAllDimensionNames() const;
650   /// Returns all dimensions of the model.
GetDimensions()651   const std::vector<RoutingDimension*>& GetDimensions() const {
652     return dimensions_.get();
653   }
654   /// Returns dimensions with soft or vehicle span costs.
655   std::vector<RoutingDimension*> GetDimensionsWithSoftOrSpanCosts() const;
656   // clang-format off
657   /// Returns [global|local]_dimension_optimizers_, which are empty if the model
658   /// has not been closed.
659   const std::vector<std::unique_ptr<GlobalDimensionCumulOptimizer> >&
GetGlobalDimensionCumulOptimizers()660   GetGlobalDimensionCumulOptimizers() const {
661     return global_dimension_optimizers_;
662   }
663   const std::vector<std::unique_ptr<GlobalDimensionCumulOptimizer> >&
GetGlobalDimensionCumulMPOptimizers()664   GetGlobalDimensionCumulMPOptimizers() const {
665     return global_dimension_mp_optimizers_;
666   }
667   const std::vector<std::unique_ptr<LocalDimensionCumulOptimizer> >&
GetLocalDimensionCumulOptimizers()668   GetLocalDimensionCumulOptimizers() const {
669     return local_dimension_optimizers_;
670   }
671   const std::vector<std::unique_ptr<LocalDimensionCumulOptimizer> >&
GetLocalDimensionCumulMPOptimizers()672   GetLocalDimensionCumulMPOptimizers() const {
673     return local_dimension_mp_optimizers_;
674   }
675   // clang-format on
676 
677   /// Returns the global/local dimension cumul optimizer for a given dimension,
678   /// or nullptr if there is none.
679   GlobalDimensionCumulOptimizer* GetMutableGlobalCumulOptimizer(
680       const RoutingDimension& dimension) const;
681   GlobalDimensionCumulOptimizer* GetMutableGlobalCumulMPOptimizer(
682       const RoutingDimension& dimension) const;
683   LocalDimensionCumulOptimizer* GetMutableLocalCumulOptimizer(
684       const RoutingDimension& dimension) const;
685   LocalDimensionCumulOptimizer* GetMutableLocalCumulMPOptimizer(
686       const RoutingDimension& dimension) const;
687 
688   /// Returns true if a dimension exists for a given dimension name.
689   bool HasDimension(const std::string& dimension_name) const;
690   /// Returns a dimension from its name. Dies if the dimension does not exist.
691   const RoutingDimension& GetDimensionOrDie(
692       const std::string& dimension_name) const;
693   /// Returns a dimension from its name. Returns nullptr if the dimension does
694   /// not exist.
695   RoutingDimension* GetMutableDimension(
696       const std::string& dimension_name) const;
697   /// Set the given dimension as "primary constrained". As of August 2013, this
698   /// is only used by ArcIsMoreConstrainedThanArc().
699   /// "dimension" must be the name of an existing dimension, or be empty, in
700   /// which case there will not be a primary dimension after this call.
SetPrimaryConstrainedDimension(const std::string & dimension_name)701   void SetPrimaryConstrainedDimension(const std::string& dimension_name) {
702     DCHECK(dimension_name.empty() || HasDimension(dimension_name));
703     primary_constrained_dimension_ = dimension_name;
704   }
705   /// Get the primary constrained dimension, or an empty string if it is unset.
GetPrimaryConstrainedDimension()706   const std::string& GetPrimaryConstrainedDimension() const {
707     return primary_constrained_dimension_;
708   }
709 
710   /// Adds a resource group to the routing model. Returns its index in
711   /// resource_groups_.
712   int AddResourceGroup();
713   // clang-format off
GetResourceGroups()714   const std::vector<std::unique_ptr<ResourceGroup> >& GetResourceGroups()
715       const {
716     return resource_groups_;
717   }
718   // clang-format on
GetResourceGroup(int rg_index)719   ResourceGroup* GetResourceGroup(int rg_index) const {
720     DCHECK_LT(rg_index, resource_groups_.size());
721     return resource_groups_[rg_index].get();
722   }
723 
724   /// Returns the indices of resource groups for this dimension. This method can
725   /// only be called after the model has been closed.
726   const std::vector<int>& GetDimensionResourceGroupIndices(
727       const RoutingDimension* dimension) const;
728 
729   /// Returns the index of the resource group attached to the dimension.
730   /// DCHECKS that there's exactly one resource group for this dimension.
GetDimensionResourceGroupIndex(const RoutingDimension * dimension)731   int GetDimensionResourceGroupIndex(const RoutingDimension* dimension) const {
732     DCHECK_EQ(GetDimensionResourceGroupIndices(dimension).size(), 1);
733     return GetDimensionResourceGroupIndices(dimension)[0];
734   }
735 
736   /// Adds a disjunction constraint on the indices: exactly 'max_cardinality' of
737   /// the indices are active. Start and end indices of any vehicle cannot be
738   /// part of a disjunction.
739   ///
740   /// If a penalty is given, at most 'max_cardinality' of the indices can be
741   /// active, and if less are active, 'penalty' is payed per inactive index.
742   /// This is equivalent to adding the constraint:
743   ///     p + Sum(i)active[i] == max_cardinality
744   /// where p is an integer variable, and the following cost to the cost
745   /// function:
746   ///     p * penalty.
747   /// 'penalty' must be positive to make the disjunction optional; a negative
748   /// penalty will force 'max_cardinality' indices of the disjunction to be
749   /// performed, and therefore p == 0.
750   /// Note: passing a vector with a single index will model an optional index
751   /// with a penalty cost if it is not visited.
752   DisjunctionIndex AddDisjunction(const std::vector<int64_t>& indices,
753                                   int64_t penalty = kNoPenalty,
754                                   int64_t max_cardinality = 1);
755   /// Returns the indices of the disjunctions to which an index belongs.
GetDisjunctionIndices(int64_t index)756   const std::vector<DisjunctionIndex>& GetDisjunctionIndices(
757       int64_t index) const {
758     return index_to_disjunctions_[index];
759   }
760   /// Calls f for each variable index of indices in the same disjunctions as the
761   /// node corresponding to the variable index 'index'; only disjunctions of
762   /// cardinality 'cardinality' are considered.
763   template <typename F>
ForEachNodeInDisjunctionWithMaxCardinalityFromIndex(int64_t index,int64_t max_cardinality,F f)764   void ForEachNodeInDisjunctionWithMaxCardinalityFromIndex(
765       int64_t index, int64_t max_cardinality, F f) const {
766     for (const DisjunctionIndex disjunction : GetDisjunctionIndices(index)) {
767       if (disjunctions_[disjunction].value.max_cardinality == max_cardinality) {
768         for (const int64_t d_index : disjunctions_[disjunction].indices) {
769           f(d_index);
770         }
771       }
772     }
773   }
774 #if !defined(SWIGPYTHON)
775   /// Returns the variable indices of the nodes in the disjunction of index
776   /// 'index'.
GetDisjunctionNodeIndices(DisjunctionIndex index)777   const std::vector<int64_t>& GetDisjunctionNodeIndices(
778       DisjunctionIndex index) const {
779     return disjunctions_[index].indices;
780   }
781 #endif  // !defined(SWIGPYTHON)
782   /// Returns the penalty of the node disjunction of index 'index'.
GetDisjunctionPenalty(DisjunctionIndex index)783   int64_t GetDisjunctionPenalty(DisjunctionIndex index) const {
784     return disjunctions_[index].value.penalty;
785   }
786   /// Returns the maximum number of possible active nodes of the node
787   /// disjunction of index 'index'.
GetDisjunctionMaxCardinality(DisjunctionIndex index)788   int64_t GetDisjunctionMaxCardinality(DisjunctionIndex index) const {
789     return disjunctions_[index].value.max_cardinality;
790   }
791   /// Returns the number of node disjunctions in the model.
GetNumberOfDisjunctions()792   int GetNumberOfDisjunctions() const { return disjunctions_.size(); }
793   /// Returns true if the model contains mandatory disjunctions (ones with
794   /// kNoPenalty as penalty).
795   bool HasMandatoryDisjunctions() const;
796   /// Returns true if the model contains at least one disjunction which is
797   /// constrained by its max_cardinality.
798   bool HasMaxCardinalityConstrainedDisjunctions() const;
799   /// Returns the list of all perfect binary disjunctions, as pairs of variable
800   /// indices: a disjunction is "perfect" when its variables do not appear in
801   /// any other disjunction. Each pair is sorted (lowest variable index first),
802   /// and the output vector is also sorted (lowest pairs first).
803   std::vector<std::pair<int64_t, int64_t>> GetPerfectBinaryDisjunctions() const;
804   /// SPECIAL: Makes the solver ignore all the disjunctions whose active
805   /// variables are all trivially zero (i.e. Max() == 0), by setting their
806   /// max_cardinality to 0.
807   /// This can be useful when using the BaseBinaryDisjunctionNeighborhood
808   /// operators, in the context of arc-based routing.
809   void IgnoreDisjunctionsAlreadyForcedToZero();
810 
811   /// Adds a soft constraint to force a set of variable indices to be on the
812   /// same vehicle. If all nodes are not on the same vehicle, each extra vehicle
813   /// used adds 'cost' to the cost function.
814   void AddSoftSameVehicleConstraint(const std::vector<int64_t>& indices,
815                                     int64_t cost);
816 
817   /// Sets the vehicles which can visit a given node. If the node is in a
818   /// disjunction, this will not prevent it from being unperformed.
819   /// Specifying an empty vector of vehicles has no effect (all vehicles
820   /// will be allowed to visit the node).
821   void SetAllowedVehiclesForIndex(const std::vector<int>& vehicles,
822                                   int64_t index);
823 
824   /// Returns true if a vehicle is allowed to visit a given node.
IsVehicleAllowedForIndex(int vehicle,int64_t index)825   bool IsVehicleAllowedForIndex(int vehicle, int64_t index) {
826     return allowed_vehicles_[index].empty() ||
827            allowed_vehicles_[index].find(vehicle) !=
828                allowed_vehicles_[index].end();
829   }
830 
831   /// Notifies that index1 and index2 form a pair of nodes which should belong
832   /// to the same route. This methods helps the search find better solutions,
833   /// especially in the local search phase.
834   /// It should be called each time you have an equality constraint linking
835   /// the vehicle variables of two node (including for instance pickup and
836   /// delivery problems):
837   ///     Solver* const solver = routing.solver();
838   ///     int64_t index1 = manager.NodeToIndex(node1);
839   ///     int64_t index2 = manager.NodeToIndex(node2);
840   ///     solver->AddConstraint(solver->MakeEquality(
841   ///         routing.VehicleVar(index1),
842   ///         routing.VehicleVar(index2)));
843   ///     routing.AddPickupAndDelivery(index1, index2);
844   ///
845   // TODO(user): Remove this when model introspection detects linked nodes.
846   void AddPickupAndDelivery(int64_t pickup, int64_t delivery);
847   /// Same as AddPickupAndDelivery but notifying that the performed node from
848   /// the disjunction of index 'pickup_disjunction' is on the same route as the
849   /// performed node from the disjunction of index 'delivery_disjunction'.
850   void AddPickupAndDeliverySets(DisjunctionIndex pickup_disjunction,
851                                 DisjunctionIndex delivery_disjunction);
852   // clang-format off
853   /// Returns pairs for which the node is a pickup; the first element of each
854   /// pair is the index in the pickup and delivery pairs list in which the
855   /// pickup appears, the second element is its index in the pickups list.
856   const std::vector<std::pair<int, int> >&
857   GetPickupIndexPairs(int64_t node_index) const;
858   /// Same as above for deliveries.
859   const std::vector<std::pair<int, int> >&
860       GetDeliveryIndexPairs(int64_t node_index) const;
861   // clang-format on
862 
863   /// Sets the Pickup and delivery policy of all vehicles. It is equivalent to
864   /// calling SetPickupAndDeliveryPolicyOfVehicle on all vehicles.
865   void SetPickupAndDeliveryPolicyOfAllVehicles(PickupAndDeliveryPolicy policy);
866   void SetPickupAndDeliveryPolicyOfVehicle(PickupAndDeliveryPolicy policy,
867                                            int vehicle);
868   PickupAndDeliveryPolicy GetPickupAndDeliveryPolicyOfVehicle(
869       int vehicle) const;
870   /// Returns the number of non-start/end nodes which do not appear in a
871   /// pickup/delivery pair.
872 
873   int GetNumOfSingletonNodes() const;
874 
875 #ifndef SWIG
876   /// Returns pickup and delivery pairs currently in the model.
GetPickupAndDeliveryPairs()877   const IndexPairs& GetPickupAndDeliveryPairs() const {
878     return pickup_delivery_pairs_;
879   }
880   const std::vector<std::pair<DisjunctionIndex, DisjunctionIndex>>&
GetPickupAndDeliveryDisjunctions()881   GetPickupAndDeliveryDisjunctions() const {
882     return pickup_delivery_disjunctions_;
883   }
884   /// Returns implicit pickup and delivery pairs currently in the model.
885   /// Pairs are implicit if they are not linked by a pickup and delivery
886   /// constraint but that for a given unary dimension, the first element of the
887   /// pair has a positive demand d, and the second element has a demand of -d.
GetImplicitUniquePickupAndDeliveryPairs()888   const IndexPairs& GetImplicitUniquePickupAndDeliveryPairs() const {
889     DCHECK(closed_);
890     return implicit_pickup_delivery_pairs_without_alternatives_;
891   }
892 #endif  // SWIG
893   /// Set the node visit types and incompatibilities/requirements between the
894   /// types (see below).
895   ///
896   /// NOTE: Before adding any incompatibilities and/or requirements on types:
897   ///       1) All corresponding node types must have been set.
898   ///       2) CloseVisitTypes() must be called so all containers are resized
899   ///          accordingly.
900   ///
901   /// The following enum is used to describe how a node with a given type 'T'
902   /// impacts the number of types 'T' on the route when visited, and thus
903   /// determines how temporal incompatibilities and requirements take effect.
904   enum VisitTypePolicy {
905     /// When visited, the number of types 'T' on the vehicle increases by one.
906     TYPE_ADDED_TO_VEHICLE,
907     /// When visited, one instance of type 'T' previously added to the route
908     /// (TYPE_ADDED_TO_VEHICLE), if any, is removed from the vehicle.
909     /// If the type was not previously added to the route or all added instances
910     /// have already been removed, this visit has no effect on the types.
911     ADDED_TYPE_REMOVED_FROM_VEHICLE,
912     /// With the following policy, the visit enforces that type 'T' is
913     /// considered on the route from its start until this node is visited.
914     TYPE_ON_VEHICLE_UP_TO_VISIT,
915     /// The visit doesn't have an impact on the number of types 'T' on the
916     /// route, as it's (virtually) added and removed directly.
917     /// This policy can be used for visits which are part of an incompatibility
918     /// or requirement set without affecting the type count on the route.
919     TYPE_SIMULTANEOUSLY_ADDED_AND_REMOVED
920   };
921   // TODO(user): Support multiple visit types per node?
922   void SetVisitType(int64_t index, int type, VisitTypePolicy type_policy);
923   int GetVisitType(int64_t index) const;
924   const std::vector<int>& GetSingleNodesOfType(int type) const;
925   const std::vector<int>& GetPairIndicesOfType(int type) const;
926   VisitTypePolicy GetVisitTypePolicy(int64_t index) const;
927   /// This function should be called once all node visit types have been set and
928   /// prior to adding any incompatibilities/requirements.
929   // TODO(user): Reconsider the logic and potentially remove the need to
930   /// "close" types.
931   void CloseVisitTypes();
GetNumberOfVisitTypes()932   int GetNumberOfVisitTypes() const { return num_visit_types_; }
933 #ifndef SWIG
GetTopologicallySortedVisitTypes()934   const std::vector<std::vector<int>>& GetTopologicallySortedVisitTypes()
935       const {
936     DCHECK(closed_);
937     return topologically_sorted_visit_types_;
938   }
939 #endif  // SWIG
940   /// Incompatibilities:
941   /// Two nodes with "hard" incompatible types cannot share the same route at
942   /// all, while with a "temporal" incompatibility they can't be on the same
943   /// route at the same time.
944   void AddHardTypeIncompatibility(int type1, int type2);
945   void AddTemporalTypeIncompatibility(int type1, int type2);
946   /// Returns visit types incompatible with a given type.
947   const absl::flat_hash_set<int>& GetHardTypeIncompatibilitiesOfType(
948       int type) const;
949   const absl::flat_hash_set<int>& GetTemporalTypeIncompatibilitiesOfType(
950       int type) const;
951   /// Returns true iff any hard (resp. temporal) type incompatibilities have
952   /// been added to the model.
HasHardTypeIncompatibilities()953   bool HasHardTypeIncompatibilities() const {
954     return has_hard_type_incompatibilities_;
955   }
HasTemporalTypeIncompatibilities()956   bool HasTemporalTypeIncompatibilities() const {
957     return has_temporal_type_incompatibilities_;
958   }
959   /// Requirements:
960   /// NOTE: As of 2019-04, cycles in the requirement graph are not supported,
961   /// and lead to the dependent nodes being skipped if possible (otherwise
962   /// the model is considered infeasible).
963   /// The following functions specify that "dependent_type" requires at least
964   /// one of the types in "required_type_alternatives".
965   ///
966   /// For same-vehicle requirements, a node of dependent type type_D requires at
967   /// least one node of type type_R among the required alternatives on the same
968   /// route.
969   void AddSameVehicleRequiredTypeAlternatives(
970       int dependent_type, absl::flat_hash_set<int> required_type_alternatives);
971   /// If type_D depends on type_R when adding type_D, any node_D of type_D and
972   /// VisitTypePolicy TYPE_ADDED_TO_VEHICLE or
973   /// TYPE_SIMULTANEOUSLY_ADDED_AND_REMOVED requires at least one type_R on its
974   /// vehicle at the time node_D is visited.
975   void AddRequiredTypeAlternativesWhenAddingType(
976       int dependent_type, absl::flat_hash_set<int> required_type_alternatives);
977   /// The following requirements apply when visiting dependent nodes that remove
978   /// their type from the route, i.e. type_R must be on the vehicle when type_D
979   /// of VisitTypePolicy ADDED_TYPE_REMOVED_FROM_VEHICLE,
980   /// TYPE_ON_VEHICLE_UP_TO_VISIT or TYPE_SIMULTANEOUSLY_ADDED_AND_REMOVED is
981   /// visited.
982   void AddRequiredTypeAlternativesWhenRemovingType(
983       int dependent_type, absl::flat_hash_set<int> required_type_alternatives);
984   // clang-format off
985   /// Returns the set of same-vehicle requirement alternatives for the given
986   /// type.
987   const std::vector<absl::flat_hash_set<int> >&
988       GetSameVehicleRequiredTypeAlternativesOfType(int type) const;
989   /// Returns the set of requirement alternatives when adding the given type.
990   const std::vector<absl::flat_hash_set<int> >&
991       GetRequiredTypeAlternativesWhenAddingType(int type) const;
992   /// Returns the set of requirement alternatives when removing the given type.
993   const std::vector<absl::flat_hash_set<int> >&
994       GetRequiredTypeAlternativesWhenRemovingType(int type) const;
995   // clang-format on
996   /// Returns true iff any same-route (resp. temporal) type requirements have
997   /// been added to the model.
HasSameVehicleTypeRequirements()998   bool HasSameVehicleTypeRequirements() const {
999     return has_same_vehicle_type_requirements_;
1000   }
HasTemporalTypeRequirements()1001   bool HasTemporalTypeRequirements() const {
1002     return has_temporal_type_requirements_;
1003   }
1004 
1005   /// Returns true iff the model has any incompatibilities or requirements set
1006   /// on node types.
HasTypeRegulations()1007   bool HasTypeRegulations() const {
1008     return HasTemporalTypeIncompatibilities() ||
1009            HasHardTypeIncompatibilities() || HasSameVehicleTypeRequirements() ||
1010            HasTemporalTypeRequirements();
1011   }
1012 
1013   /// Get the "unperformed" penalty of a node. This is only well defined if the
1014   /// node is only part of a single Disjunction, and that disjunction has a
1015   /// penalty. For forced active nodes returns max int64_t. In all other cases,
1016   /// this returns 0.
1017   int64_t UnperformedPenalty(int64_t var_index) const;
1018   /// Same as above except that it returns default_value instead of 0 when
1019   /// penalty is not well defined (default value is passed as first argument to
1020   /// simplify the usage of the method in a callback).
1021   int64_t UnperformedPenaltyOrValue(int64_t default_value,
1022                                     int64_t var_index) const;
1023   /// Returns the variable index of the first starting or ending node of all
1024   /// routes. If all routes start  and end at the same node (single depot), this
1025   /// is the node returned.
1026   int64_t GetDepot() const;
1027 
1028   /// Constrains the maximum number of active vehicles, aka the number of
1029   /// vehicles which do not have an empty route. For instance, this can be used
1030   /// to limit the number of routes in the case where there are fewer drivers
1031   /// than vehicles and that the fleet of vehicle is heterogeneous.
SetMaximumNumberOfActiveVehicles(int max_active_vehicles)1032   void SetMaximumNumberOfActiveVehicles(int max_active_vehicles) {
1033     max_active_vehicles_ = max_active_vehicles;
1034   }
1035   /// Returns the maximum number of active vehicles.
GetMaximumNumberOfActiveVehicles()1036   int GetMaximumNumberOfActiveVehicles() const { return max_active_vehicles_; }
1037   /// Sets the cost function of the model such that the cost of a segment of a
1038   /// route between node 'from' and 'to' is evaluator(from, to), whatever the
1039   /// route or vehicle performing the route.
1040   void SetArcCostEvaluatorOfAllVehicles(int evaluator_index);
1041   /// Sets the cost function for a given vehicle route.
1042   void SetArcCostEvaluatorOfVehicle(int evaluator_index, int vehicle);
1043   /// Sets the fixed cost of all vehicle routes. It is equivalent to calling
1044   /// SetFixedCostOfVehicle on all vehicle routes.
1045   void SetFixedCostOfAllVehicles(int64_t cost);
1046   /// Sets the fixed cost of one vehicle route.
1047   void SetFixedCostOfVehicle(int64_t cost, int vehicle);
1048   /// Returns the route fixed cost taken into account if the route of the
1049   /// vehicle is not empty, aka there's at least one node on the route other
1050   /// than the first and last nodes.
1051   int64_t GetFixedCostOfVehicle(int vehicle) const;
1052 
1053   /// The following methods set the linear and quadratic cost factors of
1054   /// vehicles (must be positive values). The default value of these parameters
1055   /// is zero for all vehicles.
1056   ///
1057   /// When set, the cost_ of the model will contain terms aiming at reducing the
1058   /// number of vehicles used in the model, by adding the following to the
1059   /// objective for every vehicle v:
1060   /// INDICATOR(v used in the model) *
1061   ///   [linear_cost_factor_of_vehicle_[v]
1062   ///    - quadratic_cost_factor_of_vehicle_[v]*(square of length of route v)]
1063   /// i.e. for every used vehicle, we add the linear factor as fixed cost, and
1064   /// subtract the square of the route length multiplied by the quadratic
1065   /// factor. This second term aims at making the routes as dense as possible.
1066   ///
1067   /// Sets the linear and quadratic cost factor of all vehicles.
1068   void SetAmortizedCostFactorsOfAllVehicles(int64_t linear_cost_factor,
1069                                             int64_t quadratic_cost_factor);
1070   /// Sets the linear and quadratic cost factor of the given vehicle.
1071   void SetAmortizedCostFactorsOfVehicle(int64_t linear_cost_factor,
1072                                         int64_t quadratic_cost_factor,
1073                                         int vehicle);
1074 
GetAmortizedLinearCostFactorOfVehicles()1075   const std::vector<int64_t>& GetAmortizedLinearCostFactorOfVehicles() const {
1076     return linear_cost_factor_of_vehicle_;
1077   }
GetAmortizedQuadraticCostFactorOfVehicles()1078   const std::vector<int64_t>& GetAmortizedQuadraticCostFactorOfVehicles()
1079       const {
1080     return quadratic_cost_factor_of_vehicle_;
1081   }
1082 
SetVehicleUsedWhenEmpty(bool is_used,int vehicle)1083   void SetVehicleUsedWhenEmpty(bool is_used, int vehicle) {
1084     DCHECK_LT(vehicle, vehicles_);
1085     vehicle_used_when_empty_[vehicle] = is_used;
1086   }
1087 
IsVehicleUsedWhenEmpty(int vehicle)1088   bool IsVehicleUsedWhenEmpty(int vehicle) const {
1089     DCHECK_LT(vehicle, vehicles_);
1090     return vehicle_used_when_empty_[vehicle];
1091   }
1092 
1093 /// Gets/sets the evaluator used during the search. Only relevant when
1094 /// RoutingSearchParameters.first_solution_strategy = EVALUATOR_STRATEGY.
1095 #ifndef SWIG
first_solution_evaluator()1096   const Solver::IndexEvaluator2& first_solution_evaluator() const {
1097     return first_solution_evaluator_;
1098   }
1099 #endif
1100   /// Takes ownership of evaluator.
SetFirstSolutionEvaluator(Solver::IndexEvaluator2 evaluator)1101   void SetFirstSolutionEvaluator(Solver::IndexEvaluator2 evaluator) {
1102     first_solution_evaluator_ = std::move(evaluator);
1103   }
1104   /// Adds a local search operator to the set of operators used to solve the
1105   /// vehicle routing problem.
1106   void AddLocalSearchOperator(LocalSearchOperator* ls_operator);
1107   /// Adds a search monitor to the search used to solve the routing model.
1108   void AddSearchMonitor(SearchMonitor* const monitor);
1109   /// Adds a callback called each time a solution is found during the search.
1110   /// This is a shortcut to creating a monitor to call the callback on
1111   /// AtSolution() and adding it with AddSearchMonitor.
1112   void AddAtSolutionCallback(std::function<void()> callback);
1113   /// Adds a variable to minimize in the solution finalizer. The solution
1114   /// finalizer is called each time a solution is found during the search and
1115   /// allows to instantiate secondary variables (such as dimension cumul
1116   /// variables).
1117   void AddVariableMinimizedByFinalizer(IntVar* var);
1118   /// Adds a variable to maximize in the solution finalizer (see above for
1119   /// information on the solution finalizer).
1120   void AddVariableMaximizedByFinalizer(IntVar* var);
1121   /// Adds a variable to minimize in the solution finalizer, with a weighted
1122   /// priority: the higher the more priority it has.
1123   void AddWeightedVariableMinimizedByFinalizer(IntVar* var, int64_t cost);
1124   /// Add a variable to set the closest possible to the target value in the
1125   /// solution finalizer.
1126   void AddVariableTargetToFinalizer(IntVar* var, int64_t target);
1127   /// Closes the current routing model; after this method is called, no
1128   /// modification to the model can be done, but RoutesToAssignment becomes
1129   /// available. Note that CloseModel() is automatically called by Solve() and
1130   /// other methods that produce solution.
1131   /// This is equivalent to calling
1132   /// CloseModelWithParameters(DefaultRoutingSearchParameters()).
1133   void CloseModel();
1134   /// Same as above taking search parameters (as of 10/2015 some the parameters
1135   /// have to be set when closing the model).
1136   void CloseModelWithParameters(
1137       const RoutingSearchParameters& search_parameters);
1138   /// Solves the current routing model; closes the current model.
1139   /// This is equivalent to calling
1140   /// SolveWithParameters(DefaultRoutingSearchParameters())
1141   /// or
1142   /// SolveFromAssignmentWithParameters(assignment,
1143   ///                                   DefaultRoutingSearchParameters()).
1144   const Assignment* Solve(const Assignment* assignment = nullptr);
1145   /// Solves the current routing model with the given parameters. If 'solutions'
1146   /// is specified, it will contain the k best solutions found during the search
1147   /// (from worst to best, including the one returned by this method), where k
1148   /// corresponds to the 'number_of_solutions_to_collect' in
1149   /// 'search_parameters'. Note that the Assignment returned by the method and
1150   /// the ones in solutions are owned by the underlying solver and should not be
1151   /// deleted.
1152   const Assignment* SolveWithParameters(
1153       const RoutingSearchParameters& search_parameters,
1154       std::vector<const Assignment*>* solutions = nullptr);
1155   /// Same as above, except that if assignment is not null, it will be used as
1156   /// the initial solution.
1157   const Assignment* SolveFromAssignmentWithParameters(
1158       const Assignment* assignment,
1159       const RoutingSearchParameters& search_parameters,
1160       std::vector<const Assignment*>* solutions = nullptr);
1161   /// Same as above but will try all assignments in order as first solutions
1162   /// until one succeeds.
1163   const Assignment* SolveFromAssignmentsWithParameters(
1164       const std::vector<const Assignment*>& assignments,
1165       const RoutingSearchParameters& search_parameters,
1166       std::vector<const Assignment*>* solutions = nullptr);
1167   /// Given a "source_model" and its "source_assignment", resets
1168   /// "target_assignment" with the IntVar variables (nexts_, and vehicle_vars_
1169   /// if costs aren't homogeneous across vehicles) of "this" model, with the
1170   /// values set according to those in "other_assignment".
1171   /// The objective_element of target_assignment is set to this->cost_.
1172   void SetAssignmentFromOtherModelAssignment(
1173       Assignment* target_assignment, const RoutingModel* source_model,
1174       const Assignment* source_assignment);
1175   /// Computes a lower bound to the routing problem solving a linear assignment
1176   /// problem. The routing model must be closed before calling this method.
1177   /// Note that problems with node disjunction constraints (including optional
1178   /// nodes) and non-homogenous costs are not supported (the method returns 0 in
1179   /// these cases).
1180   // TODO(user): Add support for non-homogeneous costs and disjunctions.
1181   int64_t ComputeLowerBound();
1182   /// Returns the current status of the routing model.
status()1183   Status status() const { return status_; }
1184   /// Applies a lock chain to the next search. 'locks' represents an ordered
1185   /// vector of nodes representing a partial route which will be fixed during
1186   /// the next search; it will constrain next variables such that:
1187   /// next[locks[i]] == locks[i+1].
1188   ///
1189   /// Returns the next variable at the end of the locked chain; this variable is
1190   /// not locked. An assignment containing the locks can be obtained by calling
1191   /// PreAssignment().
1192   IntVar* ApplyLocks(const std::vector<int64_t>& locks);
1193   /// Applies lock chains to all vehicles to the next search, such that locks[p]
1194   /// is the lock chain for route p. Returns false if the locks do not contain
1195   /// valid routes; expects that the routes do not contain the depots,
1196   /// i.e. there are empty vectors in place of empty routes.
1197   /// If close_routes is set to true, adds the end nodes to the route of each
1198   /// vehicle and deactivates other nodes.
1199   /// An assignment containing the locks can be obtained by calling
1200   /// PreAssignment().
1201   bool ApplyLocksToAllVehicles(const std::vector<std::vector<int64_t>>& locks,
1202                                bool close_routes);
1203   /// Returns an assignment used to fix some of the variables of the problem.
1204   /// In practice, this assignment locks partial routes of the problem. This
1205   /// can be used in the context of locking the parts of the routes which have
1206   /// already been driven in online routing problems.
PreAssignment()1207   const Assignment* const PreAssignment() const { return preassignment_; }
MutablePreAssignment()1208   Assignment* MutablePreAssignment() { return preassignment_; }
1209   /// Writes the current solution to a file containing an AssignmentProto.
1210   /// Returns false if the file cannot be opened or if there is no current
1211   /// solution.
1212   bool WriteAssignment(const std::string& file_name) const;
1213   /// Reads an assignment from a file and returns the current solution.
1214   /// Returns nullptr if the file cannot be opened or if the assignment is not
1215   /// valid.
1216   Assignment* ReadAssignment(const std::string& file_name);
1217   /// Restores an assignment as a solution in the routing model and returns the
1218   /// new solution. Returns nullptr if the assignment is not valid.
1219   Assignment* RestoreAssignment(const Assignment& solution);
1220   /// Restores the routes as the current solution. Returns nullptr if the
1221   /// solution cannot be restored (routes do not contain a valid solution). Note
1222   /// that calling this method will run the solver to assign values to the
1223   /// dimension variables; this may take considerable amount of time, especially
1224   /// when using dimensions with slack.
1225   Assignment* ReadAssignmentFromRoutes(
1226       const std::vector<std::vector<int64_t>>& routes,
1227       bool ignore_inactive_indices);
1228   /// Fills an assignment from a specification of the routes of the
1229   /// vehicles. The routes are specified as lists of variable indices that
1230   /// appear on the routes of the vehicles. The indices of the outer vector in
1231   /// 'routes' correspond to vehicles IDs, the inner vector contains the
1232   /// variable indices on the routes for the given vehicle. The inner vectors
1233   /// must not contain the start and end indices, as these are determined by the
1234   /// routing model.  Sets the value of NextVars in the assignment, adding the
1235   /// variables to the assignment if necessary. The method does not touch other
1236   /// variables in the assignment. The method can only be called after the model
1237   /// is closed.  With ignore_inactive_indices set to false, this method will
1238   /// fail (return nullptr) in case some of the route contain indices that are
1239   /// deactivated in the model; when set to true, these indices will be
1240   /// skipped.  Returns true if routes were successfully
1241   /// loaded. However, such assignment still might not be a valid
1242   /// solution to the routing problem due to more complex constraints;
1243   /// it is advisible to call solver()->CheckSolution() afterwards.
1244   bool RoutesToAssignment(const std::vector<std::vector<int64_t>>& routes,
1245                           bool ignore_inactive_indices, bool close_routes,
1246                           Assignment* const assignment) const;
1247   /// Converts the solution in the given assignment to routes for all vehicles.
1248   /// Expects that assignment contains a valid solution (i.e. routes for all
1249   /// vehicles end with an end index for that vehicle).
1250   void AssignmentToRoutes(
1251       const Assignment& assignment,
1252       std::vector<std::vector<int64_t>>* const routes) const;
1253   /// Converts the solution in the given assignment to routes for all vehicles.
1254   /// If the returned vector is route_indices, route_indices[i][j] is the index
1255   /// for jth location visited on route i. Note that contrary to
1256   /// AssignmentToRoutes, the vectors do include start and end locations.
1257 #ifndef SWIG
1258   std::vector<std::vector<int64_t>> GetRoutesFromAssignment(
1259       const Assignment& assignment);
1260 #endif
1261   /// Returns a compacted version of the given assignment, in which all vehicles
1262   /// with id lower or equal to some N have non-empty routes, and all vehicles
1263   /// with id greater than N have empty routes. Does not take ownership of the
1264   /// returned object.
1265   /// If found, the cost of the compact assignment is the same as in the
1266   /// original assignment and it preserves the values of 'active' variables.
1267   /// Returns nullptr if a compact assignment was not found.
1268   /// This method only works in homogenous mode, and it only swaps equivalent
1269   /// vehicles (vehicles with the same start and end nodes). When creating the
1270   /// compact assignment, the empty plan is replaced by the route assigned to
1271   /// the compatible vehicle with the highest id. Note that with more complex
1272   /// constraints on vehicle variables, this method might fail even if a compact
1273   /// solution exists.
1274   /// This method changes the vehicle and dimension variables as necessary.
1275   /// While compacting the solution, only basic checks on vehicle variables are
1276   /// performed; if one of these checks fails no attempts to repair it are made
1277   /// (instead, the method returns nullptr).
1278   Assignment* CompactAssignment(const Assignment& assignment) const;
1279   /// Same as CompactAssignment() but also checks the validity of the final
1280   /// compact solution; if it is not valid, no attempts to repair it are made
1281   /// (instead, the method returns nullptr).
1282   Assignment* CompactAndCheckAssignment(const Assignment& assignment) const;
1283   /// Adds an extra variable to the vehicle routing assignment.
1284   void AddToAssignment(IntVar* const var);
1285   void AddIntervalToAssignment(IntervalVar* const interval);
1286   /// For every dimension in the model with an optimizer in
1287   /// local/global_dimension_optimizers_, this method tries to pack the cumul
1288   /// values of the dimension, such that:
1289   /// - The cumul costs (span costs, soft lower and upper bound costs, etc) are
1290   ///   minimized.
1291   /// - The cumuls of the ends of the routes are minimized for this given
1292   ///   minimal cumul cost.
1293   /// - Given these minimal end cumuls, the route start cumuls are maximized.
1294   /// Returns the assignment resulting from allocating these packed cumuls with
1295   /// the solver, and nullptr if these cumuls could not be set by the solver.
1296   const Assignment* PackCumulsOfOptimizerDimensionsFromAssignment(
1297       const Assignment* original_assignment, absl::Duration duration_limit);
1298 #ifndef SWIG
1299   // TODO(user): Revisit if coordinates are added to the RoutingModel class.
1300   void SetSweepArranger(SweepArranger* sweep_arranger);
1301   /// Returns the sweep arranger to be used by routing heuristics.
1302   SweepArranger* sweep_arranger() const;
1303 #endif
1304   /// Adds a custom local search filter to the list of filters used to speed up
1305   /// local search by pruning unfeasible variable assignments.
1306   /// Calling this method after the routing model has been closed (CloseModel()
1307   /// or Solve() has been called) has no effect.
1308   /// The routing model does not take ownership of the filter.
AddLocalSearchFilter(LocalSearchFilter * filter)1309   void AddLocalSearchFilter(LocalSearchFilter* filter) {
1310     CHECK(filter != nullptr);
1311     if (closed_) {
1312       LOG(WARNING) << "Model is closed, filter addition will be ignored.";
1313     }
1314     extra_filters_.push_back({filter, LocalSearchFilterManager::kRelax});
1315     extra_filters_.push_back({filter, LocalSearchFilterManager::kAccept});
1316   }
1317 
1318   /// Model inspection.
1319   /// Returns the variable index of the starting node of a vehicle route.
Start(int vehicle)1320   int64_t Start(int vehicle) const { return starts_[vehicle]; }
1321   /// Returns the variable index of the ending node of a vehicle route.
End(int vehicle)1322   int64_t End(int vehicle) const { return ends_[vehicle]; }
1323   /// Returns true if 'index' represents the first node of a route.
1324   bool IsStart(int64_t index) const;
1325   /// Returns true if 'index' represents the last node of a route.
IsEnd(int64_t index)1326   bool IsEnd(int64_t index) const { return index >= Size(); }
1327   /// Returns the vehicle of the given start/end index, and -1 if the given
1328   /// index is not a vehicle start/end.
VehicleIndex(int64_t index)1329   int VehicleIndex(int64_t index) const { return index_to_vehicle_[index]; }
1330   /// Assignment inspection
1331   /// Returns the variable index of the node directly after the node
1332   /// corresponding to 'index' in 'assignment'.
1333   int64_t Next(const Assignment& assignment, int64_t index) const;
1334   /// Returns true if the route of 'vehicle' is non empty in 'assignment'.
1335   bool IsVehicleUsed(const Assignment& assignment, int vehicle) const;
1336 
1337 #if !defined(SWIGPYTHON)
1338   /// Returns all next variables of the model, such that Nexts(i) is the next
1339   /// variable of the node corresponding to i.
Nexts()1340   const std::vector<IntVar*>& Nexts() const { return nexts_; }
1341   /// Returns all vehicle variables of the model,  such that VehicleVars(i) is
1342   /// the vehicle variable of the node corresponding to i.
VehicleVars()1343   const std::vector<IntVar*>& VehicleVars() const { return vehicle_vars_; }
1344   /// Returns vehicle resource variables for a given resource group, such that
1345   /// ResourceVars(r_g)[v] is the resource variable for vehicle 'v' in resource
1346   /// group 'r_g'.
ResourceVars(int resource_group)1347   const std::vector<IntVar*>& ResourceVars(int resource_group) const {
1348     return resource_vars_[resource_group];
1349   }
1350 #endif  /// !defined(SWIGPYTHON)
1351   /// Returns the next variable of the node corresponding to index. Note that
1352   /// NextVar(index) == index is equivalent to ActiveVar(index) == 0.
NextVar(int64_t index)1353   IntVar* NextVar(int64_t index) const { return nexts_[index]; }
1354   /// Returns the active variable of the node corresponding to index.
ActiveVar(int64_t index)1355   IntVar* ActiveVar(int64_t index) const { return active_[index]; }
1356   /// Returns the active variable of the vehicle. It will be equal to 1 iff the
1357   /// route of the vehicle is not empty, 0 otherwise.
ActiveVehicleVar(int vehicle)1358   IntVar* ActiveVehicleVar(int vehicle) const {
1359     return vehicle_active_[vehicle];
1360   }
1361   /// Returns the variable specifying whether or not the given vehicle route is
1362   /// considered for costs and constraints. It will be equal to 1 iff the route
1363   /// of the vehicle is not empty OR vehicle_used_when_empty_[vehicle] is true.
VehicleRouteConsideredVar(int vehicle)1364   IntVar* VehicleRouteConsideredVar(int vehicle) const {
1365     return vehicle_route_considered_[vehicle];
1366   }
1367   /// Returns the vehicle variable of the node corresponding to index. Note that
1368   /// VehicleVar(index) == -1 is equivalent to ActiveVar(index) == 0.
VehicleVar(int64_t index)1369   IntVar* VehicleVar(int64_t index) const { return vehicle_vars_[index]; }
1370   /// Returns the resource variable for the given vehicle index in the given
1371   /// resource group. If a vehicle doesn't require a resource from the
1372   /// corresponding resource group, then ResourceVar(v, r_g) == -1.
ResourceVar(int vehicle,int resource_group)1373   IntVar* ResourceVar(int vehicle, int resource_group) const {
1374     DCHECK_LT(resource_group, resource_vars_.size());
1375     DCHECK_LT(vehicle, resource_vars_[resource_group].size());
1376     return resource_vars_[resource_group][vehicle];
1377   }
1378   /// Returns the global cost variable which is being minimized.
CostVar()1379   IntVar* CostVar() const { return cost_; }
1380 
1381   /// Returns the cost of the transit arc between two nodes for a given vehicle.
1382   /// Input are variable indices of node. This returns 0 if vehicle < 0.
1383   int64_t GetArcCostForVehicle(int64_t from_index, int64_t to_index,
1384                                int64_t vehicle) const;
1385   /// Whether costs are homogeneous across all vehicles.
CostsAreHomogeneousAcrossVehicles()1386   bool CostsAreHomogeneousAcrossVehicles() const {
1387     return costs_are_homogeneous_across_vehicles_;
1388   }
1389   /// Returns the cost of the segment between two nodes supposing all vehicle
1390   /// costs are the same (returns the cost for the first vehicle otherwise).
GetHomogeneousCost(int64_t from_index,int64_t to_index)1391   int64_t GetHomogeneousCost(int64_t from_index, int64_t to_index) const {
1392     return GetArcCostForVehicle(from_index, to_index, /*vehicle=*/0);
1393   }
1394   /// Returns the cost of the arc in the context of the first solution strategy.
1395   /// This is typically a simplification of the actual cost; see the .cc.
1396   int64_t GetArcCostForFirstSolution(int64_t from_index,
1397                                      int64_t to_index) const;
1398   /// Returns the cost of the segment between two nodes for a given cost
1399   /// class. Input are variable indices of nodes and the cost class.
1400   /// Unlike GetArcCostForVehicle(), if cost_class is kNoCost, then the
1401   /// returned cost won't necessarily be zero: only some of the components
1402   /// of the cost that depend on the cost class will be omited. See the code
1403   /// for details.
1404   int64_t GetArcCostForClass(int64_t from_index, int64_t to_index,
1405                              int64_t /*CostClassIndex*/ cost_class_index) const;
1406   /// Get the cost class index of the given vehicle.
GetCostClassIndexOfVehicle(int64_t vehicle)1407   CostClassIndex GetCostClassIndexOfVehicle(int64_t vehicle) const {
1408     DCHECK(closed_);
1409     DCHECK_GE(vehicle, 0);
1410     DCHECK_LT(vehicle, cost_class_index_of_vehicle_.size());
1411     DCHECK_GE(cost_class_index_of_vehicle_[vehicle], 0);
1412     return cost_class_index_of_vehicle_[vehicle];
1413   }
1414   /// Returns true iff the model contains a vehicle with the given
1415   /// cost_class_index.
HasVehicleWithCostClassIndex(CostClassIndex cost_class_index)1416   bool HasVehicleWithCostClassIndex(CostClassIndex cost_class_index) const {
1417     DCHECK(closed_);
1418     if (cost_class_index == kCostClassIndexOfZeroCost) {
1419       return has_vehicle_with_zero_cost_class_;
1420     }
1421     return cost_class_index < cost_classes_.size();
1422   }
1423   /// Returns the number of different cost classes in the model.
GetCostClassesCount()1424   int GetCostClassesCount() const { return cost_classes_.size(); }
1425   /// Ditto, minus the 'always zero', built-in cost class.
GetNonZeroCostClassesCount()1426   int GetNonZeroCostClassesCount() const {
1427     return std::max(0, GetCostClassesCount() - 1);
1428   }
GetVehicleClassIndexOfVehicle(int64_t vehicle)1429   VehicleClassIndex GetVehicleClassIndexOfVehicle(int64_t vehicle) const {
1430     DCHECK(closed_);
1431     return vehicle_class_index_of_vehicle_[vehicle];
1432   }
1433   /// Returns a vehicle of the given vehicle class, and -1 if there are no
1434   /// vehicles for this class.
GetVehicleOfClass(VehicleClassIndex vehicle_class)1435   int GetVehicleOfClass(VehicleClassIndex vehicle_class) const {
1436     DCHECK(closed_);
1437     const RoutingModel::VehicleTypeContainer& vehicle_type_container =
1438         GetVehicleTypeContainer();
1439     if (vehicle_class.value() >= GetVehicleClassesCount() ||
1440         vehicle_type_container.vehicles_per_vehicle_class[vehicle_class.value()]
1441             .empty()) {
1442       return -1;
1443     }
1444     return vehicle_type_container
1445         .vehicles_per_vehicle_class[vehicle_class.value()]
1446         .front();
1447   }
1448   /// Returns the number of different vehicle classes in the model.
GetVehicleClassesCount()1449   int GetVehicleClassesCount() const { return vehicle_classes_.size(); }
1450   /// Returns variable indices of nodes constrained to be on the same route.
GetSameVehicleIndicesOfIndex(int node)1451   const std::vector<int>& GetSameVehicleIndicesOfIndex(int node) const {
1452     DCHECK(closed_);
1453     return same_vehicle_groups_[same_vehicle_group_[node]];
1454   }
1455 
GetVehicleTypeContainer()1456   const VehicleTypeContainer& GetVehicleTypeContainer() const {
1457     DCHECK(closed_);
1458     return vehicle_type_container_;
1459   }
1460 
1461   /// Returns whether the arc from->to1 is more constrained than from->to2,
1462   /// taking into account, in order:
1463   /// - whether the destination node isn't an end node
1464   /// - whether the destination node is mandatory
1465   /// - whether the destination node is bound to the same vehicle as the source
1466   /// - the "primary constrained" dimension (see SetPrimaryConstrainedDimension)
1467   /// It then breaks ties using, in order:
1468   /// - the arc cost (taking unperformed penalties into account)
1469   /// - the size of the vehicle vars of "to1" and "to2" (lowest size wins)
1470   /// - the value: the lowest value of the indices to1 and to2 wins.
1471   /// See the .cc for details.
1472   /// The more constrained arc is typically preferable when building a
1473   /// first solution. This method is intended to be used as a callback for the
1474   /// BestValueByComparisonSelector value selector.
1475   /// Args:
1476   ///   from: the variable index of the source node
1477   ///   to1: the variable index of the first candidate destination node.
1478   ///   to2: the variable index of the second candidate destination node.
1479   bool ArcIsMoreConstrainedThanArc(int64_t from, int64_t to1, int64_t to2);
1480   /// Print some debugging information about an assignment, including the
1481   /// feasible intervals of the CumulVar for dimension "dimension_to_print"
1482   /// at each step of the routes.
1483   /// If "dimension_to_print" is omitted, all dimensions will be printed.
1484   std::string DebugOutputAssignment(
1485       const Assignment& solution_assignment,
1486       const std::string& dimension_to_print) const;
1487   /// Returns a vector cumul_bounds, for which cumul_bounds[i][j] is a pair
1488   /// containing the minimum and maximum of the CumulVar of the jth node on
1489   /// route i.
1490   /// - cumul_bounds[i][j].first is the minimum.
1491   /// - cumul_bounds[i][j].second is the maximum.
1492 #ifndef SWIG
1493   std::vector<std::vector<std::pair<int64_t, int64_t>>> GetCumulBounds(
1494       const Assignment& solution_assignment, const RoutingDimension& dimension);
1495 #endif
1496   /// Returns the underlying constraint solver. Can be used to add extra
1497   /// constraints and/or modify search algorithms.
solver()1498   Solver* solver() const { return solver_.get(); }
1499 
1500   /// Returns true if the search limit has been crossed.
CheckLimit()1501   bool CheckLimit() {
1502     DCHECK(limit_ != nullptr);
1503     return limit_->Check();
1504   }
1505 
1506   /// Returns the time left in the search limit.
RemainingTime()1507   absl::Duration RemainingTime() const {
1508     DCHECK(limit_ != nullptr);
1509     return limit_->AbsoluteSolverDeadline() - solver_->Now();
1510   }
1511 
1512   /// Sizes and indices
1513   /// Returns the number of nodes in the model.
nodes()1514   int nodes() const { return nodes_; }
1515   /// Returns the number of vehicle routes in the model.
vehicles()1516   int vehicles() const { return vehicles_; }
1517   /// Returns the number of next variables in the model.
Size()1518   int64_t Size() const { return nodes_ + vehicles_ - start_end_count_; }
1519 
1520   /// Returns statistics on first solution search, number of decisions sent to
1521   /// filters, number of decisions rejected by filters.
1522   int64_t GetNumberOfDecisionsInFirstSolution(
1523       const RoutingSearchParameters& search_parameters) const;
1524   int64_t GetNumberOfRejectsInFirstSolution(
1525       const RoutingSearchParameters& search_parameters) const;
1526   /// Returns the automatic first solution strategy selected.
1527   operations_research::FirstSolutionStrategy::Value
GetAutomaticFirstSolutionStrategy()1528   GetAutomaticFirstSolutionStrategy() const {
1529     return automatic_first_solution_strategy_;
1530   }
1531 
1532   /// Returns true if a vehicle/node matching problem is detected.
1533   bool IsMatchingModel() const;
1534 
1535 #ifndef SWIG
1536   /// Sets the callback returning the variable to use for the Tabu Search
1537   /// metaheuristic.
1538   using GetTabuVarsCallback =
1539       std::function<std::vector<operations_research::IntVar*>(RoutingModel*)>;
1540 
1541   void SetTabuVarsCallback(GetTabuVarsCallback tabu_var_callback);
1542 #endif  // SWIG
1543 
1544   /// The next few members are in the public section only for testing purposes.
1545   // TODO(user): Find a way to test and restrict the access at the same time.
1546   ///
1547   /// MakeGuidedSlackFinalizer creates a DecisionBuilder for the slacks of a
1548   /// dimension using a callback to choose which values to start with.
1549   /// The finalizer works only when all next variables in the model have
1550   /// been fixed. It has the following two characteristics:
1551   /// 1. It follows the routes defined by the nexts variables when choosing a
1552   ///    variable to make a decision on.
1553   /// 2. When it comes to choose a value for the slack of node i, the decision
1554   ///    builder first calls the callback with argument i, and supposingly the
1555   ///    returned value is x it creates decisions slack[i] = x, slack[i] = x +
1556   ///    1, slack[i] = x - 1, slack[i] = x + 2, etc.
1557   DecisionBuilder* MakeGuidedSlackFinalizer(
1558       const RoutingDimension* dimension,
1559       std::function<int64_t(int64_t)> initializer);
1560 #ifndef SWIG
1561   // TODO(user): MakeGreedyDescentLSOperator is too general for routing.h.
1562   /// Perhaps move it to constraint_solver.h.
1563   /// MakeGreedyDescentLSOperator creates a local search operator that tries to
1564   /// improve the initial assignment by moving a logarithmically decreasing step
1565   /// away in each possible dimension.
1566   static std::unique_ptr<LocalSearchOperator> MakeGreedyDescentLSOperator(
1567       std::vector<IntVar*> variables);
1568   // Read access to currently registered search monitors.
GetSearchMonitors()1569   const std::vector<SearchMonitor*>& GetSearchMonitors() const {
1570     return monitors_;
1571   }
1572 #endif  /// __SWIG__
1573   /// MakeSelfDependentDimensionFinalizer is a finalizer for the slacks of a
1574   /// self-dependent dimension. It makes an extensive use of the caches of the
1575   /// state dependent transits.
1576   /// In detail, MakeSelfDependentDimensionFinalizer returns a composition of a
1577   /// local search decision builder with a greedy descent operator for the cumul
1578   /// of the start of each route and a guided slack finalizer. Provided there
1579   /// are no time windows and the maximum slacks are large enough, once the
1580   /// cumul of the start of route is fixed, the guided finalizer can find
1581   /// optimal values of the slacks for the rest of the route in time
1582   /// proportional to the length of the route. Therefore the composed finalizer
1583   /// generally works in time O(log(t)*n*m), where t is the latest possible
1584   /// departute time, n is the number of nodes in the network and m is the
1585   /// number of vehicles.
1586   DecisionBuilder* MakeSelfDependentDimensionFinalizer(
1587       const RoutingDimension* dimension);
1588 
1589  private:
1590   /// Local search move operator usable in routing.
1591   enum RoutingLocalSearchOperator {
1592     RELOCATE = 0,
1593     RELOCATE_PAIR,
1594     LIGHT_RELOCATE_PAIR,
1595     RELOCATE_NEIGHBORS,
1596     EXCHANGE,
1597     EXCHANGE_PAIR,
1598     CROSS,
1599     CROSS_EXCHANGE,
1600     TWO_OPT,
1601     OR_OPT,
1602     GLOBAL_CHEAPEST_INSERTION_CLOSE_NODES_LNS,
1603     LOCAL_CHEAPEST_INSERTION_CLOSE_NODES_LNS,
1604     GLOBAL_CHEAPEST_INSERTION_PATH_LNS,
1605     LOCAL_CHEAPEST_INSERTION_PATH_LNS,
1606     RELOCATE_PATH_GLOBAL_CHEAPEST_INSERTION_INSERT_UNPERFORMED,
1607     GLOBAL_CHEAPEST_INSERTION_EXPENSIVE_CHAIN_LNS,
1608     LOCAL_CHEAPEST_INSERTION_EXPENSIVE_CHAIN_LNS,
1609     RELOCATE_EXPENSIVE_CHAIN,
1610     LIN_KERNIGHAN,
1611     TSP_OPT,
1612     MAKE_ACTIVE,
1613     RELOCATE_AND_MAKE_ACTIVE,
1614     MAKE_ACTIVE_AND_RELOCATE,
1615     MAKE_INACTIVE,
1616     MAKE_CHAIN_INACTIVE,
1617     SWAP_ACTIVE,
1618     EXTENDED_SWAP_ACTIVE,
1619     NODE_PAIR_SWAP,
1620     PATH_LNS,
1621     FULL_PATH_LNS,
1622     TSP_LNS,
1623     INACTIVE_LNS,
1624     EXCHANGE_RELOCATE_PAIR,
1625     RELOCATE_SUBTRIP,
1626     EXCHANGE_SUBTRIP,
1627     LOCAL_SEARCH_OPERATOR_COUNTER
1628   };
1629 
1630   /// Structure storing a value for a set of variable indices. Is used to store
1631   /// data for index disjunctions (variable indices, max_cardinality and penalty
1632   /// when unperformed).
1633   template <typename T>
1634   struct ValuedNodes {
1635     std::vector<int64_t> indices;
1636     T value;
1637   };
1638   struct DisjunctionValues {
1639     int64_t penalty;
1640     int64_t max_cardinality;
1641   };
1642   typedef ValuedNodes<DisjunctionValues> Disjunction;
1643 
1644   /// Storage of a cost cache element corresponding to a cost arc ending at
1645   /// node 'index' and on the cost class 'cost_class'.
1646   struct CostCacheElement {
1647     /// This is usually an int64_t, but using an int here decreases the RAM
1648     /// usage, and should be fine since in practice we never have more than
1649     /// 1<<31 vars. Note(user): on 2013-11, microbenchmarks on the arc costs
1650     /// callbacks also showed a 2% speed-up thanks to using int rather than
1651     /// int64_t.
1652     int index;
1653     CostClassIndex cost_class_index;
1654     int64_t cost;
1655   };
1656 
1657   /// Internal methods.
1658   void Initialize();
1659   void AddNoCycleConstraintInternal();
1660   bool AddDimensionWithCapacityInternal(
1661       const std::vector<int>& evaluator_indices, int64_t slack_max,
1662       std::vector<int64_t> vehicle_capacities, bool fix_start_cumul_to_zero,
1663       const std::string& name);
1664   bool AddDimensionDependentDimensionWithVehicleCapacityInternal(
1665       const std::vector<int>& pure_transits,
1666       const std::vector<int>& dependent_transits,
1667       const RoutingDimension* base_dimension, int64_t slack_max,
1668       std::vector<int64_t> vehicle_capacities, bool fix_start_cumul_to_zero,
1669       const std::string& name);
1670   bool InitializeDimensionInternal(
1671       const std::vector<int>& evaluator_indices,
1672       const std::vector<int>& state_dependent_evaluator_indices,
1673       int64_t slack_max, bool fix_start_cumul_to_zero,
1674       RoutingDimension* dimension);
1675   DimensionIndex GetDimensionIndex(const std::string& dimension_name) const;
1676 
1677   /// Creates global and local cumul optimizers for the dimensions needing them,
1678   /// and stores them in the corresponding [local|global]_dimension_optimizers_
1679   /// vectors.
1680   /// This function also computes and stores the "offsets" for these dimensions,
1681   /// used in the local/global optimizers to simplify LP computations.
1682   ///
1683   /// Note on the offsets computation:
1684   /// The global/local cumul offsets are used by the respective optimizers to
1685   /// have smaller numbers, and therefore better numerical behavior in the LP.
1686   /// These offsets are used as a minimum value for the cumuls over the route
1687   /// (or globally), i.e. a value we consider all cumuls to be greater or equal
1688   /// to. When transits are all positive, the cumuls of every node on a route is
1689   /// necessarily greater than the cumul of its start. Therefore, the local
1690   /// offset for a vehicle can be set to the minimum of its start node's cumul,
1691   /// and for the global optimizers, to the min start cumul over all vehicles.
1692   /// However, to be able to distinguish between infeasible nodes (i.e. nodes
1693   /// for which the cumul upper bound is less than the min cumul of the
1694   /// vehicle's start), we set the offset to "min_start_cumul" - 1. By doing so,
1695   /// all infeasible nodes described above will have bounds of [0, 0]. Example:
1696   /// Start cumul bounds: [11, 20] --> offset = 11 - 1 = 10.
1697   /// Two nodes with cumul bounds. Node1: [5, 10],  Node2: [7, 20]
1698   /// After applying the offset to the above windows, they become:
1699   /// Vehicle: [1, 10].     Node1: [0, 0] (infeasible).     Node2: [0, 10].
1700   ///
1701   /// On the other hand, when transits on a route can be negative, no assumption
1702   /// can be made on the cumuls of nodes wrt the start cumuls, and the offset is
1703   /// therefore set to 0.
1704   void StoreDimensionCumulOptimizers(const RoutingSearchParameters& parameters);
1705 
1706   void ComputeCostClasses(const RoutingSearchParameters& parameters);
1707   void ComputeVehicleClasses();
1708   /// The following method initializes the vehicle_type_container_:
1709   /// - Computes the vehicle types of vehicles and stores it in
1710   ///   type_index_of_vehicle.
1711   /// - The vehicle classes corresponding to each vehicle type index are stored
1712   ///   and sorted by fixed cost in sorted_vehicle_classes_per_type.
1713   /// - The vehicles for each vehicle class are stored in
1714   ///   vehicles_per_vehicle_class.
1715   void ComputeVehicleTypes();
1716   /// This method scans the visit types and sets up the following members:
1717   /// - single_nodes_of_type_[type] contains indices of nodes of visit type
1718   ///   "type" which are not part of any pickup/delivery pair.
1719   /// - pair_indices_of_type_[type] is the set of "pair_index" such that
1720   ///   pickup_delivery_pairs_[pair_index] has at least one pickup or delivery
1721   ///   with visit type "type".
1722   /// - topologically_sorted_visit_types_ contains the visit types in
1723   ///   topological order based on required-->dependent arcs from the
1724   ///   visit type requirements.
1725   void FinalizeVisitTypes();
1726   // Called by FinalizeVisitTypes() to setup topologically_sorted_visit_types_.
1727   void TopologicallySortVisitTypes();
1728   int64_t GetArcCostForClassInternal(int64_t from_index, int64_t to_index,
1729                                      CostClassIndex cost_class_index) const;
1730   void AppendHomogeneousArcCosts(const RoutingSearchParameters& parameters,
1731                                  int node_index,
1732                                  std::vector<IntVar*>* cost_elements);
1733   void AppendArcCosts(const RoutingSearchParameters& parameters, int node_index,
1734                       std::vector<IntVar*>* cost_elements);
1735   Assignment* DoRestoreAssignment();
1736   static const CostClassIndex kCostClassIndexOfZeroCost;
SafeGetCostClassInt64OfVehicle(int64_t vehicle)1737   int64_t SafeGetCostClassInt64OfVehicle(int64_t vehicle) const {
1738     DCHECK_LT(0, vehicles_);
1739     return (vehicle >= 0 ? GetCostClassIndexOfVehicle(vehicle)
1740                          : kCostClassIndexOfZeroCost)
1741         .value();
1742   }
1743   int64_t GetDimensionTransitCostSum(int64_t i, int64_t j,
1744                                      const CostClass& cost_class) const;
1745   /// Returns nullptr if no penalty cost, otherwise returns penalty variable.
1746   IntVar* CreateDisjunction(DisjunctionIndex disjunction);
1747   /// Sets up pickup and delivery sets.
1748   void AddPickupAndDeliverySetsInternal(const std::vector<int64_t>& pickups,
1749                                         const std::vector<int64_t>& deliveries);
1750   /// Returns the cost variable related to the soft same vehicle constraint of
1751   /// index 'vehicle_index'.
1752   IntVar* CreateSameVehicleCost(int vehicle_index);
1753   /// Returns the first active variable index in 'indices' starting from index
1754   /// + 1.
1755   int FindNextActive(int index, const std::vector<int64_t>& indices) const;
1756 
1757   /// Checks that all nodes on the route starting at start_index (using the
1758   /// solution stored in assignment) can be visited by the given vehicle.
1759   bool RouteCanBeUsedByVehicle(const Assignment& assignment, int start_index,
1760                                int vehicle) const;
1761   /// Replaces the route of unused_vehicle with the route of active_vehicle in
1762   /// compact_assignment. Expects that unused_vehicle is a vehicle with an empty
1763   /// route and that the route of active_vehicle is non-empty. Also expects that
1764   /// 'assignment' contains the original assignment, from which
1765   /// compact_assignment was created.
1766   /// Returns true if the vehicles were successfully swapped; otherwise, returns
1767   /// false.
1768   bool ReplaceUnusedVehicle(int unused_vehicle, int active_vehicle,
1769                             Assignment* compact_assignment) const;
1770 
1771   void QuietCloseModel();
QuietCloseModelWithParameters(const RoutingSearchParameters & parameters)1772   void QuietCloseModelWithParameters(
1773       const RoutingSearchParameters& parameters) {
1774     if (!closed_) {
1775       CloseModelWithParameters(parameters);
1776     }
1777   }
1778 
1779   /// Solve matching problem with min-cost flow and store result in assignment.
1780   bool SolveMatchingModel(Assignment* assignment,
1781                           const RoutingSearchParameters& parameters);
1782 #ifndef SWIG
1783   /// Append an assignment to a vector of assignments if it is feasible.
1784   bool AppendAssignmentIfFeasible(
1785       const Assignment& assignment,
1786       std::vector<std::unique_ptr<Assignment>>* assignments);
1787 #endif
1788   /// Log a solution.
1789   void LogSolution(const RoutingSearchParameters& parameters,
1790                    const std::string& description, int64_t solution_cost,
1791                    int64_t start_time_ms);
1792   /// See CompactAssignment. Checks the final solution if
1793   /// check_compact_assignment is true.
1794   Assignment* CompactAssignmentInternal(const Assignment& assignment,
1795                                         bool check_compact_assignment) const;
1796   /// Checks that the current search parameters are valid for the current
1797   /// model's specific settings. This assumes that FindErrorInSearchParameters()
1798   /// from
1799   /// ./routing_flags.h caught no error.
1800   std::string FindErrorInSearchParametersForModel(
1801       const RoutingSearchParameters& search_parameters) const;
1802   /// Sets up search objects, such as decision builders and monitors.
1803   void SetupSearch(const RoutingSearchParameters& search_parameters);
1804   /// Set of auxiliary methods used to setup the search.
1805   // TODO(user): Document each auxiliary method.
1806   Assignment* GetOrCreateAssignment();
1807   Assignment* GetOrCreateTmpAssignment();
1808   RegularLimit* GetOrCreateLimit();
1809   RegularLimit* GetOrCreateLocalSearchLimit();
1810   RegularLimit* GetOrCreateLargeNeighborhoodSearchLimit();
1811   RegularLimit* GetOrCreateFirstSolutionLargeNeighborhoodSearchLimit();
1812   LocalSearchOperator* CreateInsertionOperator();
1813   LocalSearchOperator* CreateMakeInactiveOperator();
1814   template <class T>
CreateCPOperator(const T & operator_factory)1815   LocalSearchOperator* CreateCPOperator(const T& operator_factory) {
1816     return operator_factory(solver_.get(), nexts_,
1817                             CostsAreHomogeneousAcrossVehicles()
1818                                 ? std::vector<IntVar*>()
1819                                 : vehicle_vars_,
1820                             vehicle_start_class_callback_);
1821   }
1822   template <class T>
CreateCPOperator()1823   LocalSearchOperator* CreateCPOperator() {
1824     return CreateCPOperator(MakeLocalSearchOperator<T>);
1825   }
1826   template <class T, class Arg>
CreateOperator(const Arg & arg)1827   LocalSearchOperator* CreateOperator(const Arg& arg) {
1828     return solver_->RevAlloc(new T(nexts_,
1829                                    CostsAreHomogeneousAcrossVehicles()
1830                                        ? std::vector<IntVar*>()
1831                                        : vehicle_vars_,
1832                                    vehicle_start_class_callback_, arg));
1833   }
1834   template <class T>
CreatePairOperator()1835   LocalSearchOperator* CreatePairOperator() {
1836     return CreateOperator<T>(pickup_delivery_pairs_);
1837   }
1838   void CreateNeighborhoodOperators(const RoutingSearchParameters& parameters);
1839   LocalSearchOperator* ConcatenateOperators(
1840       const RoutingSearchParameters& search_parameters,
1841       const std::vector<LocalSearchOperator*>& operators) const;
1842   LocalSearchOperator* GetNeighborhoodOperators(
1843       const RoutingSearchParameters& search_parameters) const;
1844   std::vector<LocalSearchFilterManager::FilterEvent>
1845   GetOrCreateLocalSearchFilters(const RoutingSearchParameters& parameters,
1846                                 bool filter_cost = true);
1847   LocalSearchFilterManager* GetOrCreateLocalSearchFilterManager(
1848       const RoutingSearchParameters& parameters);
1849   std::vector<LocalSearchFilterManager::FilterEvent>
1850   GetOrCreateFeasibilityFilters(const RoutingSearchParameters& parameters);
1851   LocalSearchFilterManager* GetOrCreateFeasibilityFilterManager(
1852       const RoutingSearchParameters& parameters);
1853   LocalSearchFilterManager* GetOrCreateStrongFeasibilityFilterManager(
1854       const RoutingSearchParameters& parameters);
1855   DecisionBuilder* CreateSolutionFinalizer(SearchLimit* lns_limit);
1856   DecisionBuilder* CreateFinalizerForMinimizedAndMaximizedVariables();
1857   void CreateFirstSolutionDecisionBuilders(
1858       const RoutingSearchParameters& search_parameters);
1859   DecisionBuilder* GetFirstSolutionDecisionBuilder(
1860       const RoutingSearchParameters& search_parameters) const;
1861   IntVarFilteredDecisionBuilder* GetFilteredFirstSolutionDecisionBuilderOrNull(
1862       const RoutingSearchParameters& parameters) const;
1863   LocalSearchPhaseParameters* CreateLocalSearchParameters(
1864       const RoutingSearchParameters& search_parameters);
1865   DecisionBuilder* CreateLocalSearchDecisionBuilder(
1866       const RoutingSearchParameters& search_parameters);
1867   void SetupDecisionBuilders(const RoutingSearchParameters& search_parameters);
1868   void SetupMetaheuristics(const RoutingSearchParameters& search_parameters);
1869   void SetupAssignmentCollector(
1870       const RoutingSearchParameters& search_parameters);
1871   void SetupTrace(const RoutingSearchParameters& search_parameters);
1872   void SetupImprovementLimit(const RoutingSearchParameters& search_parameters);
1873   void SetupSearchMonitors(const RoutingSearchParameters& search_parameters);
1874   bool UsesLightPropagation(
1875       const RoutingSearchParameters& search_parameters) const;
1876   GetTabuVarsCallback tabu_var_callback_;
1877 
1878   // Detects implicit pickup delivery pairs. These pairs are
1879   // non-pickup/delivery pairs for which there exists a unary dimension such
1880   // that the demand d of the implicit pickup is positive and the demand of the
1881   // implicit delivery is equal to -d.
1882   void DetectImplicitPickupAndDeliveries();
1883 
1884   int GetVehicleStartClass(int64_t start) const;
1885 
InitSameVehicleGroups(int number_of_groups)1886   void InitSameVehicleGroups(int number_of_groups) {
1887     same_vehicle_group_.assign(Size(), 0);
1888     same_vehicle_groups_.assign(number_of_groups, {});
1889   }
SetSameVehicleGroup(int index,int group)1890   void SetSameVehicleGroup(int index, int group) {
1891     same_vehicle_group_[index] = group;
1892     same_vehicle_groups_[group].push_back(index);
1893   }
1894 
1895   /// Model
1896   std::unique_ptr<Solver> solver_;
1897   int nodes_;
1898   int vehicles_;
1899   int max_active_vehicles_;
1900   Constraint* no_cycle_constraint_ = nullptr;
1901   /// Decision variables: indexed by int64_t var index.
1902   std::vector<IntVar*> nexts_;
1903   std::vector<IntVar*> vehicle_vars_;
1904   std::vector<IntVar*> active_;
1905   /// Resource variables, indexed first by resource group index and then by
1906   /// vehicle index.
1907   // clang-format off
1908   std::vector<std::vector<IntVar*> > resource_vars_;
1909   // clang-format on
1910   // The following vectors are indexed by vehicle index.
1911   std::vector<IntVar*> vehicle_active_;
1912   std::vector<IntVar*> vehicle_route_considered_;
1913   /// is_bound_to_end_[i] will be true iff the path starting at var #i is fully
1914   /// bound and reaches the end of a route, i.e. either:
1915   /// - IsEnd(i) is true
1916   /// - or nexts_[i] is bound and is_bound_to_end_[nexts_[i].Value()] is true.
1917   std::vector<IntVar*> is_bound_to_end_;
1918   mutable RevSwitch is_bound_to_end_ct_added_;
1919   /// Dimensions
1920   absl::flat_hash_map<std::string, DimensionIndex> dimension_name_to_index_;
1921   absl::StrongVector<DimensionIndex, RoutingDimension*> dimensions_;
1922   /// Resource Groups.
1923   /// If resource_groups_ is not empty, then for each group of resources, each
1924   /// (used) vehicle must be assigned to exactly 1 resource, and each resource
1925   /// can in turn be assigned to at most 1 vehicle.
1926   // clang-format off
1927   std::vector<std::unique_ptr<ResourceGroup> > resource_groups_;
1928   /// Stores the set of resource groups related to each dimension.
1929   absl::StrongVector<DimensionIndex, std::vector<int> >
1930       dimension_resource_group_indices_;
1931 
1932   /// TODO(user): Define a new Dimension[Global|Local]OptimizerIndex type
1933   /// and use it to define ITIVectors and for the dimension to optimizer index
1934   /// mappings below.
1935   std::vector<std::unique_ptr<GlobalDimensionCumulOptimizer> >
1936       global_dimension_optimizers_;
1937   std::vector<std::unique_ptr<GlobalDimensionCumulOptimizer> >
1938       global_dimension_mp_optimizers_;
1939   absl::StrongVector<DimensionIndex, int> global_optimizer_index_;
1940   std::vector<std::unique_ptr<LocalDimensionCumulOptimizer> >
1941       local_dimension_optimizers_;
1942   std::vector<std::unique_ptr<LocalDimensionCumulOptimizer> >
1943       local_dimension_mp_optimizers_;
1944   // clang-format off
1945   absl::StrongVector<DimensionIndex, int> local_optimizer_index_;
1946   std::string primary_constrained_dimension_;
1947   /// Costs
1948   IntVar* cost_ = nullptr;
1949   std::vector<int> vehicle_to_transit_cost_;
1950   std::vector<int64_t> fixed_cost_of_vehicle_;
1951   std::vector<CostClassIndex> cost_class_index_of_vehicle_;
1952   bool has_vehicle_with_zero_cost_class_;
1953   std::vector<int64_t> linear_cost_factor_of_vehicle_;
1954   std::vector<int64_t> quadratic_cost_factor_of_vehicle_;
1955   bool vehicle_amortized_cost_factors_set_;
1956   /// vehicle_used_when_empty_[vehicle] determines if "vehicle" should be
1957   /// taken into account for costs (arc costs, span costs, etc.) and constraints
1958   /// (eg. resources) even when the route of the vehicle is empty (i.e. goes
1959   /// straight from its start to its end).
1960   ///
1961   /// NOTE1: A vehicle's fixed cost is added iff the vehicle serves nodes on its
1962   /// route, regardless of this variable's value.
1963   ///
1964   /// NOTE2: The default value for this boolean is 'false' for all vehicles,
1965   /// i.e. by default empty routes will not contribute to the cost nor be
1966   /// considered for constraints.
1967   std::vector<bool> vehicle_used_when_empty_;
1968 #ifndef SWIG
1969   absl::StrongVector<CostClassIndex, CostClass> cost_classes_;
1970 #endif  // SWIG
1971   bool costs_are_homogeneous_across_vehicles_;
1972   bool cache_callbacks_;
1973   mutable std::vector<CostCacheElement> cost_cache_;  /// Index by source index.
1974   std::vector<VehicleClassIndex> vehicle_class_index_of_vehicle_;
1975 #ifndef SWIG
1976   absl::StrongVector<VehicleClassIndex, VehicleClass> vehicle_classes_;
1977 #endif  // SWIG
1978   VehicleTypeContainer vehicle_type_container_;
1979   std::function<int(int64_t)> vehicle_start_class_callback_;
1980   /// Disjunctions
1981   absl::StrongVector<DisjunctionIndex, Disjunction> disjunctions_;
1982   std::vector<std::vector<DisjunctionIndex> > index_to_disjunctions_;
1983   /// Same vehicle costs
1984   std::vector<ValuedNodes<int64_t> > same_vehicle_costs_;
1985   /// Allowed vehicles
1986 #ifndef SWIG
1987   std::vector<absl::flat_hash_set<int>> allowed_vehicles_;
1988 #endif  // SWIG
1989   /// Pickup and delivery
1990   IndexPairs pickup_delivery_pairs_;
1991   IndexPairs implicit_pickup_delivery_pairs_without_alternatives_;
1992   std::vector<std::pair<DisjunctionIndex, DisjunctionIndex> >
1993       pickup_delivery_disjunctions_;
1994   // clang-format off
1995   // If node_index is a pickup, index_to_pickup_index_pairs_[node_index] is the
1996   // vector of pairs {pair_index, pickup_index} such that
1997   // (pickup_delivery_pairs_[pair_index].first)[pickup_index] == node_index
1998   std::vector<std::vector<std::pair<int, int> > > index_to_pickup_index_pairs_;
1999   // Same as above for deliveries.
2000   std::vector<std::vector<std::pair<int, int> > >
2001       index_to_delivery_index_pairs_;
2002   // clang-format on
2003   std::vector<PickupAndDeliveryPolicy> vehicle_pickup_delivery_policy_;
2004   // Same vehicle group to which a node belongs.
2005   std::vector<int> same_vehicle_group_;
2006   // Same vehicle node groups.
2007   std::vector<std::vector<int>> same_vehicle_groups_;
2008   // Node visit types
2009   // Variable index to visit type index.
2010   std::vector<int> index_to_visit_type_;
2011   // Variable index to VisitTypePolicy.
2012   std::vector<VisitTypePolicy> index_to_type_policy_;
2013   // clang-format off
2014   std::vector<std::vector<int> > single_nodes_of_type_;
2015   std::vector<std::vector<int> > pair_indices_of_type_;
2016 
2017   std::vector<absl::flat_hash_set<int> >
2018       hard_incompatible_types_per_type_index_;
2019   bool has_hard_type_incompatibilities_;
2020   std::vector<absl::flat_hash_set<int> >
2021       temporal_incompatible_types_per_type_index_;
2022   bool has_temporal_type_incompatibilities_;
2023 
2024   std::vector<std::vector<absl::flat_hash_set<int> > >
2025       same_vehicle_required_type_alternatives_per_type_index_;
2026   bool has_same_vehicle_type_requirements_;
2027   std::vector<std::vector<absl::flat_hash_set<int> > >
2028       required_type_alternatives_when_adding_type_index_;
2029   std::vector<std::vector<absl::flat_hash_set<int> > >
2030       required_type_alternatives_when_removing_type_index_;
2031   bool has_temporal_type_requirements_;
2032   absl::flat_hash_map</*type*/int, absl::flat_hash_set<VisitTypePolicy> >
2033       trivially_infeasible_visit_types_to_policies_;
2034 
2035   // Visit types sorted topologically based on required-->dependent requirement
2036   // arcs between the types (if the requirement/dependency graph is acyclic).
2037   // Visit types of the same topological level are sorted in each sub-vector
2038   // by decreasing requirement "tightness", computed as the pair of the two
2039   // following criteria:
2040   //
2041   // 1) How highly *dependent* this type is, determined by
2042   //    (total number of required alternative sets for that type)
2043   //        / (average number of types in the required alternative sets)
2044   // 2) How highly *required* this type t is, computed as
2045   //    SUM_{S required set containing t} ( 1 / |S| ),
2046   //    i.e. the sum of reverse number of elements of all required sets
2047   //    containing the type t.
2048   //
2049   // The higher these two numbers, the tighter the type is wrt requirements.
2050   std::vector<std::vector<int> > topologically_sorted_visit_types_;
2051   // clang-format on
2052   int num_visit_types_;
2053   // Two indices are equivalent if they correspond to the same node (as given
2054   // to the constructors taking a RoutingIndexManager).
2055   std::vector<int> index_to_equivalence_class_;
2056   std::vector<int> index_to_vehicle_;
2057   std::vector<int64_t> starts_;
2058   std::vector<int64_t> ends_;
2059   // TODO(user): b/62478706 Once the port is done, this shouldn't be needed
2060   //                  anymore.
2061   RoutingIndexManager manager_;
2062   int start_end_count_;
2063   // Model status
2064   bool closed_ = false;
2065   Status status_ = ROUTING_NOT_SOLVED;
2066   bool enable_deep_serialization_ = true;
2067 
2068   // Search data
2069   std::vector<DecisionBuilder*> first_solution_decision_builders_;
2070   std::vector<IntVarFilteredDecisionBuilder*>
2071       first_solution_filtered_decision_builders_;
2072   Solver::IndexEvaluator2 first_solution_evaluator_;
2073   FirstSolutionStrategy::Value automatic_first_solution_strategy_ =
2074       FirstSolutionStrategy::UNSET;
2075   std::vector<LocalSearchOperator*> local_search_operators_;
2076   std::vector<SearchMonitor*> monitors_;
2077   SolutionCollector* collect_assignments_ = nullptr;
2078   SolutionCollector* collect_one_assignment_ = nullptr;
2079   SolutionCollector* packed_dimensions_assignment_collector_ = nullptr;
2080   DecisionBuilder* solve_db_ = nullptr;
2081   DecisionBuilder* improve_db_ = nullptr;
2082   DecisionBuilder* restore_assignment_ = nullptr;
2083   DecisionBuilder* restore_tmp_assignment_ = nullptr;
2084   Assignment* assignment_ = nullptr;
2085   Assignment* preassignment_ = nullptr;
2086   Assignment* tmp_assignment_ = nullptr;
2087   std::vector<IntVar*> extra_vars_;
2088   std::vector<IntervalVar*> extra_intervals_;
2089   std::vector<LocalSearchOperator*> extra_operators_;
2090   LocalSearchFilterManager* local_search_filter_manager_ = nullptr;
2091   LocalSearchFilterManager* feasibility_filter_manager_ = nullptr;
2092   LocalSearchFilterManager* strong_feasibility_filter_manager_ = nullptr;
2093   std::vector<LocalSearchFilterManager::FilterEvent> extra_filters_;
2094 #ifndef SWIG
2095   std::vector<std::pair<IntVar*, int64_t>> finalizer_variable_cost_pairs_;
2096   std::vector<std::pair<IntVar*, int64_t>> finalizer_variable_target_pairs_;
2097   absl::flat_hash_map<IntVar*, int> finalizer_variable_cost_index_;
2098   absl::flat_hash_set<IntVar*> finalizer_variable_target_set_;
2099   std::unique_ptr<SweepArranger> sweep_arranger_;
2100 #endif
2101 
2102   RegularLimit* limit_ = nullptr;
2103   RegularLimit* ls_limit_ = nullptr;
2104   RegularLimit* lns_limit_ = nullptr;
2105   RegularLimit* first_solution_lns_limit_ = nullptr;
2106 
2107   typedef std::pair<int64_t, int64_t> CacheKey;
2108   typedef absl::flat_hash_map<CacheKey, int64_t> TransitCallbackCache;
2109   typedef absl::flat_hash_map<CacheKey, StateDependentTransit>
2110       StateDependentTransitCallbackCache;
2111 
2112   std::vector<TransitCallback1> unary_transit_evaluators_;
2113   std::vector<TransitCallback2> transit_evaluators_;
2114   // The following vector stores a boolean per transit_evaluator_, indicating
2115   // whether the transits are all positive.
2116   // is_transit_evaluator_positive_ will be set to true only when registering a
2117   // callback via RegisterPositiveTransitCallback(), and to false otherwise.
2118   // The actual positivity of the transit values will only be checked in debug
2119   // mode, when calling RegisterPositiveTransitCallback().
2120   // Therefore, RegisterPositiveTransitCallback() should only be called when the
2121   // transits are known to be positive, as the positivity of a callback will
2122   // allow some improvements in the solver, but will entail in errors if the
2123   // transits are falsely assumed positive.
2124   std::vector<bool> is_transit_evaluator_positive_;
2125   std::vector<VariableIndexEvaluator2> state_dependent_transit_evaluators_;
2126   std::vector<std::unique_ptr<StateDependentTransitCallbackCache>>
2127       state_dependent_transit_evaluators_cache_;
2128 
2129   friend class RoutingDimension;
2130   friend class RoutingModelInspector;
2131   friend class ResourceGroup::Resource;
2132 
2133   DISALLOW_COPY_AND_ASSIGN(RoutingModel);
2134 };
2135 
2136 /// Routing model visitor.
2137 class RoutingModelVisitor : public BaseObject {
2138  public:
2139   /// Constraint types.
2140   static const char kLightElement[];
2141   static const char kLightElement2[];
2142   static const char kRemoveValues[];
2143 };
2144 
2145 #if !defined(SWIG)
2146 /// This class acts like a CP propagator: it takes a set of tasks given by
2147 /// their start/duration/end features, and reduces the range of possible values.
2148 class DisjunctivePropagator {
2149  public:
2150   /// A structure to hold tasks described by their features.
2151   /// The first num_chain_tasks are considered linked by a chain of precedences,
2152   /// i.e. if i < j < num_chain_tasks, then end(i) <= start(j).
2153   /// This occurs frequently in routing, and can be leveraged by
2154   /// some variants of classic propagators.
2155   struct Tasks {
2156     int num_chain_tasks = 0;
2157     std::vector<int64_t> start_min;
2158     std::vector<int64_t> start_max;
2159     std::vector<int64_t> duration_min;
2160     std::vector<int64_t> duration_max;
2161     std::vector<int64_t> end_min;
2162     std::vector<int64_t> end_max;
2163     std::vector<bool> is_preemptible;
2164     std::vector<const SortedDisjointIntervalList*> forbidden_intervals;
2165     std::vector<std::pair<int64_t, int64_t>> distance_duration;
2166     int64_t span_min = 0;
2167     int64_t span_max = kint64max;
2168 
ClearTasks2169     void Clear() {
2170       start_min.clear();
2171       start_max.clear();
2172       duration_min.clear();
2173       duration_max.clear();
2174       end_min.clear();
2175       end_max.clear();
2176       is_preemptible.clear();
2177       forbidden_intervals.clear();
2178       distance_duration.clear();
2179       span_min = 0;
2180       span_max = kint64max;
2181       num_chain_tasks = 0;
2182     }
2183   };
2184 
2185   /// Computes new bounds for all tasks, returns false if infeasible.
2186   /// This does not compute a fixed point, so recalling it may filter more.
2187   bool Propagate(Tasks* tasks);
2188 
2189   /// Propagates the deductions from the chain of precedences, if there is one.
2190   bool Precedences(Tasks* tasks);
2191   /// Transforms the problem with a time symmetry centered in 0. Returns true
2192   /// for convenience.
2193   bool MirrorTasks(Tasks* tasks);
2194   /// Does edge-finding deductions on all tasks.
2195   bool EdgeFinding(Tasks* tasks);
2196   /// Does detectable precedences deductions on tasks in the chain precedence,
2197   /// taking the time windows of nonchain tasks into account.
2198   bool DetectablePrecedencesWithChain(Tasks* tasks);
2199   /// Tasks might have holes in their domain, this enforces such holes.
2200   bool ForbiddenIntervals(Tasks* tasks);
2201   /// Propagates distance_duration constraints, if any.
2202   bool DistanceDuration(Tasks* tasks);
2203   /// Propagates a lower bound of the chain span,
2204   /// end[num_chain_tasks] - start[0], to span_min.
2205   bool ChainSpanMin(Tasks* tasks);
2206   /// Computes a lower bound of the span of the chain, taking into account only
2207   /// the first nonchain task.
2208   /// For more accurate results, this should be called after Precedences(),
2209   /// otherwise the lower bound might be lower than feasible.
2210   bool ChainSpanMinDynamic(Tasks* tasks);
2211 
2212  private:
2213   /// The main algorithm uses Vilim's theta tree data structure.
2214   /// See Petr Vilim's PhD thesis "Global Constraints in Scheduling".
2215   sat::ThetaLambdaTree<int64_t> theta_lambda_tree_;
2216   /// Mappings between events and tasks.
2217   std::vector<int> tasks_by_start_min_;
2218   std::vector<int> tasks_by_end_max_;
2219   std::vector<int> event_of_task_;
2220   std::vector<int> nonchain_tasks_by_start_max_;
2221   /// Maps chain elements to the sum of chain task durations before them.
2222   std::vector<int64_t> total_duration_before_;
2223 };
2224 
2225 struct TravelBounds {
2226   std::vector<int64_t> min_travels;
2227   std::vector<int64_t> max_travels;
2228   std::vector<int64_t> pre_travels;
2229   std::vector<int64_t> post_travels;
2230 };
2231 
2232 void AppendTasksFromPath(const std::vector<int64_t>& path,
2233                          const TravelBounds& travel_bounds,
2234                          const RoutingDimension& dimension,
2235                          DisjunctivePropagator::Tasks* tasks);
2236 void AppendTasksFromIntervals(const std::vector<IntervalVar*>& intervals,
2237                               DisjunctivePropagator::Tasks* tasks);
2238 void FillPathEvaluation(const std::vector<int64_t>& path,
2239                         const RoutingModel::TransitCallback2& evaluator,
2240                         std::vector<int64_t>* values);
2241 void FillTravelBoundsOfVehicle(int vehicle, const std::vector<int64_t>& path,
2242                                const RoutingDimension& dimension,
2243                                TravelBounds* travel_bounds);
2244 #endif  // !defined(SWIG)
2245 
2246 /// GlobalVehicleBreaksConstraint ensures breaks constraints are enforced on
2247 /// all vehicles in the dimension passed to its constructor.
2248 /// It is intended to be used for dimensions representing time.
2249 /// A break constraint ensures break intervals fit on the route of a vehicle.
2250 /// For a given vehicle, it forces break intervals to be disjoint from visit
2251 /// intervals, where visit intervals start at CumulVar(node) and last for
2252 /// node_visit_transit[node]. Moreover, it ensures that there is enough time
2253 /// between two consecutive nodes of a route to do transit and vehicle breaks,
2254 /// i.e. if Next(nodeA) = nodeB, CumulVar(nodeA) = tA and CumulVar(nodeB) = tB,
2255 /// then SlackVar(nodeA) >= sum_{breaks \subseteq [tA, tB)} duration(break).
2256 class GlobalVehicleBreaksConstraint : public Constraint {
2257  public:
2258   explicit GlobalVehicleBreaksConstraint(const RoutingDimension* dimension);
DebugString()2259   std::string DebugString() const override {
2260     return "GlobalVehicleBreaksConstraint";
2261   }
2262 
2263   void Post() override;
2264   void InitialPropagate() override;
2265 
2266  private:
2267   void PropagateNode(int node);
2268   void PropagateVehicle(int vehicle);
2269   void PropagateMaxBreakDistance(int vehicle);
2270 
2271   const RoutingModel* model_;
2272   const RoutingDimension* const dimension_;
2273   std::vector<Demon*> vehicle_demons_;
2274   std::vector<int64_t> path_;
2275 
2276   /// Sets path_ to be the longest sequence such that
2277   /// _ path_[0] is the start of the vehicle
2278   /// _ Next(path_[i-1]) is Bound() and has value path_[i],
2279   /// followed by the end of the vehicle if the last node was not an end.
2280   void FillPartialPathOfVehicle(int vehicle);
2281   void FillPathTravels(const std::vector<int64_t>& path);
2282 
2283   /// This translates pruning information to solver variables.
2284   /// If constructed with an IntervalVar*, it follows the usual semantics of
2285   /// IntervalVars. If constructed with an IntVar*, before_start and
2286   /// after_start, operations are translated to simulate an interval that starts
2287   /// at start - before_start and ends and start + after_start. If constructed
2288   /// with nothing, the TaskTranslator will do nothing. This class should have
2289   /// been an interface + subclasses, but that would force pointers in the
2290   /// user's task vector, which means dynamic allocation. With this union-like
2291   /// structure, a vector's reserved size will adjust to usage and eventually no
2292   /// more dynamic allocation will be made.
2293   class TaskTranslator {
2294    public:
TaskTranslator(IntVar * start,int64_t before_start,int64_t after_start)2295     TaskTranslator(IntVar* start, int64_t before_start, int64_t after_start)
2296         : start_(start),
2297           before_start_(before_start),
2298           after_start_(after_start) {}
TaskTranslator(IntervalVar * interval)2299     explicit TaskTranslator(IntervalVar* interval) : interval_(interval) {}
TaskTranslator()2300     TaskTranslator() {}
2301 
SetStartMin(int64_t value)2302     void SetStartMin(int64_t value) {
2303       if (start_ != nullptr) {
2304         start_->SetMin(CapAdd(before_start_, value));
2305       } else if (interval_ != nullptr) {
2306         interval_->SetStartMin(value);
2307       }
2308     }
SetStartMax(int64_t value)2309     void SetStartMax(int64_t value) {
2310       if (start_ != nullptr) {
2311         start_->SetMax(CapAdd(before_start_, value));
2312       } else if (interval_ != nullptr) {
2313         interval_->SetStartMax(value);
2314       }
2315     }
SetDurationMin(int64_t value)2316     void SetDurationMin(int64_t value) {
2317       if (interval_ != nullptr) {
2318         interval_->SetDurationMin(value);
2319       }
2320     }
SetEndMin(int64_t value)2321     void SetEndMin(int64_t value) {
2322       if (start_ != nullptr) {
2323         start_->SetMin(CapSub(value, after_start_));
2324       } else if (interval_ != nullptr) {
2325         interval_->SetEndMin(value);
2326       }
2327     }
SetEndMax(int64_t value)2328     void SetEndMax(int64_t value) {
2329       if (start_ != nullptr) {
2330         start_->SetMax(CapSub(value, after_start_));
2331       } else if (interval_ != nullptr) {
2332         interval_->SetEndMax(value);
2333       }
2334     }
2335 
2336    private:
2337     IntVar* start_ = nullptr;
2338     int64_t before_start_;
2339     int64_t after_start_;
2340     IntervalVar* interval_ = nullptr;
2341   };
2342 
2343   /// Route and interval variables are normalized to the following values.
2344   std::vector<TaskTranslator> task_translators_;
2345 
2346   /// This is used to restrict bounds of tasks.
2347   DisjunctivePropagator disjunctive_propagator_;
2348   DisjunctivePropagator::Tasks tasks_;
2349 
2350   /// Used to help filling tasks_ at each propagation.
2351   TravelBounds travel_bounds_;
2352 };
2353 
2354 class TypeRegulationsChecker {
2355  public:
2356   explicit TypeRegulationsChecker(const RoutingModel& model);
~TypeRegulationsChecker()2357   virtual ~TypeRegulationsChecker() {}
2358 
2359   bool CheckVehicle(int vehicle,
2360                     const std::function<int64_t(int64_t)>& next_accessor);
2361 
2362  protected:
2363 #ifndef SWIG
2364   using VisitTypePolicy = RoutingModel::VisitTypePolicy;
2365 #endif  // SWIG
2366 
2367   struct TypePolicyOccurrence {
2368     /// Number of TYPE_ADDED_TO_VEHICLE and
2369     /// TYPE_SIMULTANEOUSLY_ADDED_AND_REMOVED node type policies seen on the
2370     /// route.
2371     int num_type_added_to_vehicle = 0;
2372     /// Number of ADDED_TYPE_REMOVED_FROM_VEHICLE (effectively removing a type
2373     /// from the route) and TYPE_SIMULTANEOUSLY_ADDED_AND_REMOVED node type
2374     /// policies seen on the route.
2375     /// This number is always <= num_type_added_to_vehicle, as a type is only
2376     /// actually removed if it was on the route before.
2377     int num_type_removed_from_vehicle = 0;
2378     /// Position of the last node of policy TYPE_ON_VEHICLE_UP_TO_VISIT visited
2379     /// on the route.
2380     /// If positive, the type is considered on the vehicle from the start of the
2381     /// route until this position.
2382     int position_of_last_type_on_vehicle_up_to_visit = -1;
2383   };
2384 
2385   /// Returns true iff any occurrence of the given type was seen on the route,
2386   /// i.e. iff the added count for this type is positive, or if a node of this
2387   /// type and policy TYPE_ON_VEHICLE_UP_TO_VISIT is visited on the route (see
2388   /// TypePolicyOccurrence.last_type_on_vehicle_up_to_visit).
2389   bool TypeOccursOnRoute(int type) const;
2390   /// Returns true iff there's at least one instance of the given type on the
2391   /// route when scanning the route at the given position 'pos'.
2392   /// This is the case iff we have at least one added but non-removed instance
2393   /// of the type, or if
2394   /// occurrences_of_type_[type].last_type_on_vehicle_up_to_visit is greater
2395   /// than 'pos'.
2396   bool TypeCurrentlyOnRoute(int type, int pos) const;
2397 
2398   void InitializeCheck(int vehicle,
2399                        const std::function<int64_t(int64_t)>& next_accessor);
OnInitializeCheck()2400   virtual void OnInitializeCheck() {}
2401   virtual bool HasRegulationsToCheck() const = 0;
2402   virtual bool CheckTypeRegulations(int type, VisitTypePolicy policy,
2403                                     int pos) = 0;
FinalizeCheck()2404   virtual bool FinalizeCheck() const { return true; }
2405 
2406   const RoutingModel& model_;
2407 
2408  private:
2409   std::vector<TypePolicyOccurrence> occurrences_of_type_;
2410   std::vector<int64_t> current_route_visits_;
2411 };
2412 
2413 /// Checker for type incompatibilities.
2414 class TypeIncompatibilityChecker : public TypeRegulationsChecker {
2415  public:
2416   TypeIncompatibilityChecker(const RoutingModel& model,
2417                              bool check_hard_incompatibilities);
~TypeIncompatibilityChecker()2418   ~TypeIncompatibilityChecker() override {}
2419 
2420  private:
2421   bool HasRegulationsToCheck() const override;
2422   bool CheckTypeRegulations(int type, VisitTypePolicy policy, int pos) override;
2423   /// NOTE(user): As temporal incompatibilities are always verified with
2424   /// this checker, we only store 1 boolean indicating whether or not hard
2425   /// incompatibilities are also verified.
2426   bool check_hard_incompatibilities_;
2427 };
2428 
2429 /// Checker for type requirements.
2430 class TypeRequirementChecker : public TypeRegulationsChecker {
2431  public:
TypeRequirementChecker(const RoutingModel & model)2432   explicit TypeRequirementChecker(const RoutingModel& model)
2433       : TypeRegulationsChecker(model) {}
~TypeRequirementChecker()2434   ~TypeRequirementChecker() override {}
2435 
2436  private:
2437   bool HasRegulationsToCheck() const override;
OnInitializeCheck()2438   void OnInitializeCheck() override {
2439     types_with_same_vehicle_requirements_on_route_.clear();
2440   }
2441   // clang-format off
2442   /// Verifies that for each set in required_type_alternatives, at least one of
2443   /// the required types is on the route at position 'pos'.
2444   bool CheckRequiredTypesCurrentlyOnRoute(
2445       const std::vector<absl::flat_hash_set<int> >& required_type_alternatives,
2446       int pos);
2447   // clang-format on
2448   bool CheckTypeRegulations(int type, VisitTypePolicy policy, int pos) override;
2449   bool FinalizeCheck() const override;
2450 
2451   absl::flat_hash_set<int> types_with_same_vehicle_requirements_on_route_;
2452 };
2453 
2454 /// The following constraint ensures that incompatibilities and requirements
2455 /// between types are respected.
2456 ///
2457 /// It verifies both "hard" and "temporal" incompatibilities.
2458 /// Two nodes with hard incompatible types cannot be served by the same vehicle
2459 /// at all, while with a temporal incompatibility they can't be on the same
2460 /// route at the same time.
2461 /// The VisitTypePolicy of a node determines how visiting it impacts the type
2462 /// count on the route.
2463 ///
2464 /// For example, for
2465 /// - three temporally incompatible types T1 T2 and T3
2466 /// - 2 pairs of nodes a1/r1 and a2/r2 of type T1 and T2 respectively, with
2467 ///     - a1 and a2 of VisitTypePolicy TYPE_ADDED_TO_VEHICLE
2468 ///     - r1 and r2 of policy ADDED_TYPE_REMOVED_FROM_VEHICLE
2469 /// - 3 nodes A, UV and AR of type T3, respectively with type policies
2470 ///   TYPE_ADDED_TO_VEHICLE, TYPE_ON_VEHICLE_UP_TO_VISIT and
2471 ///   TYPE_SIMULTANEOUSLY_ADDED_AND_REMOVED
2472 /// the configurations
2473 /// UV --> a1 --> r1 --> a2 --> r2,   a1 --> r1 --> a2 --> r2 --> A and
2474 /// a1 --> r1 --> AR --> a2 --> r2 are acceptable, whereas the configurations
2475 /// a1 --> a2 --> r1 --> ..., or A --> a1 --> r1 --> ..., or
2476 /// a1 --> r1 --> UV --> ... are not feasible.
2477 ///
2478 /// It also verifies same-vehicle and temporal type requirements.
2479 /// A node of type T_d with a same-vehicle requirement for type T_r needs to be
2480 /// served by the same vehicle as a node of type T_r.
2481 /// Temporal requirements, on the other hand, can take effect either when the
2482 /// dependent type is being added to the route or when it's removed from it,
2483 /// which is determined by the dependent node's VisitTypePolicy.
2484 /// In the above example:
2485 /// - If T3 is required on the same vehicle as T1, A, AR or UV must be on the
2486 ///   same vehicle as a1.
2487 /// - If T2 is required when adding T1, a2 must be visited *before* a1, and if
2488 ///   r2 is also visited on the route, it must be *after* a1, i.e. T2 must be on
2489 ///   the vehicle when a1 is visited:
2490 ///   ... --> a2 --> ... --> a1 --> ... --> r2 --> ...
2491 /// - If T3 is required when removing T1, T3 needs to be on the vehicle when
2492 ///   r1 is visited:
2493 ///   ... --> A --> ... --> r1 --> ...   OR   ... --> r1 --> ... --> UV --> ...
2494 class TypeRegulationsConstraint : public Constraint {
2495  public:
2496   explicit TypeRegulationsConstraint(const RoutingModel& model);
2497 
2498   void Post() override;
2499   void InitialPropagate() override;
2500 
2501  private:
2502   void PropagateNodeRegulations(int node);
2503   void CheckRegulationsOnVehicle(int vehicle);
2504 
2505   const RoutingModel& model_;
2506   TypeIncompatibilityChecker incompatibility_checker_;
2507   TypeRequirementChecker requirement_checker_;
2508   std::vector<Demon*> vehicle_demons_;
2509 };
2510 #if !defined SWIG
2511 /// A structure meant to store soft bounds and associated violation constants.
2512 /// It is 'Simple' because it has one BoundCost per element,
2513 /// in contrast to 'Multiple'. Design notes:
2514 /// - it is meant to store model information to be shared through pointers,
2515 ///   so it disallows copy and assign to avoid accidental duplication.
2516 /// - it keeps soft bounds as an array of structs to help cache,
2517 ///   because code that uses such bounds typically use both bound and cost.
2518 /// - soft bounds are named pairs, prevents some mistakes.
2519 /// - using operator[] to access elements is not interesting,
2520 ///   because the structure will be accessed through pointers, moreover having
2521 ///   to type bound_cost reminds the user of the order if they do a copy
2522 ///   assignment of the element.
2523 class SimpleBoundCosts {
2524  public:
2525   struct BoundCost {
2526     int64_t bound;
2527     int64_t cost;
2528   };
SimpleBoundCosts(int num_bounds,BoundCost default_bound_cost)2529   SimpleBoundCosts(int num_bounds, BoundCost default_bound_cost)
2530       : bound_costs_(num_bounds, default_bound_cost) {}
bound_cost(int element)2531   BoundCost& bound_cost(int element) { return bound_costs_[element]; }
bound_cost(int element)2532   BoundCost bound_cost(int element) const { return bound_costs_[element]; }
Size()2533   int Size() { return bound_costs_.size(); }
2534   SimpleBoundCosts(const SimpleBoundCosts&) = delete;
2535   SimpleBoundCosts operator=(const SimpleBoundCosts&) = delete;
2536 
2537  private:
2538   std::vector<BoundCost> bound_costs_;
2539 };
2540 #endif  // !defined SWIG
2541 
2542 /// Dimensions represent quantities accumulated at nodes along the routes. They
2543 /// represent quantities such as weights or volumes carried along the route, or
2544 /// distance or times.
2545 ///
2546 /// Quantities at a node are represented by "cumul" variables and the increase
2547 /// or decrease of quantities between nodes are represented by "transit"
2548 /// variables. These variables are linked as follows:
2549 ///
2550 /// if j == next(i),
2551 /// cumuls(j) = cumuls(i) + transits(i) + slacks(i) +
2552 ///             state_dependent_transits(i)
2553 ///
2554 /// where slack is a positive slack variable (can represent waiting times for
2555 /// a time dimension), and state_dependent_transits is a non-purely functional
2556 /// version of transits_. Favour transits over state_dependent_transits when
2557 /// possible, because purely functional callbacks allow more optimisations and
2558 /// make the model faster and easier to solve.
2559 // TODO(user): Break constraints need to know the service time of nodes
2560 /// for a given vehicle, it is passed as an external vector, it would be better
2561 /// to have this information here.
2562 class RoutingDimension {
2563  public:
2564   ~RoutingDimension();
2565   /// Returns the model on which the dimension was created.
model()2566   RoutingModel* model() const { return model_; }
2567   /// Returns the transition value for a given pair of nodes (as var index);
2568   /// this value is the one taken by the corresponding transit variable when
2569   /// the 'next' variable for 'from_index' is bound to 'to_index'.
2570   int64_t GetTransitValue(int64_t from_index, int64_t to_index,
2571                           int64_t vehicle) const;
2572   /// Same as above but taking a vehicle class of the dimension instead of a
2573   /// vehicle (the class of a vehicle can be obtained with vehicle_to_class()).
GetTransitValueFromClass(int64_t from_index,int64_t to_index,int64_t vehicle_class)2574   int64_t GetTransitValueFromClass(int64_t from_index, int64_t to_index,
2575                                    int64_t vehicle_class) const {
2576     return model_->TransitCallback(class_evaluators_[vehicle_class])(from_index,
2577                                                                      to_index);
2578   }
2579   /// Get the cumul, transit and slack variables for the given node (given as
2580   /// int64_t var index).
CumulVar(int64_t index)2581   IntVar* CumulVar(int64_t index) const { return cumuls_[index]; }
TransitVar(int64_t index)2582   IntVar* TransitVar(int64_t index) const { return transits_[index]; }
FixedTransitVar(int64_t index)2583   IntVar* FixedTransitVar(int64_t index) const {
2584     return fixed_transits_[index];
2585   }
SlackVar(int64_t index)2586   IntVar* SlackVar(int64_t index) const { return slacks_[index]; }
2587 
2588 #if !defined(SWIGPYTHON)
2589   /// Like CumulVar(), TransitVar(), SlackVar() but return the whole variable
2590   /// vectors instead (indexed by int64_t var index).
cumuls()2591   const std::vector<IntVar*>& cumuls() const { return cumuls_; }
fixed_transits()2592   const std::vector<IntVar*>& fixed_transits() const { return fixed_transits_; }
transits()2593   const std::vector<IntVar*>& transits() const { return transits_; }
slacks()2594   const std::vector<IntVar*>& slacks() const { return slacks_; }
2595 #if !defined(SWIGCSHARP) && !defined(SWIGJAVA)
2596   /// Returns forbidden intervals for each node.
forbidden_intervals()2597   const std::vector<SortedDisjointIntervalList>& forbidden_intervals() const {
2598     return forbidden_intervals_;
2599   }
2600   /// Returns allowed intervals for a given node in a given interval.
2601   SortedDisjointIntervalList GetAllowedIntervalsInRange(
2602       int64_t index, int64_t min_value, int64_t max_value) const;
2603   /// Returns the smallest value outside the forbidden intervals of node 'index'
2604   /// that is greater than or equal to a given 'min_value'.
GetFirstPossibleGreaterOrEqualValueForNode(int64_t index,int64_t min_value)2605   int64_t GetFirstPossibleGreaterOrEqualValueForNode(int64_t index,
2606                                                      int64_t min_value) const {
2607     DCHECK_LT(index, forbidden_intervals_.size());
2608     const SortedDisjointIntervalList& forbidden_intervals =
2609         forbidden_intervals_[index];
2610     const auto first_forbidden_interval_it =
2611         forbidden_intervals.FirstIntervalGreaterOrEqual(min_value);
2612     if (first_forbidden_interval_it != forbidden_intervals.end() &&
2613         min_value >= first_forbidden_interval_it->start) {
2614       /// min_value is in a forbidden interval.
2615       return CapAdd(first_forbidden_interval_it->end, 1);
2616     }
2617     /// min_value is not forbidden.
2618     return min_value;
2619   }
2620   /// Returns the largest value outside the forbidden intervals of node 'index'
2621   /// that is less than or equal to a given 'max_value'.
2622   /// NOTE: If this method is called with a max_value lower than the node's
2623   /// cumul min, it will return -1.
GetLastPossibleLessOrEqualValueForNode(int64_t index,int64_t max_value)2624   int64_t GetLastPossibleLessOrEqualValueForNode(int64_t index,
2625                                                  int64_t max_value) const {
2626     DCHECK_LT(index, forbidden_intervals_.size());
2627     const SortedDisjointIntervalList& forbidden_intervals =
2628         forbidden_intervals_[index];
2629     const auto last_forbidden_interval_it =
2630         forbidden_intervals.LastIntervalLessOrEqual(max_value);
2631     if (last_forbidden_interval_it != forbidden_intervals.end() &&
2632         max_value <= last_forbidden_interval_it->end) {
2633       /// max_value is in a forbidden interval.
2634       return CapSub(last_forbidden_interval_it->start, 1);
2635     }
2636     /// max_value is not forbidden.
2637     return max_value;
2638   }
2639   /// Returns the capacities for all vehicles.
vehicle_capacities()2640   const std::vector<int64_t>& vehicle_capacities() const {
2641     return vehicle_capacities_;
2642   }
2643   /// Returns the callback evaluating the transit value between two node indices
2644   /// for a given vehicle.
transit_evaluator(int vehicle)2645   const RoutingModel::TransitCallback2& transit_evaluator(int vehicle) const {
2646     return model_->TransitCallback(
2647         class_evaluators_[vehicle_to_class_[vehicle]]);
2648   }
2649 
2650   /// Returns the callback evaluating the transit value between two node indices
2651   /// for a given vehicle class.
class_transit_evaluator(RoutingVehicleClassIndex vehicle_class)2652   const RoutingModel::TransitCallback2& class_transit_evaluator(
2653       RoutingVehicleClassIndex vehicle_class) const {
2654     const int vehicle = model_->GetVehicleOfClass(vehicle_class);
2655     DCHECK_NE(vehicle, -1);
2656     return transit_evaluator(vehicle);
2657   }
2658 
2659   /// Returns the unary callback evaluating the transit value between two node
2660   /// indices for a given vehicle. If the corresponding callback is not unary,
2661   /// returns a null callback.
GetUnaryTransitEvaluator(int vehicle)2662   const RoutingModel::TransitCallback1& GetUnaryTransitEvaluator(
2663       int vehicle) const {
2664     return model_->UnaryTransitCallbackOrNull(
2665         class_evaluators_[vehicle_to_class_[vehicle]]);
2666   }
2667   /// Returns true iff the transit evaluator of 'vehicle' is positive for all
2668   /// arcs.
AreVehicleTransitsPositive(int vehicle)2669   bool AreVehicleTransitsPositive(int vehicle) const {
2670     return model()->is_transit_evaluator_positive_
2671         [class_evaluators_[vehicle_to_class_[vehicle]]];
2672   }
vehicle_to_class(int vehicle)2673   int vehicle_to_class(int vehicle) const { return vehicle_to_class_[vehicle]; }
2674 #endif  /// !defined(SWIGCSHARP) && !defined(SWIGJAVA)
2675 #endif  /// !defined(SWIGPYTHON)
2676   /// Sets an upper bound on the dimension span on a given vehicle. This is the
2677   /// preferred way to limit the "length" of the route of a vehicle according to
2678   /// a dimension.
2679   void SetSpanUpperBoundForVehicle(int64_t upper_bound, int vehicle);
2680   /// Sets a cost proportional to the dimension span on a given vehicle,
2681   /// or on all vehicles at once. "coefficient" must be nonnegative.
2682   /// This is handy to model costs proportional to idle time when the dimension
2683   /// represents time.
2684   /// The cost for a vehicle is
2685   ///   span_cost = coefficient * (dimension end value - dimension start value).
2686   void SetSpanCostCoefficientForVehicle(int64_t coefficient, int vehicle);
2687   void SetSpanCostCoefficientForAllVehicles(int64_t coefficient);
2688   /// Sets a cost proportional to the *global* dimension span, that is the
2689   /// difference between the largest value of route end cumul variables and
2690   /// the smallest value of route start cumul variables.
2691   /// In other words:
2692   /// global_span_cost =
2693   ///   coefficient * (Max(dimension end value) - Min(dimension start value)).
2694   void SetGlobalSpanCostCoefficient(int64_t coefficient);
2695 
2696 #ifndef SWIG
2697   /// Sets a piecewise linear cost on the cumul variable of a given variable
2698   /// index. If f is a piecewise linear function, the resulting cost at 'index'
2699   /// will be f(CumulVar(index)). As of 3/2017, only non-decreasing positive
2700   /// cost functions are supported.
2701   void SetCumulVarPiecewiseLinearCost(int64_t index,
2702                                       const PiecewiseLinearFunction& cost);
2703   /// Returns true if a piecewise linear cost has been set for a given variable
2704   /// index.
2705   bool HasCumulVarPiecewiseLinearCost(int64_t index) const;
2706   /// Returns the piecewise linear cost of a cumul variable for a given variable
2707   /// index. The returned pointer has the same validity as this class.
2708   const PiecewiseLinearFunction* GetCumulVarPiecewiseLinearCost(
2709       int64_t index) const;
2710 #endif
2711 
2712   /// Sets a soft upper bound to the cumul variable of a given variable index.
2713   /// If the value of the cumul variable is greater than the bound, a cost
2714   /// proportional to the difference between this value and the bound is added
2715   /// to the cost function of the model:
2716   ///   cumulVar <= upper_bound -> cost = 0
2717   ///    cumulVar > upper_bound -> cost = coefficient * (cumulVar - upper_bound)
2718   /// This is also handy to model tardiness costs when the dimension represents
2719   /// time.
2720   void SetCumulVarSoftUpperBound(int64_t index, int64_t upper_bound,
2721                                  int64_t coefficient);
2722   /// Returns true if a soft upper bound has been set for a given variable
2723   /// index.
2724   bool HasCumulVarSoftUpperBound(int64_t index) const;
2725   /// Returns the soft upper bound of a cumul variable for a given variable
2726   /// index. The "hard" upper bound of the variable is returned if no soft upper
2727   /// bound has been set.
2728   int64_t GetCumulVarSoftUpperBound(int64_t index) const;
2729   /// Returns the cost coefficient of the soft upper bound of a cumul variable
2730   /// for a given variable index. If no soft upper bound has been set, 0 is
2731   /// returned.
2732   int64_t GetCumulVarSoftUpperBoundCoefficient(int64_t index) const;
2733 
2734   /// Sets a soft lower bound to the cumul variable of a given variable index.
2735   /// If the value of the cumul variable is less than the bound, a cost
2736   /// proportional to the difference between this value and the bound is added
2737   /// to the cost function of the model:
2738   ///   cumulVar > lower_bound -> cost = 0
2739   ///   cumulVar <= lower_bound -> cost = coefficient * (lower_bound -
2740   ///               cumulVar).
2741   /// This is also handy to model earliness costs when the dimension represents
2742   /// time.
2743   void SetCumulVarSoftLowerBound(int64_t index, int64_t lower_bound,
2744                                  int64_t coefficient);
2745   /// Returns true if a soft lower bound has been set for a given variable
2746   /// index.
2747   bool HasCumulVarSoftLowerBound(int64_t index) const;
2748   /// Returns the soft lower bound of a cumul variable for a given variable
2749   /// index. The "hard" lower bound of the variable is returned if no soft lower
2750   /// bound has been set.
2751   int64_t GetCumulVarSoftLowerBound(int64_t index) const;
2752   /// Returns the cost coefficient of the soft lower bound of a cumul variable
2753   /// for a given variable index. If no soft lower bound has been set, 0 is
2754   /// returned.
2755   int64_t GetCumulVarSoftLowerBoundCoefficient(int64_t index) const;
2756   /// Sets the breaks for a given vehicle. Breaks are represented by
2757   /// IntervalVars. They may interrupt transits between nodes and increase
2758   /// the value of corresponding slack variables.
2759   /// A break may take place before the start of a vehicle, after the end of
2760   /// a vehicle, or during a travel i -> j.
2761   ///
2762   /// In that case, the interval [break.Start(), break.End()) must be a subset
2763   /// of [CumulVar(i) + pre_travel(i, j), CumulVar(j) - post_travel(i, j)). In
2764   /// other words, a break may not overlap any node n's visit, given by
2765   /// [CumulVar(n) - post_travel(_, n), CumulVar(n) + pre_travel(n, _)).
2766   /// This formula considers post_travel(_, start) and pre_travel(end, _) to be
2767   /// 0; pre_travel will never be called on any (_, start) and post_travel will
2768   /// never we called on any (end, _). If pre_travel_evaluator or
2769   /// post_travel_evaluator is -1, it will be taken as a function that always
2770   /// returns 0.
2771   // TODO(user): Remove if !defined when routing.i is repaired.
2772 #if !defined(SWIGPYTHON)
2773   void SetBreakIntervalsOfVehicle(std::vector<IntervalVar*> breaks, int vehicle,
2774                                   int pre_travel_evaluator,
2775                                   int post_travel_evaluator);
2776 #endif  // !defined(SWIGPYTHON)
2777 
2778   /// Deprecated, sets pre_travel(i, j) = node_visit_transit[i].
2779   void SetBreakIntervalsOfVehicle(std::vector<IntervalVar*> breaks, int vehicle,
2780                                   std::vector<int64_t> node_visit_transits);
2781 
2782   /// With breaks supposed to be consecutive, this forces the distance between
2783   /// breaks of size at least minimum_break_duration to be at most distance.
2784   /// This supposes that the time until route start and after route end are
2785   /// infinite breaks.
2786   void SetBreakDistanceDurationOfVehicle(int64_t distance, int64_t duration,
2787                                          int vehicle);
2788   /// Sets up vehicle_break_intervals_, vehicle_break_distance_duration_,
2789   /// pre_travel_evaluators and post_travel_evaluators.
2790   void InitializeBreaks();
2791   /// Returns true if any break interval or break distance was defined.
2792   bool HasBreakConstraints() const;
2793 #if !defined(SWIGPYTHON)
2794   /// Deprecated, sets pre_travel(i, j) = node_visit_transit[i]
2795   /// and post_travel(i, j) = delays(i, j).
2796   void SetBreakIntervalsOfVehicle(
2797       std::vector<IntervalVar*> breaks, int vehicle,
2798       std::vector<int64_t> node_visit_transits,
2799       std::function<int64_t(int64_t, int64_t)> delays);
2800 
2801   /// Returns the break intervals set by SetBreakIntervalsOfVehicle().
2802   const std::vector<IntervalVar*>& GetBreakIntervalsOfVehicle(
2803       int vehicle) const;
2804   /// Returns the pairs (distance, duration) specified by break distance
2805   /// constraints.
2806   // clang-format off
2807   const std::vector<std::pair<int64_t, int64_t> >&
2808       GetBreakDistanceDurationOfVehicle(int vehicle) const;
2809   // clang-format on
2810 #endif  /// !defined(SWIGPYTHON)
2811   int GetPreTravelEvaluatorOfVehicle(int vehicle) const;
2812   int GetPostTravelEvaluatorOfVehicle(int vehicle) const;
2813 
2814   /// Returns the parent in the dependency tree if any or nullptr otherwise.
base_dimension()2815   const RoutingDimension* base_dimension() const { return base_dimension_; }
2816   /// It makes sense to use the function only for self-dependent dimension.
2817   /// For such dimensions the value of the slack of a node determines the
2818   /// transition cost of the next transit. Provided that
2819   ///   1. cumul[node] is fixed,
2820   ///   2. next[node] and next[next[node]] (if exists) are fixed,
2821   /// the value of slack[node] for which cumul[next[node]] + transit[next[node]]
2822   /// is minimized can be found in O(1) using this function.
2823   int64_t ShortestTransitionSlack(int64_t node) const;
2824 
2825   /// Returns the name of the dimension.
name()2826   const std::string& name() const { return name_; }
2827 
2828   /// Accessors.
2829 #ifndef SWIG
GetPathPrecedenceGraph()2830   const ReverseArcListGraph<int, int>& GetPathPrecedenceGraph() const {
2831     return path_precedence_graph_;
2832   }
2833 #endif  // SWIG
2834 
2835   /// Limits, in terms of maximum difference between the cumul variables,
2836   /// between the pickup and delivery alternatives belonging to a single
2837   /// pickup/delivery pair in the RoutingModel. The indices passed to the
2838   /// function respectively correspond to the position of the pickup in the
2839   /// vector of pickup alternatives, and delivery position in the delivery
2840   /// alternatives for this pickup/delivery pair. These limits should only be
2841   /// set when each node index appears in at most one pickup/delivery pair, i.e.
2842   /// each pickup (delivery) index is in a single pickup/delivery pair.first
2843   /// (pair.second).
2844   typedef std::function<int64_t(int, int)> PickupToDeliveryLimitFunction;
2845 
2846   void SetPickupToDeliveryLimitFunctionForPair(
2847       PickupToDeliveryLimitFunction limit_function, int pair_index);
2848 
2849   bool HasPickupToDeliveryLimits() const;
2850 #ifndef SWIG
2851   int64_t GetPickupToDeliveryLimitForPair(int pair_index, int pickup,
2852                                           int delivery) const;
2853 
2854   struct NodePrecedence {
2855     int64_t first_node;
2856     int64_t second_node;
2857     int64_t offset;
2858   };
2859 
AddNodePrecedence(NodePrecedence precedence)2860   void AddNodePrecedence(NodePrecedence precedence) {
2861     node_precedences_.push_back(precedence);
2862   }
GetNodePrecedences()2863   const std::vector<NodePrecedence>& GetNodePrecedences() const {
2864     return node_precedences_;
2865   }
2866 #endif  // SWIG
2867 
AddNodePrecedence(int64_t first_node,int64_t second_node,int64_t offset)2868   void AddNodePrecedence(int64_t first_node, int64_t second_node,
2869                          int64_t offset) {
2870     AddNodePrecedence({first_node, second_node, offset});
2871   }
2872 
GetSpanUpperBoundForVehicle(int vehicle)2873   int64_t GetSpanUpperBoundForVehicle(int vehicle) const {
2874     return vehicle_span_upper_bounds_[vehicle];
2875   }
2876 #ifndef SWIG
vehicle_span_upper_bounds()2877   const std::vector<int64_t>& vehicle_span_upper_bounds() const {
2878     return vehicle_span_upper_bounds_;
2879   }
2880 #endif  // SWIG
GetSpanCostCoefficientForVehicle(int vehicle)2881   int64_t GetSpanCostCoefficientForVehicle(int vehicle) const {
2882     return vehicle_span_cost_coefficients_[vehicle];
2883   }
2884 #ifndef SWIG
GetSpanCostCoefficientForVehicleClass(RoutingVehicleClassIndex vehicle_class)2885   int64_t GetSpanCostCoefficientForVehicleClass(
2886       RoutingVehicleClassIndex vehicle_class) const {
2887     const int vehicle = model_->GetVehicleOfClass(vehicle_class);
2888     DCHECK_NE(vehicle, -1);
2889     return GetSpanCostCoefficientForVehicle(vehicle);
2890   }
2891 #endif  // SWIG
2892 #ifndef SWIG
vehicle_span_cost_coefficients()2893   const std::vector<int64_t>& vehicle_span_cost_coefficients() const {
2894     return vehicle_span_cost_coefficients_;
2895   }
2896 #endif  // SWIG
global_span_cost_coefficient()2897   int64_t global_span_cost_coefficient() const {
2898     return global_span_cost_coefficient_;
2899   }
2900 
GetGlobalOptimizerOffset()2901   int64_t GetGlobalOptimizerOffset() const {
2902     DCHECK_GE(global_optimizer_offset_, 0);
2903     return global_optimizer_offset_;
2904   }
GetLocalOptimizerOffsetForVehicle(int vehicle)2905   int64_t GetLocalOptimizerOffsetForVehicle(int vehicle) const {
2906     if (vehicle >= local_optimizer_offset_for_vehicle_.size()) {
2907       return 0;
2908     }
2909     DCHECK_GE(local_optimizer_offset_for_vehicle_[vehicle], 0);
2910     return local_optimizer_offset_for_vehicle_[vehicle];
2911   }
2912 #if !defined SWIG
2913   /// If the span of vehicle on this dimension is larger than bound,
2914   /// the cost will be increased by cost * (span - bound).
SetSoftSpanUpperBoundForVehicle(SimpleBoundCosts::BoundCost bound_cost,int vehicle)2915   void SetSoftSpanUpperBoundForVehicle(SimpleBoundCosts::BoundCost bound_cost,
2916                                        int vehicle) {
2917     if (!HasSoftSpanUpperBounds()) {
2918       vehicle_soft_span_upper_bound_ = absl::make_unique<SimpleBoundCosts>(
2919           model_->vehicles(), SimpleBoundCosts::BoundCost{kint64max, 0});
2920     }
2921     vehicle_soft_span_upper_bound_->bound_cost(vehicle) = bound_cost;
2922   }
HasSoftSpanUpperBounds()2923   bool HasSoftSpanUpperBounds() const {
2924     return vehicle_soft_span_upper_bound_ != nullptr;
2925   }
GetSoftSpanUpperBoundForVehicle(int vehicle)2926   SimpleBoundCosts::BoundCost GetSoftSpanUpperBoundForVehicle(
2927       int vehicle) const {
2928     DCHECK(HasSoftSpanUpperBounds());
2929     return vehicle_soft_span_upper_bound_->bound_cost(vehicle);
2930   }
2931   /// If the span of vehicle on this dimension is larger than bound,
2932   /// the cost will be increased by cost * (span - bound)^2.
SetQuadraticCostSoftSpanUpperBoundForVehicle(SimpleBoundCosts::BoundCost bound_cost,int vehicle)2933   void SetQuadraticCostSoftSpanUpperBoundForVehicle(
2934       SimpleBoundCosts::BoundCost bound_cost, int vehicle) {
2935     if (!HasQuadraticCostSoftSpanUpperBounds()) {
2936       vehicle_quadratic_cost_soft_span_upper_bound_ =
2937           absl::make_unique<SimpleBoundCosts>(
2938               model_->vehicles(), SimpleBoundCosts::BoundCost{kint64max, 0});
2939     }
2940     vehicle_quadratic_cost_soft_span_upper_bound_->bound_cost(vehicle) =
2941         bound_cost;
2942   }
HasQuadraticCostSoftSpanUpperBounds()2943   bool HasQuadraticCostSoftSpanUpperBounds() const {
2944     return vehicle_quadratic_cost_soft_span_upper_bound_ != nullptr;
2945   }
GetQuadraticCostSoftSpanUpperBoundForVehicle(int vehicle)2946   SimpleBoundCosts::BoundCost GetQuadraticCostSoftSpanUpperBoundForVehicle(
2947       int vehicle) const {
2948     DCHECK(HasQuadraticCostSoftSpanUpperBounds());
2949     return vehicle_quadratic_cost_soft_span_upper_bound_->bound_cost(vehicle);
2950   }
2951 #endif  /// !defined SWIG
2952 
2953  private:
2954   struct SoftBound {
2955     IntVar* var;
2956     int64_t bound;
2957     int64_t coefficient;
2958   };
2959 
2960   struct PiecewiseLinearCost {
PiecewiseLinearCostPiecewiseLinearCost2961     PiecewiseLinearCost() : var(nullptr), cost(nullptr) {}
2962     IntVar* var;
2963     std::unique_ptr<PiecewiseLinearFunction> cost;
2964   };
2965 
2966   class SelfBased {};
2967   RoutingDimension(RoutingModel* model, std::vector<int64_t> vehicle_capacities,
2968                    const std::string& name,
2969                    const RoutingDimension* base_dimension);
2970   RoutingDimension(RoutingModel* model, std::vector<int64_t> vehicle_capacities,
2971                    const std::string& name, SelfBased);
2972   void Initialize(const std::vector<int>& transit_evaluators,
2973                   const std::vector<int>& state_dependent_transit_evaluators,
2974                   int64_t slack_max);
2975   void InitializeCumuls();
2976   void InitializeTransits(
2977       const std::vector<int>& transit_evaluators,
2978       const std::vector<int>& state_dependent_transit_evaluators,
2979       int64_t slack_max);
2980   void InitializeTransitVariables(int64_t slack_max);
2981   /// Sets up the cost variables related to cumul soft upper bounds.
2982   void SetupCumulVarSoftUpperBoundCosts(
2983       std::vector<IntVar*>* cost_elements) const;
2984   /// Sets up the cost variables related to cumul soft lower bounds.
2985   void SetupCumulVarSoftLowerBoundCosts(
2986       std::vector<IntVar*>* cost_elements) const;
2987   void SetupCumulVarPiecewiseLinearCosts(
2988       std::vector<IntVar*>* cost_elements) const;
2989   /// Sets up the cost variables related to the global span and per-vehicle span
2990   /// costs (only for the "slack" part of the latter).
2991   void SetupGlobalSpanCost(std::vector<IntVar*>* cost_elements) const;
2992   void SetupSlackAndDependentTransitCosts() const;
2993   /// Finalize the model of the dimension.
2994   void CloseModel(bool use_light_propagation);
2995 
SetOffsetForGlobalOptimizer(int64_t offset)2996   void SetOffsetForGlobalOptimizer(int64_t offset) {
2997     global_optimizer_offset_ = std::max(Zero(), offset);
2998   }
2999   /// Moves elements of "offsets" into vehicle_offsets_for_local_optimizer_.
SetVehicleOffsetsForLocalOptimizer(std::vector<int64_t> offsets)3000   void SetVehicleOffsetsForLocalOptimizer(std::vector<int64_t> offsets) {
3001     /// Make sure all offsets are positive.
3002     std::transform(offsets.begin(), offsets.end(), offsets.begin(),
3003                    [](int64_t offset) { return std::max(Zero(), offset); });
3004     local_optimizer_offset_for_vehicle_ = std::move(offsets);
3005   }
3006 
3007   std::vector<IntVar*> cumuls_;
3008   std::vector<SortedDisjointIntervalList> forbidden_intervals_;
3009   std::vector<IntVar*> capacity_vars_;
3010   const std::vector<int64_t> vehicle_capacities_;
3011   std::vector<IntVar*> transits_;
3012   std::vector<IntVar*> fixed_transits_;
3013   /// Values in class_evaluators_ correspond to the evaluators in
3014   /// RoutingModel::transit_evaluators_ for each vehicle class.
3015   std::vector<int> class_evaluators_;
3016   std::vector<int64_t> vehicle_to_class_;
3017 #ifndef SWIG
3018   ReverseArcListGraph<int, int> path_precedence_graph_;
3019 #endif
3020   // For every {first_node, second_node, offset} element in node_precedences_,
3021   // if both first_node and second_node are performed, then
3022   // cumuls_[second_node] must be greater than (or equal to)
3023   // cumuls_[first_node] + offset.
3024   std::vector<NodePrecedence> node_precedences_;
3025 
3026   // The transits of a dimension may depend on its cumuls or the cumuls of
3027   // another dimension. There can be no cycles, except for self loops, a
3028   // typical example for this is a time dimension.
3029   const RoutingDimension* const base_dimension_;
3030 
3031   // Values in state_dependent_class_evaluators_ correspond to the evaluators
3032   // in RoutingModel::state_dependent_transit_evaluators_ for each vehicle
3033   // class.
3034   std::vector<int> state_dependent_class_evaluators_;
3035   std::vector<int64_t> state_dependent_vehicle_to_class_;
3036 
3037   // For each pickup/delivery pair_index for which limits have been set,
3038   // pickup_to_delivery_limits_per_pair_index_[pair_index] contains the
3039   // PickupToDeliveryLimitFunction for the pickup and deliveries in this pair.
3040   std::vector<PickupToDeliveryLimitFunction>
3041       pickup_to_delivery_limits_per_pair_index_;
3042 
3043   // Used if some vehicle has breaks in this dimension, typically time.
3044   bool break_constraints_are_initialized_ = false;
3045   // clang-format off
3046   std::vector<std::vector<IntervalVar*> > vehicle_break_intervals_;
3047   std::vector<std::vector<std::pair<int64_t, int64_t> > >
3048       vehicle_break_distance_duration_;
3049   // clang-format on
3050   // For each vehicle, stores the part of travel that is made directly
3051   // after (before) the departure (arrival) node of the travel.
3052   // These parts of the travel are non-interruptible, in particular by a break.
3053   std::vector<int> vehicle_pre_travel_evaluators_;
3054   std::vector<int> vehicle_post_travel_evaluators_;
3055 
3056   std::vector<IntVar*> slacks_;
3057   std::vector<IntVar*> dependent_transits_;
3058   std::vector<int64_t> vehicle_span_upper_bounds_;
3059   int64_t global_span_cost_coefficient_;
3060   std::vector<int64_t> vehicle_span_cost_coefficients_;
3061   std::vector<SoftBound> cumul_var_soft_upper_bound_;
3062   std::vector<SoftBound> cumul_var_soft_lower_bound_;
3063   std::vector<PiecewiseLinearCost> cumul_var_piecewise_linear_cost_;
3064   RoutingModel* const model_;
3065   const std::string name_;
3066   int64_t global_optimizer_offset_;
3067   std::vector<int64_t> local_optimizer_offset_for_vehicle_;
3068   /// nullptr if not defined.
3069   std::unique_ptr<SimpleBoundCosts> vehicle_soft_span_upper_bound_;
3070   std::unique_ptr<SimpleBoundCosts>
3071       vehicle_quadratic_cost_soft_span_upper_bound_;
3072   friend class RoutingModel;
3073   friend class RoutingModelInspector;
3074   friend void AppendDimensionCumulFilters(
3075       const std::vector<RoutingDimension*>& dimensions,
3076       const RoutingSearchParameters& parameters, bool filter_objective_cost,
3077       std::vector<LocalSearchFilterManager::FilterEvent>* filters);
3078 
3079   DISALLOW_COPY_AND_ASSIGN(RoutingDimension);
3080 };
3081 
3082 /// A decision builder which tries to assign values to variables as close as
3083 /// possible to target values first.
3084 DecisionBuilder* MakeSetValuesFromTargets(Solver* solver,
3085                                           std::vector<IntVar*> variables,
3086                                           std::vector<int64_t> targets);
3087 
3088 /// Attempts to solve the model using the cp-sat solver. As of 5/2019, will
3089 /// solve the TSP corresponding to the model if it has a single vehicle.
3090 /// Therefore the resulting solution might not actually be feasible. Will return
3091 /// false if a solution could not be found.
3092 bool SolveModelWithSat(const RoutingModel& model,
3093                        const RoutingSearchParameters& search_parameters,
3094                        const Assignment* initial_solution,
3095                        Assignment* solution);
3096 
3097 #if !defined(SWIG)
3098 IntVarLocalSearchFilter* MakeVehicleBreaksFilter(
3099     const RoutingModel& routing_model, const RoutingDimension& dimension);
3100 
3101 // A decision builder that monitors solutions, and tries to fix dimension
3102 // variables whose route did not change in the candidate solution.
3103 // Dimension variables are Cumul, Slack and break variables of all dimensions.
3104 // The user must make sure that those variables will be always be fixed at
3105 // solution, typically by composing another DecisionBuilder after this one.
3106 // If this DecisionBuilder returns a non-nullptr value at some node of the
3107 // search tree, it will always return nullptr in the subtree of that node.
3108 // Moreover, the decision will be a simultaneous assignment of the dimension
3109 // variables of unchanged routes on the left branch, and an empty decision on
3110 // the right branch.
3111 DecisionBuilder* MakeRestoreDimensionValuesForUnchangedRoutes(
3112     RoutingModel* model);
3113 #endif
3114 
3115 }  // namespace operations_research
3116 #endif  // OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_H_
3117