routing.h
Go to the documentation of this file.
1 // Copyright 2010-2018 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 routes,
56 // 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 methods
64 // (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 (select
84 // the first node with an unbound successor and connect it to the node
85 // which produces the cheapest route segment), PathCheapestArc (starting
86 // from a route "start" node, connect it to the node which produces the
87 // cheapest route segment, then extend the route by iterating on the last
88 // 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 with
99 // a default value of 13 nodes). It is not activated by default because it
100 // 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 MyDistance(int64 from, int64 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(int64, int64)>
132 // 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 node = routing.Start(route_number);
148 // !routing.IsEnd(node);
149 // node = solution->Value(routing.NextVar(node))) {
150 // LOG(INFO) << routing.IndexToNode(node);
151 // }
152 //
153 //
154 // Keywords: Vehicle Routing, Traveling Salesman Problem, TSP, VRP, CVRPTW, PDP.
155 
156 #ifndef OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_H_
157 #define OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_H_
158 
159 #include <cstddef>
160 #include <functional>
161 #include <memory>
162 #include <queue>
163 #include <string>
164 #include <utility>
165 #include <vector>
166 
167 #include "absl/container/flat_hash_map.h"
168 #include "absl/container/flat_hash_set.h"
169 #include "absl/hash/hash.h"
170 #include "absl/time/time.h"
171 #include "ortools/base/adjustable_priority_queue-inl.h"
172 #include "ortools/base/adjustable_priority_queue.h"
173 #include "ortools/base/commandlineflags.h"
174 #include "ortools/base/hash.h"
175 #include "ortools/base/int_type_indexed_vector.h"
176 #include "ortools/base/logging.h"
177 #include "ortools/base/macros.h"
183 #include "ortools/glop/lp_solver.h"
184 #include "ortools/glop/parameters.pb.h"
185 #include "ortools/graph/graph.h"
186 #include "ortools/lp_data/lp_data.h"
187 #include "ortools/lp_data/lp_types.h"
188 #include "ortools/sat/theta_tree.h"
189 #include "ortools/util/range_query_function.h"
190 #include "ortools/util/sorted_interval_list.h"
191 
192 namespace operations_research {
193 
194 class IntVarFilteredDecisionBuilder;
195 class LocalSearchOperator;
196 class RoutingDimension;
197 #ifndef SWIG
198 using util::ReverseArcListGraph;
199 class SweepArranger;
200 #endif
201 struct SweepIndex;
202 
203 class RoutingModel {
204  public:
205  // Status of the search.
206  enum Status {
207  // Problem not solved yet (before calling RoutingModel::Solve()).
208  ROUTING_NOT_SOLVED,
209  // Problem solved successfully after calling RoutingModel::Solve().
210  ROUTING_SUCCESS,
211  // No solution found to the problem after calling RoutingModel::Solve().
212  ROUTING_FAIL,
213  // Time limit reached before finding a solution with RoutingModel::Solve().
214  ROUTING_FAIL_TIMEOUT,
215  // Model, model parameters or flags are not valid.
216  ROUTING_INVALID
217  };
218 
219  // Types of precedence policy applied to pickup and delivery pairs.
220  enum PickupAndDeliveryPolicy {
221  // Any precedence is accepted.
222  PICKUP_AND_DELIVERY_NO_ORDER,
223  // Deliveries must be performed in reverse order of pickups.
224  PICKUP_AND_DELIVERY_LIFO,
225  // Deliveries must be performed in the same order as pickups.
226  PICKUP_AND_DELIVERY_FIFO
227  };
228  typedef RoutingCostClassIndex CostClassIndex;
229  typedef RoutingDimensionIndex DimensionIndex;
230  typedef RoutingDisjunctionIndex DisjunctionIndex;
231  typedef RoutingVehicleClassIndex VehicleClassIndex;
232  typedef RoutingTransitCallback1 TransitCallback1;
233  typedef RoutingTransitCallback2 TransitCallback2;
234 
235 // TODO(user): Remove all SWIG guards by adding the @ignore in .i.
236 #if !defined(SWIG)
237  typedef RoutingIndexPair IndexPair;
238  typedef RoutingIndexPairs IndexPairs;
239 #endif // SWIG
240 
241 #if !defined(SWIG)
242  // What follows is relevant for models with time/state dependent transits.
243  // Such transits, say from node A to node B, are functions f: int64->int64
244  // of the cumuls of a dimension. The user is free to implement the abstract
245  // RangeIntToIntFunction interface, but it is expected that the implementation
246  // of each method is quite fast. For performance-related reasons,
247  // StateDependentTransit keeps an additional pointer to a
248  // RangeMinMaxIndexFunction, with similar functionality to
249  // RangeIntToIntFunction, for g(x) = f(x)+x, where f is the transit from A to
250  // B. In most situations the best solutions are problem-specific, but in case
251  // of doubt the user may use the MakeStateDependentTransit function from the
252  // routing library, which works out-of-the-box, with very good running time,
253  // but memory inefficient in some situations.
254  struct StateDependentTransit {
255  RangeIntToIntFunction* transit; // f(x)
256  RangeMinMaxIndexFunction* transit_plus_identity; // g(x) = f(x) + x
257  };
258  typedef std::function<StateDependentTransit(int64, int64)>
259  VariableIndexEvaluator2;
260 #endif // SWIG
261 
262 #if !defined(SWIG)
263  struct CostClass {
264  // Index of the arc cost evaluator, registered in the RoutingModel class.
265  int evaluator_index = 0;
266 
267  // SUBTLE:
268  // The vehicle's fixed cost is skipped on purpose here, because we
269  // can afford to do so:
270  // - We don't really care about creating "strict" equivalence classes;
271  // all we care about is to:
272  // 1) compress the space of cost callbacks so that
273  // we can cache them more efficiently.
274  // 2) have a smaller IntVar domain thanks to using a "cost class var"
275  // instead of the vehicle var, so that we reduce the search space.
276  // Both of these are an incentive for *fewer* cost classes. Ignoring
277  // the fixed costs can only be good in that regard.
278  // - The fixed costs are only needed when evaluating the cost of the
279  // first arc of the route, in which case we know the vehicle, since we
280  // have the route's start node.
281 
282  // Only dimensions that have non-zero cost evaluator and a non-zero cost
283  // coefficient (in this cost class) are listed here. Since we only need
284  // their transit evaluator (the raw version that takes var index, not Node
285  // Index) and their span cost coefficient, we just store those.
286  // This is sorted by the natural operator < (and *not* by DimensionIndex).
287  struct DimensionCost {
288  int64 transit_evaluator_class;
289  int64 cost_coefficient;
290  const RoutingDimension* dimension;
291  bool operator<(const DimensionCost& cost) const {
292  if (transit_evaluator_class != cost.transit_evaluator_class) {
293  return transit_evaluator_class < cost.transit_evaluator_class;
294  }
295  return cost_coefficient < cost.cost_coefficient;
296  }
297  };
298  std::vector<DimensionCost>
299  dimension_transit_evaluator_class_and_cost_coefficient;
300 
301  explicit CostClass(int evaluator_index)
302  : evaluator_index(evaluator_index) {}
303 
304  // Comparator for STL containers and algorithms.
305  static bool LessThan(const CostClass& a, const CostClass& b) {
306  if (a.evaluator_index != b.evaluator_index) {
307  return a.evaluator_index < b.evaluator_index;
308  }
309  return a.dimension_transit_evaluator_class_and_cost_coefficient <
310  b.dimension_transit_evaluator_class_and_cost_coefficient;
311  }
312  };
313 
314  struct VehicleClass {
315  // The cost class of the vehicle.
316  CostClassIndex cost_class_index;
317  // Contrarily to CostClass, here we need strict equivalence.
318  int64 fixed_cost;
319  // Vehicle start and end equivalence classes. Currently if two vehicles have
320  // different start/end nodes which are "physically" located at the same
321  // place, these two vehicles will be considered as non-equivalent unless the
322  // two indices are in the same class.
323  // TODO(user): Find equivalent start/end nodes wrt dimensions and
324  // callbacks.
325  int start_equivalence_class;
326  int end_equivalence_class;
327  // Bounds of cumul variables at start and end vehicle nodes.
328  // dimension_{start,end}_cumuls_{min,max}[d] is the bound for dimension d.
329  gtl::ITIVector<DimensionIndex, int64> dimension_start_cumuls_min;
330  gtl::ITIVector<DimensionIndex, int64> dimension_start_cumuls_max;
331  gtl::ITIVector<DimensionIndex, int64> dimension_end_cumuls_min;
332  gtl::ITIVector<DimensionIndex, int64> dimension_end_cumuls_max;
333  gtl::ITIVector<DimensionIndex, int64> dimension_capacities;
334  // dimension_evaluators[d]->Run(from, to) is the transit value of arc
335  // from->to for a dimension d.
336  gtl::ITIVector<DimensionIndex, int64> dimension_evaluator_classes;
337  // Fingerprint of unvisitable non-start/end nodes.
338  uint64 unvisitable_nodes_fprint;
339 
340  // Comparator for STL containers and algorithms.
341  static bool LessThan(const VehicleClass& a, const VehicleClass& b);
342  };
343 #endif // defined(SWIG)
344 
345  // Constant used to express a hard constraint instead of a soft penalty.
346  static const int64 kNoPenalty;
347 
348  // Constant used to express the "no disjunction" index, returned when a node
349  // does not appear in any disjunction.
350  static const DisjunctionIndex kNoDisjunction;
351 
352  // Constant used to express the "no dimension" index, returned when a
353  // dimension name does not correspond to an actual dimension.
354  static const DimensionIndex kNoDimension;
355 
356  // Constructor taking an index manager. The version which does not take
357  // RoutingModelParameters is equivalent to passing
358  // DefaultRoutingModelParameters().
359  explicit RoutingModel(const RoutingIndexManager& index_manager);
360  RoutingModel(const RoutingIndexManager& index_manager,
361  const RoutingModelParameters& parameters);
362  ~RoutingModel();
363 
364  // Registers 'callback' and returns its index.
365  int RegisterUnaryTransitCallback(TransitCallback1 callback);
366  int RegisterTransitCallback(TransitCallback2 callback);
367  int RegisterPositiveTransitCallback(TransitCallback2 callback);
368  int RegisterStateDependentTransitCallback(VariableIndexEvaluator2 callback);
369  const TransitCallback2& TransitCallback(int callback_index) const {
370  CHECK_LT(callback_index, transit_evaluators_.size());
371  return transit_evaluators_[callback_index];
372  }
373  const TransitCallback1& UnaryTransitCallbackOrNull(int callback_index) const {
374  CHECK_LT(callback_index, unary_transit_evaluators_.size());
375  return unary_transit_evaluators_[callback_index];
376  }
377  const VariableIndexEvaluator2& StateDependentTransitCallback(
378  int callback_index) const {
379  CHECK_LT(callback_index, state_dependent_transit_evaluators_.size());
380  return state_dependent_transit_evaluators_[callback_index];
381  }
382 
383  // Model creation
384 
385  // Methods to add dimensions to routes; dimensions represent quantities
386  // accumulated at nodes along the routes. They represent quantities such as
387  // weights or volumes carried along the route, or distance or times.
388  // Quantities at a node are represented by "cumul" variables and the increase
389  // or decrease of quantities between nodes are represented by "transit"
390  // variables. These variables are linked as follows:
391  // if j == next(i), cumul(j) = cumul(i) + transit(i) + slack(i)
392  // where slack is a positive slack variable (can represent waiting times for
393  // a time dimension).
394  // Setting the value of fix_start_cumul_to_zero to true will force the "cumul"
395  // variable of the start node of all vehicles to be equal to 0.
396 
397  // Creates a dimension where the transit variable is constrained to be
398  // equal to evaluator(i, next(i)); 'slack_max' is the upper bound of the
399  // slack variable and 'capacity' is the upper bound of the cumul variables.
400  // 'name' is the name used to reference the dimension; this name is used to
401  // get cumul and transit variables from the routing model.
402  // Returns false if a dimension with the same name has already been created
403  // (and doesn't create the new dimension).
404  // Takes ownership of the callback 'evaluator'.
405  bool AddDimension(int evaluator_index, int64 slack_max, int64 capacity,
406  bool fix_start_cumul_to_zero, const std::string& name);
407  bool AddDimensionWithVehicleTransits(
408  const std::vector<int>& evaluator_indices, int64 slack_max,
409  int64 capacity, bool fix_start_cumul_to_zero, const std::string& name);
410  bool AddDimensionWithVehicleCapacity(int evaluator_index, int64 slack_max,
411  std::vector<int64> vehicle_capacities,
412  bool fix_start_cumul_to_zero,
413  const std::string& name);
414  bool AddDimensionWithVehicleTransitAndCapacity(
415  const std::vector<int>& evaluator_indices, int64 slack_max,
416  std::vector<int64> vehicle_capacities, bool fix_start_cumul_to_zero,
417  const std::string& name);
418  // Creates a dimension where the transit variable is constrained to be
419  // equal to 'value'; 'capacity' is the upper bound of the cumul variables.
420  // 'name' is the name used to reference the dimension; this name is used to
421  // get cumul and transit variables from the routing model.
422  // Returns false if a dimension with the same name has already been created
423  // (and doesn't create the new dimension).
424  bool AddConstantDimensionWithSlack(int64 value, int64 capacity,
425  int64 slack_max,
426  bool fix_start_cumul_to_zero,
427  const std::string& name);
428  bool AddConstantDimension(int64 value, int64 capacity,
429  bool fix_start_cumul_to_zero,
430  const std::string& name) {
431  return AddConstantDimensionWithSlack(value, capacity, 0,
432  fix_start_cumul_to_zero, name);
433  }
434  // Creates a dimension where the transit variable is constrained to be
435  // equal to 'values[i]' for node i; 'capacity' is the upper bound of
436  // the cumul variables. 'name' is the name used to reference the dimension;
437  // this name is used to get cumul and transit variables from the routing
438  // model.
439  // Returns false if a dimension with the same name has already been created
440  // (and doesn't create the new dimension).
441  bool AddVectorDimension(std::vector<int64> values, int64 capacity,
442  bool fix_start_cumul_to_zero,
443  const std::string& name);
444  // Creates a dimension where the transit variable is constrained to be
445  // equal to 'values[i][next(i)]' for node i; 'capacity' is the upper bound of
446  // the cumul variables. 'name' is the name used to reference the dimension;
447  // this name is used to get cumul and transit variables from the routing
448  // model.
449  // Returns false if a dimension with the same name has already been created
450  // (and doesn't create the new dimension).
451  bool AddMatrixDimension(std::vector<std::vector<int64>> values,
452  int64 capacity, bool fix_start_cumul_to_zero,
453  const std::string& name);
454  // Creates a dimension with transits depending on the cumuls of another
455  // dimension. 'pure_transits' are the per-vehicle fixed transits as above.
456  // 'dependent_transits' is a vector containing for each vehicle an index to a
457  // registered state dependent transit callback. 'base_dimension' indicates the
458  // dimension from which the cumul variable is taken. If 'base_dimension' is
459  // nullptr, then the newly created dimension is self-based.
460  bool AddDimensionDependentDimensionWithVehicleCapacity(
461  const std::vector<int>& pure_transits,
462  const std::vector<int>& dependent_transits,
463  const RoutingDimension* base_dimension, int64 slack_max,
464  std::vector<int64> vehicle_capacities, bool fix_start_cumul_to_zero,
465  const std::string& name) {
466  return AddDimensionDependentDimensionWithVehicleCapacityInternal(
467  pure_transits, dependent_transits, base_dimension, slack_max,
468  std::move(vehicle_capacities), fix_start_cumul_to_zero, name);
469  }
470  // As above, but pure_transits are taken to be zero evaluators.
471  bool AddDimensionDependentDimensionWithVehicleCapacity(
472  const std::vector<int>& transits, const RoutingDimension* base_dimension,
473  int64 slack_max, std::vector<int64> vehicle_capacities,
474  bool fix_start_cumul_to_zero, const std::string& name);
475  // Homogeneous versions of the functions above.
476  bool AddDimensionDependentDimensionWithVehicleCapacity(
477  int transit, const RoutingDimension* base_dimension, int64 slack_max,
478  int64 vehicle_capacity, bool fix_start_cumul_to_zero,
479  const std::string& name);
480  bool AddDimensionDependentDimensionWithVehicleCapacity(
481  int pure_transit, int dependent_transit,
482  const RoutingDimension* base_dimension, int64 slack_max,
483  int64 vehicle_capacity, bool fix_start_cumul_to_zero,
484  const std::string& name);
485 
486  // Creates a cached StateDependentTransit from an std::function.
487  static RoutingModel::StateDependentTransit MakeStateDependentTransit(
488  const std::function<int64(int64)>& f, int64 domain_start,
489  int64 domain_end);
490 
491  // For every vehicle of the routing model:
492  // - if total_slacks[vehicle] is not nullptr, constrains it to be the sum of
493  // slacks on that vehicle, that is,
494  // dimension->CumulVar(end) - dimension->CumulVar(start) -
495  // sum_{node in path of vehicle} dimension->FixedTransitVar(node).
496  // - if spans[vehicle] is not nullptr, constrains it to be
497  // dimension->CumulVar(end) - dimension->CumulVar(start)
498  // This does stronger propagation than a decomposition, and takes breaks into
499  // account.
500  Constraint* MakePathSpansAndTotalSlacks(const RoutingDimension* dimension,
501  std::vector<IntVar*> spans,
502  std::vector<IntVar*> total_slacks);
503 
504  // Outputs the names of all dimensions added to the routing engine.
505  // TODO(user): rename.
506  std::vector<::std::string> GetAllDimensionNames() const;
507  // Returns all dimensions of the model.
508  const std::vector<RoutingDimension*>& GetDimensions() const {
509  return dimensions_.get();
510  }
511  // Returns dimensions with soft or vehicle span costs.
512  std::vector<RoutingDimension*> GetDimensionsWithSoftOrSpanCosts() const;
513  // Returns dimensions_for_[global|local]_optimizer_ if the model has been
514  // closed, and empty vectors otherwise.
515  const std::vector<RoutingDimension*>& GetDimensionsForGlobalCumulOptimizers()
516  const {
517  return dimensions_for_global_optimizer_;
518  }
519  const std::vector<RoutingDimension*>& GetDimensionsForLocalCumulOptimizers()
520  const {
521  return dimensions_for_local_optimizer_;
522  }
523  // Returns true if a dimension exists for a given dimension name.
524  bool HasDimension(const std::string& dimension_name) const;
525  // Returns a dimension from its name. Dies if the dimension does not exist.
526  const RoutingDimension& GetDimensionOrDie(
527  const std::string& dimension_name) const;
528  // Returns a dimension from its name. Returns nullptr if the dimension does
529  // not exist.
530  RoutingDimension* GetMutableDimension(
531  const std::string& dimension_name) const;
532  // Set the given dimension as "primary constrained". As of August 2013, this
533  // is only used by ArcIsMoreConstrainedThanArc().
534  // "dimension" must be the name of an existing dimension, or be empty, in
535  // which case there will not be a primary dimension after this call.
536  void SetPrimaryConstrainedDimension(const std::string& dimension_name) {
537  DCHECK(dimension_name.empty() || HasDimension(dimension_name));
538  primary_constrained_dimension_ = dimension_name;
539  }
540  // Get the primary constrained dimension, or an empty std::string if it is
541  // unset.
542  const std::string& GetPrimaryConstrainedDimension() const {
543  return primary_constrained_dimension_;
544  }
545  // Adds a disjunction constraint on the indices: exactly 'max_cardinality' of
546  // the indices are active. Start and end indices of any vehicle cannot be part
547  // of a disjunction.
548  // If a penalty is given, at most 'max_cardinality' of the indices can be
549  // active, and if less are active, 'penalty' is payed per inactive index.
550  // This is equivalent to adding the constraint:
551  // p + Sum(i)active[i] == max_cardinality
552  // where p is an integer variable, and the following cost to the cost
553  // function:
554  // p * penalty.
555  // 'penalty' must be positive to make the disjunction optional; a negative
556  // penalty will force 'max_cardinality' indices of the disjunction to be
557  // performed, and therefore p == 0.
558  // Note: passing a vector with a single index will model an optional index
559  // with a penalty cost if it is not visited.
560  DisjunctionIndex AddDisjunction(const std::vector<int64>& indices,
561  int64 penalty = kNoPenalty,
562  int64 max_cardinality = 1);
563  // Returns the indices of the disjunctions to which an index belongs.
564  const std::vector<DisjunctionIndex>& GetDisjunctionIndices(
565  int64 index) const {
566  return index_to_disjunctions_[index];
567  }
568  // Calls f for each variable index of indices in the same disjunctions as the
569  // node corresponding to the variable index 'index'; only disjunctions of
570  // cardinality 'cardinality' are considered.
571  template <typename F>
572  void ForEachNodeInDisjunctionWithMaxCardinalityFromIndex(
573  int64 index, int64 max_cardinality, F f) const {
574  for (const DisjunctionIndex disjunction : GetDisjunctionIndices(index)) {
575  if (disjunctions_[disjunction].value.max_cardinality == max_cardinality) {
576  for (const int64 d_index : disjunctions_[disjunction].indices) {
577  f(d_index);
578  }
579  }
580  }
581  }
582 #if !defined(SWIGPYTHON)
583  // Returns the variable indices of the nodes in the disjunction of index
584  // 'index'.
585  const std::vector<int64>& GetDisjunctionIndices(
586  DisjunctionIndex index) const {
587  return disjunctions_[index].indices;
588  }
589 #endif // !defined(SWIGPYTHON)
590  // Returns the penalty of the node disjunction of index 'index'.
591  int64 GetDisjunctionPenalty(DisjunctionIndex index) const {
592  return disjunctions_[index].value.penalty;
593  }
594  // Returns the maximum number of possible active nodes of the node disjunction
595  // of index 'index'.
596  int64 GetDisjunctionMaxCardinality(DisjunctionIndex index) const {
597  return disjunctions_[index].value.max_cardinality;
598  }
599  // Returns the number of node disjunctions in the model.
600  int GetNumberOfDisjunctions() const { return disjunctions_.size(); }
601  // Returns the list of all perfect binary disjunctions, as pairs of variable
602  // indices: a disjunction is "perfect" when its variables do not appear in
603  // any other disjunction. Each pair is sorted (lowest variable index first),
604  // and the output vector is also sorted (lowest pairs first).
605  std::vector<std::pair<int64, int64>> GetPerfectBinaryDisjunctions() const;
606  // SPECIAL: Makes the solver ignore all the disjunctions whose active
607  // variables are all trivially zero (i.e. Max() == 0), by setting their
608  // max_cardinality to 0.
609  // This can be useful when using the BaseBinaryDisjunctionNeighborhood
610  // operators, in the context of arc-based routing.
611  void IgnoreDisjunctionsAlreadyForcedToZero();
612 
613  // Adds a soft contraint to force a set of variable indices to be on the same
614  // vehicle. If all nodes are not on the same vehicle, each extra vehicle used
615  // adds 'cost' to the cost function.
616  void AddSoftSameVehicleConstraint(const std::vector<int64>& indices,
617  int64 cost);
618 
619  // Sets the vehicles which can visit a given node. If the node is in a
620  // disjunction, this will not prevent it from being unperformed.
621  // Specifying an empty vector of vehicles has no effect (all vehicles
622  // will be allowed to visit the node).
623  void SetAllowedVehiclesForIndex(const std::vector<int>& vehicles,
624  int64 index);
625 
626  // Returns true if a vehicle is allowed to visit a given node.
627  bool IsVehicleAllowedForIndex(int vehicle, int64 index) {
628  return allowed_vehicles_[index].empty() ||
629  allowed_vehicles_[index].find(vehicle) !=
630  allowed_vehicles_[index].end();
631  }
632 
633  // Notifies that index1 and index2 form a pair of nodes which should belong
634  // to the same route. This methods helps the search find better solutions,
635  // especially in the local search phase.
636  // It should be called each time you have an equality constraint linking
637  // the vehicle variables of two node (including for instance pickup and
638  // delivery problems):
639  // Solver* const solver = routing.solver();
640  // int64 index1 = manager.NodeToIndex(node1);
641  // int64 index2 = manager.NodeToIndex(node2);
642  // solver->AddConstraint(solver->MakeEquality(
643  // routing.VehicleVar(index1),
644  // routing.VehicleVar(index2)));
645  // routing.AddPickupAndDelivery(index1, index2);
646  //
647  // TODO(user): Remove this when model introspection detects linked nodes.
648  void AddPickupAndDelivery(int64 pickup, int64 delivery);
649  // Same as AddPickupAndDelivery but notifying that the performed node from
650  // the disjunction of index 'pickup_disjunction' is on the same route as the
651  // performed node from the disjunction of index 'delivery_disjunction'.
652  void AddPickupAndDeliverySets(DisjunctionIndex pickup_disjunction,
653  DisjunctionIndex delivery_disjunction);
654  // clang-format off
655  // Returns pairs for which the node is a pickup; the first element of each
656  // pair is the index in the pickup and delivery pairs list in which the pickup
657  // appears, the second element is its index in the pickups list.
658  const std::vector<std::pair<int, int> >&
659  GetPickupIndexPairs(int64 node_index) const;
660  // Same as above for deliveries.
661  const std::vector<std::pair<int, int> >&
662  GetDeliveryIndexPairs(int64 node_index) const;
663  // clang-format on
664 
665  // Sets the Pickup and delivery policy of all vehicles. It is equivalent to
666  // calling SetPickupAndDeliveryPolicyOfVehicle on all vehicles.
667  void SetPickupAndDeliveryPolicyOfAllVehicles(PickupAndDeliveryPolicy policy);
668  void SetPickupAndDeliveryPolicyOfVehicle(PickupAndDeliveryPolicy policy,
669  int vehicle);
670  PickupAndDeliveryPolicy GetPickupAndDeliveryPolicyOfVehicle(
671  int vehicle) const;
672  // Returns the number of non-start/end nodes which do not appear in a
673  // pickup/delivery pair.
674 
675  int GetNumOfSingletonNodes() const;
676 
677 #ifndef SWIG
678  // Returns pickup and delivery pairs currently in the model.
679  const IndexPairs& GetPickupAndDeliveryPairs() const {
680  return pickup_delivery_pairs_;
681  }
682  const std::vector<std::pair<DisjunctionIndex, DisjunctionIndex>>&
683  GetPickupAndDeliveryDisjunctions() const {
684  return pickup_delivery_disjunctions_;
685  }
686 #endif // SWIG
687  // Set the node visit types and incompatibilities/requirements between the
688  // types (see below).
689  // NOTE: The visit type of a node must be positive, and all nodes belonging to
690  // the same pickup/delivery pair must have the same type (or no type at all).
691  // NOTE: Before adding any incompatibilities and/or requirements on types:
692  // 1) All corresponding node types must have been set.
693  // 2) CloseVisitTypes() must be called so all containers are resized
694  // accordingly.
695  // NOTE: These incompatibilities and requirements are only handled when each
696  // node index appears in at most one pickup/delivery pair, i.e. when the same
697  // node isn't a pickup and/or delivery in multiple pickup/delivery pairs.
698  // TODO(user): Support multiple visit types per node?
699  void SetVisitType(int64 index, int type);
700  int GetVisitType(int64 index) const;
701  // This function should be called once all node visit types have been set and
702  // prior to adding any incompatibilities/requirements.
703  // TODO(user): Reconsider the logic and potentially remove the need to
704  // "close" types.
705  void CloseVisitTypes();
706  int GetNumberOfVisitTypes() const { return num_visit_types_; }
707  // Incompatibilities:
708  // Two nodes with "hard" incompatible types cannot share the same route at
709  // all, while with a "temporal" incompatibility they can't be on the same
710  // route at the same time.
711  void AddHardTypeIncompatibility(int type1, int type2);
712  void AddTemporalTypeIncompatibility(int type1, int type2);
713  // Returns visit types incompatible with a given type.
714  const absl::flat_hash_set<int>& GetHardTypeIncompatibilitiesOfType(
715  int type) const;
716  const absl::flat_hash_set<int>& GetTemporalTypeIncompatibilitiesOfType(
717  int type) const;
718  // Returns true iff any hard (resp. temporal) type incompatibilities have been
719  // added to the model.
721  return has_hard_type_incompatibilities_;
722  }
724  return has_temporal_type_incompatibilities_;
725  }
726  // Requirements:
727  // NOTE: As of 2019-04, cycles in the requirement graph are not supported,
728  // and lead to the dependent nodes being skipped if possible (otherwise
729  // the model is considered infeasible).
730  // The following functions specify that "dependent_type" requires at least
731  // one of the types in "required_type_alternatives".
732  //
733  // For same-vehicle requirements, a node of dependent type type_D requires at
734  // least one node of type type_R among the required alternatives on the same
735  // route.
737  int dependent_type, absl::flat_hash_set<int> required_type_alternatives);
738  // If type_D temporally depends on type_R, any non-delivery node_D of type_D
739  // requires at least one non-delivered node of type_R on its vehicle at the
740  // time node_D is visited.
742  int dependent_type, absl::flat_hash_set<int> required_type_alternatives);
743  // clang-format off
744  // Returns the sets of same-vehicle/temporal requirement alternatives for the
745  // given type.
746  const std::vector<absl::flat_hash_set<int> >&
748  const std::vector<absl::flat_hash_set<int> >&
750  // clang-format on
751  // Returns true iff any same-route (resp. temporal) type requirements have
752  // been added to the model.
754  return has_same_vehicle_type_requirements_;
755  }
757  return has_temporal_type_requirements_;
758  }
759 
760  // Returns true iff the model has any incompatibilities or requirements set
761  // on node types.
762  bool HasTypeRegulations() const {
766  }
767 
768  // Get the "unperformed" penalty of a node. This is only well defined if the
769  // node is only part of a single Disjunction involving only itself, and that
770  // disjunction has a penalty. In all other cases, including forced active
771  // nodes, this returns 0.
772  int64 UnperformedPenalty(int64 var_index) const;
773  // Same as above except that it returns default_value instead of 0 when
774  // penalty is not well defined (default value is passed as first argument to
775  // simplify the usage of the method in a callback).
776  int64 UnperformedPenaltyOrValue(int64 default_value, int64 var_index) const;
777  // Returns the variable index of the first starting or ending node of all
778  // routes. If all routes start and end at the same node (single depot), this
779  // is the node returned.
780  int64 GetDepot() const;
781 
782  // Sets the cost function of the model such that the cost of a segment of a
783  // route between node 'from' and 'to' is evaluator(from, to), whatever the
784  // route or vehicle performing the route.
785  void SetArcCostEvaluatorOfAllVehicles(int evaluator_index);
786  // Sets the cost function for a given vehicle route.
787  void SetArcCostEvaluatorOfVehicle(int evaluator_index, int vehicle);
788  // Sets the fixed cost of all vehicle routes. It is equivalent to calling
789  // SetFixedCostOfVehicle on all vehicle routes.
790  void SetFixedCostOfAllVehicles(int64 cost);
791  // Sets the fixed cost of one vehicle route.
792  void SetFixedCostOfVehicle(int64 cost, int vehicle);
793  // Returns the route fixed cost taken into account if the route of the
794  // vehicle is not empty, aka there's at least one node on the route other than
795  // the first and last nodes.
796  int64 GetFixedCostOfVehicle(int vehicle) const;
797 
798  // The following methods set the linear and quadratic cost factors of vehicles
799  // (must be positive values). The default value of these parameters is zero
800  // for all vehicles.
801  // When set, the cost_ of the model will contain terms aiming at reducing the
802  // number of vehicles used in the model, by adding the following to the
803  // objective for every vehicle v:
804  // INDICATOR(v used in the model) *
805  // [linear_cost_factor_of_vehicle_[v]
806  // - quadratic_cost_factor_of_vehicle_[v]*(square of length of route v)]
807  // i.e. for every used vehicle, we add the linear factor as fixed cost, and
808  // subtract the square of the route length multiplied by the quadratic factor.
809  // This second term aims at making the routes as dense as possible.
810  //
811  // Sets the linear and quadratic cost factor of all vehicles.
812  void SetAmortizedCostFactorsOfAllVehicles(int64 linear_cost_factor,
813  int64 quadratic_cost_factor);
814  // Sets the linear and quadratic cost factor of the given vehicle.
815  void SetAmortizedCostFactorsOfVehicle(int64 linear_cost_factor,
816  int64 quadratic_cost_factor,
817  int vehicle);
818 
819  const std::vector<int64>& GetAmortizedLinearCostFactorOfVehicles() const {
820  return linear_cost_factor_of_vehicle_;
821  }
822  const std::vector<int64>& GetAmortizedQuadraticCostFactorOfVehicles() const {
823  return quadratic_cost_factor_of_vehicle_;
824  }
825 
826  void ConsiderEmptyRouteCostsForVehicle(bool consider_costs, int vehicle) {
827  DCHECK_LT(vehicle, vehicles_);
828  consider_empty_route_costs_[vehicle] = consider_costs;
829  }
830 
831  bool AreEmptyRouteCostsConsideredForVehicle(int vehicle) const {
832  DCHECK_LT(vehicle, vehicles_);
833  return consider_empty_route_costs_[vehicle];
834  }
835 
836 // Search
837 // Gets/sets the evaluator used during the search. Only relevant when
838 // RoutingSearchParameters.first_solution_strategy = EVALUATOR_STRATEGY.
839 #ifndef SWIG
841  return first_solution_evaluator_;
842  }
843 #endif
844  // Takes ownership of evaluator.
846  first_solution_evaluator_ = std::move(evaluator);
847  }
848  // Adds a local search operator to the set of operators used to solve the
849  // vehicle routing problem.
850  void AddLocalSearchOperator(LocalSearchOperator* ls_operator);
851  // Adds a search monitor to the search used to solve the routing model.
852  void AddSearchMonitor(SearchMonitor* const monitor);
853  // Adds a callback called each time a solution is found during the search.
854  // This is a shortcut to creating a monitor to call the callback on
855  // AtSolution() and adding it with AddSearchMonitor.
856  void AddAtSolutionCallback(std::function<void()> callback);
857  // Adds a variable to minimize in the solution finalizer. The solution
858  // finalizer is called each time a solution is found during the search and
859  // allows to instantiate secondary variables (such as dimension cumul
860  // variables).
861  void AddVariableMinimizedByFinalizer(IntVar* var);
862  // Adds a variable to maximize in the solution finalizer (see above for
863  // information on the solution finalizer).
864  void AddVariableMaximizedByFinalizer(IntVar* var);
865  // Closes the current routing model; after this method is called, no
866  // modification to the model can be done, but RoutesToAssignment becomes
867  // available. Note that CloseModel() is automatically called by Solve() and
868  // other methods that produce solution.
869  // This is equivalent to calling
870  // CloseModelWithParameters(DefaultRoutingSearchParameters()).
871  void CloseModel();
872  // Same as above taking search parameters (as of 10/2015 some the parameters
873  // have to be set when closing the model).
875  const RoutingSearchParameters& search_parameters);
876  // Solves the current routing model; closes the current model.
877  // This is equivalent to calling
878  // SolveWithParameters(DefaultRoutingSearchParameters())
879  // or
880  // SolveFromAssignmentWithParameters(assignment,
881  // DefaultRoutingSearchParameters()).
882  const Assignment* Solve(const Assignment* assignment = nullptr);
883  // Solves the current routing model with the given parameters. If 'solutions'
884  // is specified, it will contain the k best solutions found during the search
885  // (from worst to best, including the one returned by this method), where k
886  // corresponds to the 'number_of_solutions_to_collect' in 'search_parameters'.
887  // Note that the Assignment returned by the method and the ones in solutions
888  // are owned by the underlying solver and should not be deleted.
889  const Assignment* SolveWithParameters(
890  const RoutingSearchParameters& search_parameters,
891  std::vector<const Assignment*>* solutions = nullptr);
892  const Assignment* SolveFromAssignmentWithParameters(
893  const Assignment* assignment,
894  const RoutingSearchParameters& search_parameters,
895  std::vector<const Assignment*>* solutions = nullptr);
896  // Given a "source_model" and its "source_assignment", resets
897  // "target_assignment" with the IntVar variables (nexts_, and vehicle_vars_
898  // if costs aren't homogeneous across vehicles) of "this" model, with the
899  // values set according to those in "other_assignment".
900  // The objective_element of target_assignment is set to this->cost_.
902  Assignment* target_assignment, const RoutingModel* source_model,
903  const Assignment* source_assignment);
904  // Computes a lower bound to the routing problem solving a linear assignment
905  // problem. The routing model must be closed before calling this method.
906  // Note that problems with node disjunction constraints (including optional
907  // nodes) and non-homogenous costs are not supported (the method returns 0 in
908  // these cases).
909  // TODO(user): Add support for non-homogeneous costs and disjunctions.
910  int64 ComputeLowerBound();
911  // Returns the current status of the routing model.
912  Status status() const { return status_; }
913  // Applies a lock chain to the next search. 'locks' represents an ordered
914  // vector of nodes representing a partial route which will be fixed during the
915  // next search; it will constrain next variables such that:
916  // next[locks[i]] == locks[i+1].
917  // Returns the next variable at the end of the locked chain; this variable is
918  // not locked. An assignment containing the locks can be obtained by calling
919  // PreAssignment().
920  IntVar* ApplyLocks(const std::vector<int64>& locks);
921  // Applies lock chains to all vehicles to the next search, such that locks[p]
922  // is the lock chain for route p. Returns false if the locks do not contain
923  // valid routes; expects that the routes do not contain the depots,
924  // i.e. there are empty vectors in place of empty routes.
925  // If close_routes is set to true, adds the end nodes to the route of each
926  // vehicle and deactivates other nodes.
927  // An assignment containing the locks can be obtained by calling
928  // PreAssignment().
929  bool ApplyLocksToAllVehicles(const std::vector<std::vector<int64>>& locks,
930  bool close_routes);
931  // Returns an assignment used to fix some of the variables of the problem.
932  // In practice, this assignment locks partial routes of the problem. This
933  // can be used in the context of locking the parts of the routes which have
934  // already been driven in online routing problems.
935  const Assignment* const PreAssignment() const { return preassignment_; }
936  Assignment* MutablePreAssignment() { return preassignment_; }
937  // Writes the current solution to a file containing an AssignmentProto.
938  // Returns false if the file cannot be opened or if there is no current
939  // solution.
940  bool WriteAssignment(const std::string& file_name) const;
941  // Reads an assignment from a file and returns the current solution.
942  // Returns nullptr if the file cannot be opened or if the assignment is not
943  // valid.
944  Assignment* ReadAssignment(const std::string& file_name);
945  // Restores an assignment as a solution in the routing model and returns the
946  // new solution. Returns nullptr if the assignment is not valid.
947  Assignment* RestoreAssignment(const Assignment& solution);
948  // Restores the routes as the current solution. Returns nullptr if the
949  // solution cannot be restored (routes do not contain a valid solution). Note
950  // that calling this method will run the solver to assign values to the
951  // dimension variables; this may take considerable amount of time, especially
952  // when using dimensions with slack.
953  Assignment* ReadAssignmentFromRoutes(
954  const std::vector<std::vector<int64>>& routes,
955  bool ignore_inactive_indices);
956  // Fills an assignment from a specification of the routes of the
957  // vehicles. The routes are specified as lists of variable indices that appear
958  // on the routes of the vehicles. The indices of the outer vector in
959  // 'routes' correspond to vehicles IDs, the inner vector contains the
960  // variable indices on the routes for the given vehicle. The inner vectors
961  // must not contain the start and end indices, as these are determined by the
962  // routing model. Sets the value of NextVars in the assignment, adding the
963  // variables to the assignment if necessary. The method does not touch other
964  // variables in the assignment. The method can only be called after the model
965  // is closed. With ignore_inactive_indices set to false, this method will
966  // fail (return nullptr) in case some of the route contain indices that are
967  // deactivated in the model; when set to true, these indices will be
968  // skipped. Returns true if routes were successfully
969  // loaded. However, such assignment still might not be a valid
970  // solution to the routing problem due to more complex constraints;
971  // it is advisible to call solver()->CheckSolution() afterwards.
972  bool RoutesToAssignment(const std::vector<std::vector<int64>>& routes,
973  bool ignore_inactive_indices, bool close_routes,
974  Assignment* const assignment) const;
975  // Converts the solution in the given assignment to routes for all vehicles.
976  // Expects that assignment contains a valid solution (i.e. routes for all
977  // vehicles end with an end index for that vehicle).
978  void AssignmentToRoutes(const Assignment& assignment,
979  std::vector<std::vector<int64>>* const routes) const;
980  // Returns a compacted version of the given assignment, in which all vehicles
981  // with id lower or equal to some N have non-empty routes, and all vehicles
982  // with id greater than N have empty routes. Does not take ownership of the
983  // returned object.
984  // If found, the cost of the compact assignment is the same as in the
985  // original assignment and it preserves the values of 'active' variables.
986  // Returns nullptr if a compact assignment was not found.
987  // This method only works in homogenous mode, and it only swaps equivalent
988  // vehicles (vehicles with the same start and end nodes). When creating the
989  // compact assignment, the empty plan is replaced by the route assigned to the
990  // compatible vehicle with the highest id. Note that with more complex
991  // constraints on vehicle variables, this method might fail even if a compact
992  // solution exists.
993  // This method changes the vehicle and dimension variables as necessary.
994  // While compacting the solution, only basic checks on vehicle variables are
995  // performed; if one of these checks fails no attempts to repair it are made
996  // (instead, the method returns nullptr).
997  Assignment* CompactAssignment(const Assignment& assignment) const;
998  // Same as CompactAssignment() but also checks the validity of the final
999  // compact solution; if it is not valid, no attempts to repair it are made
1000  // (instead, the method returns nullptr).
1001  Assignment* CompactAndCheckAssignment(const Assignment& assignment) const;
1002  // Adds an extra variable to the vehicle routing assignment.
1003  void AddToAssignment(IntVar* const var);
1004  void AddIntervalToAssignment(IntervalVar* const interval);
1005  // For every dimension in the model's dimensions_for_local/global_optimizer_,
1006  // this method tries to pack the cumul values of the dimension, such that:
1007  // - The cumul costs (span costs, soft lower and upper bound costs, etc) are
1008  // minimized.
1009  // - The cumuls of the ends of the routes are minimized for this given minimal
1010  // cumul cost.
1011  // - Given these minimal end cumuls, the route start cumuls are maximized.
1012  // Returns the assignment resulting from allocating these packed cumuls with
1013  // the solver, and nullptr if these cumuls could not be set by the solver.
1015  const Assignment* original_assignment, absl::Duration duration_limit);
1016 #ifndef SWIG
1017  // TODO(user): Revisit if coordinates are added to the RoutingModel class.
1018  void SetSweepArranger(SweepArranger* sweep_arranger) {
1019  sweep_arranger_.reset(sweep_arranger);
1020  }
1021  // Returns the sweep arranger to be used by routing heuristics.
1022  SweepArranger* sweep_arranger() const { return sweep_arranger_.get(); }
1023 #endif
1024  // Adds a custom local search filter to the list of filters used to speed up
1025  // local search by pruning unfeasible variable assignments.
1026  // Calling this method after the routing model has been closed (CloseModel()
1027  // or Solve() has been called) has no effect.
1028  // The routing model does not take ownership of the filter.
1029  void AddLocalSearchFilter(LocalSearchFilter* filter) {
1030  CHECK(filter != nullptr);
1031  if (closed_) {
1032  LOG(WARNING) << "Model is closed, filter addition will be ignored.";
1033  }
1034  extra_filters_.push_back(filter);
1035  }
1036 
1037  // Model inspection.
1038  // Returns the variable index of the starting node of a vehicle route.
1039  int64 Start(int vehicle) const { return starts_[vehicle]; }
1040  // Returns the variable index of the ending node of a vehicle route.
1041  int64 End(int vehicle) const { return ends_[vehicle]; }
1042  // Returns true if 'index' represents the first node of a route.
1043  bool IsStart(int64 index) const;
1044  // Returns true if 'index' represents the last node of a route.
1045  bool IsEnd(int64 index) const { return index >= Size(); }
1046  // Returns the vehicle of the given start/end index, and -1 if the given index
1047  // is not a vehicle start/end.
1048  int VehicleIndex(int index) const { return index_to_vehicle_[index]; }
1049  // Assignment inspection
1050  // Returns the variable index of the node directly after the node
1051  // corresponding to 'index' in 'assignment'.
1052  int64 Next(const Assignment& assignment, int64 index) const;
1053  // Returns true if the route of 'vehicle' is non empty in 'assignment'.
1054  bool IsVehicleUsed(const Assignment& assignment, int vehicle) const;
1055 // Variables
1056 #if !defined(SWIGPYTHON)
1057  // Returns all next variables of the model, such that Nexts(i) is the next
1058  // variable of the node corresponding to i.
1059  const std::vector<IntVar*>& Nexts() const { return nexts_; }
1060  // Returns all vehicle variables of the model, such that VehicleVars(i) is
1061  // the vehicle variable of the node corresponding to i.
1062  const std::vector<IntVar*>& VehicleVars() const { return vehicle_vars_; }
1063 #endif // !defined(SWIGPYTHON)
1064  // Returns the next variable of the node corresponding to index. Note that
1065  // NextVar(index) == index is equivalent to ActiveVar(index) == 0.
1066  IntVar* NextVar(int64 index) const { return nexts_[index]; }
1067  // Returns the active variable of the node corresponding to index.
1068  IntVar* ActiveVar(int64 index) const { return active_[index]; }
1069  // Returns the variable specifying whether or not costs are considered for
1070  // vehicle.
1071  IntVar* VehicleCostsConsideredVar(int vehicle) const {
1072  return vehicle_costs_considered_[vehicle];
1073  }
1074  // Returns the vehicle variable of the node corresponding to index. Note that
1075  // VehicleVar(index) == -1 is equivalent to ActiveVar(index) == 0.
1076  IntVar* VehicleVar(int64 index) const { return vehicle_vars_[index]; }
1077  // Returns the global cost variable which is being minimized.
1078  IntVar* CostVar() const { return cost_; }
1079 
1080  // Returns the cost of the transit arc between two nodes for a given vehicle.
1081  // Input are variable indices of node. This returns 0 if vehicle < 0.
1082  int64 GetArcCostForVehicle(int64 from_index, int64 to_index,
1083  int64 vehicle) const;
1084  // Whether costs are homogeneous across all vehicles.
1086  return costs_are_homogeneous_across_vehicles_;
1087  }
1088  // Returns the cost of the segment between two nodes supposing all vehicle
1089  // costs are the same (returns the cost for the first vehicle otherwise).
1090  int64 GetHomogeneousCost(int64 from_index, int64 to_index) const {
1091  return GetArcCostForVehicle(from_index, to_index, /*vehicle=*/0);
1092  }
1093  // Returns the cost of the arc in the context of the first solution strategy.
1094  // This is typically a simplification of the actual cost; see the .cc.
1095  int64 GetArcCostForFirstSolution(int64 from_index, int64 to_index) const;
1096  // Returns the cost of the segment between two nodes for a given cost
1097  // class. Input are variable indices of nodes and the cost class.
1098  // Unlike GetArcCostForVehicle(), if cost_class is kNoCost, then the
1099  // returned cost won't necessarily be zero: only some of the components
1100  // of the cost that depend on the cost class will be omited. See the code
1101  // for details.
1102  int64 GetArcCostForClass(int64 from_index, int64 to_index,
1103  int64 /*CostClassIndex*/ cost_class_index) const;
1104  // Get the cost class index of the given vehicle.
1105  CostClassIndex GetCostClassIndexOfVehicle(int64 vehicle) const {
1106  DCHECK(closed_);
1107  return cost_class_index_of_vehicle_[vehicle];
1108  }
1109  // Returns true iff the model contains a vehicle with the given
1110  // cost_class_index.
1111  bool HasVehicleWithCostClassIndex(CostClassIndex cost_class_index) const {
1112  DCHECK(closed_);
1113  if (cost_class_index == kCostClassIndexOfZeroCost) {
1114  return has_vehicle_with_zero_cost_class_;
1115  }
1116  return cost_class_index < cost_classes_.size();
1117  }
1118  // Returns the number of different cost classes in the model.
1119  int GetCostClassesCount() const { return cost_classes_.size(); }
1120  // Ditto, minus the 'always zero', built-in cost class.
1122  return std::max(0, GetCostClassesCount() - 1);
1123  }
1124  VehicleClassIndex GetVehicleClassIndexOfVehicle(int64 vehicle) const {
1125  DCHECK(closed_);
1126  return vehicle_class_index_of_vehicle_[vehicle];
1127  }
1128  // Returns the number of different vehicle classes in the model.
1129  int GetVehicleClassesCount() const { return vehicle_classes_.size(); }
1130  // Returns variable indices of nodes constrained to be on the same route.
1131  const std::vector<int>& GetSameVehicleIndicesOfIndex(int node) const {
1132  DCHECK(closed_);
1133  return same_vehicle_groups_[same_vehicle_group_[node]];
1134  }
1135  // Returns whether the arc from->to1 is more constrained than from->to2,
1136  // taking into account, in order:
1137  // - whether the destination node isn't an end node
1138  // - whether the destination node is mandatory
1139  // - whether the destination node is bound to the same vehicle as the source
1140  // - the "primary constrained" dimension (see SetPrimaryConstrainedDimension)
1141  // It then breaks ties using, in order:
1142  // - the arc cost (taking unperformed penalties into account)
1143  // - the size of the vehicle vars of "to1" and "to2" (lowest size wins)
1144  // - the value: the lowest value of the indices to1 and to2 wins.
1145  // See the .cc for details.
1146  // The more constrained arc is typically preferable when building a
1147  // first solution. This method is intended to be used as a callback for the
1148  // BestValueByComparisonSelector value selector.
1149  // Args:
1150  // from: the variable index of the source node
1151  // to1: the variable index of the first candidate destination node.
1152  // to2: the variable index of the second candidate destination node.
1153  bool ArcIsMoreConstrainedThanArc(int64 from, int64 to1, int64 to2);
1154  // Print some debugging information about an assignment, including the
1155  // feasible intervals of the CumulVar for dimension "dimension_to_print"
1156  // at each step of the routes.
1157  // If "dimension_to_print" is omitted, all dimensions will be printed.
1158  std::string DebugOutputAssignment(
1159  const Assignment& solution_assignment,
1160  const std::string& dimension_to_print) const;
1161 
1162  // Returns the underlying constraint solver. Can be used to add extra
1163  // constraints and/or modify search algoithms.
1164  Solver* solver() const { return solver_.get(); }
1165 
1166  // Returns true if the search limit has been crossed.
1167  bool CheckLimit() {
1168  DCHECK(limit_ != nullptr);
1169  return limit_->Check();
1170  }
1171 
1172  // Returns the time left in the search limit.
1173  absl::Duration RemainingTime() const {
1174  DCHECK(limit_ != nullptr);
1175  return limit_->AbsoluteSolverDeadline() - solver_->Now();
1176  }
1177 
1178  // Sizes and indices
1179  // Returns the number of nodes in the model.
1180  int nodes() const { return nodes_; }
1181  // Returns the number of vehicle routes in the model.
1182  int vehicles() const { return vehicles_; }
1183  // Returns the number of next variables in the model.
1184  int64 Size() const { return nodes_ + vehicles_ - start_end_count_; }
1185 
1186  // Returns statistics on first solution search, number of decisions sent to
1187  // filters, number of decisions rejected by filters.
1189  const RoutingSearchParameters& search_parameters) const;
1191  const RoutingSearchParameters& search_parameters) const;
1192 
1193  // Returns true if a vehicle/node matching problem is detected.
1194  bool IsMatchingModel() const;
1195 
1196 #ifndef SWIG
1197  // Sets the callback returning the variable to use for the Tabu Search
1198  // metaheuristic.
1199  using GetTabuVarsCallback =
1200  std::function<std::vector<operations_research::IntVar*>(RoutingModel*)>;
1201 
1202  void SetTabuVarsCallback(GetTabuVarsCallback tabu_var_callback);
1203 #endif // SWIG
1204 
1205  // The next few members are in the public section only for testing purposes.
1206  // TODO(user): Find a way to test and restrict the access at the same time.
1207  //
1208  // MakeGuidedSlackFinalizer creates a DecisionBuilder for the slacks of a
1209  // dimension using a callback to choose which values to start with.
1210  // The finalizer works only when all next variables in the model have
1211  // been fixed. It has the following two characteristics:
1212  // 1. It follows the routes defined by the nexts variables when choosing a
1213  // variable to make a decision on.
1214  // 2. When it comes to choose a value for the slack of node i, the decision
1215  // builder first calls the callback with argument i, and supposingly the
1216  // returned value is x it creates decisions slack[i] = x, slack[i] = x + 1,
1217  // slack[i] = x - 1, slack[i] = x + 2, etc.
1218  DecisionBuilder* MakeGuidedSlackFinalizer(
1219  const RoutingDimension* dimension,
1220  std::function<int64(int64)> initializer);
1221 #ifndef SWIG
1222  // TODO(user): MakeGreedyDescentLSOperator is too general for routing.h.
1223  // Perhaps move it to constraint_solver.h.
1224  // MakeGreedyDescentLSOperator creates a local search operator that tries to
1225  // improve the initial assignment by moving a logarithmically decreasing step
1226  // away in each possible dimension.
1227  static std::unique_ptr<LocalSearchOperator> MakeGreedyDescentLSOperator(
1228  std::vector<IntVar*> variables);
1229 #endif // __SWIG__
1230  // MakeSelfDependentDimensionFinalizer is a finalizer for the slacks of a
1231  // self-dependent dimension. It makes an extensive use of the caches of the
1232  // state dependent transits.
1233  // In detail, MakeSelfDependentDimensionFinalizer returns a composition of a
1234  // local search decision builder with a greedy descent operator for the cumul
1235  // of the start of each route and a guided slack finalizer. Provided there are
1236  // no time windows and the maximum slacks are large enough, once the cumul of
1237  // the start of route is fixed, the guided finalizer can find optimal values
1238  // of the slacks for the rest of the route in time proportional to the length
1239  // of the route. Therefore the composed finalizer generally works in time
1240  // O(log(t)*n*m), where t is the latest possible departute time, n is the
1241  // number of nodes in the network and m is the number of vehicles.
1242  DecisionBuilder* MakeSelfDependentDimensionFinalizer(
1243  const RoutingDimension* dimension);
1244 
1245  private:
1246  // Local search move operator usable in routing.
1247  enum RoutingLocalSearchOperator {
1248  RELOCATE = 0,
1249  RELOCATE_PAIR,
1250  LIGHT_RELOCATE_PAIR,
1251  RELOCATE_NEIGHBORS,
1252  EXCHANGE,
1253  EXCHANGE_PAIR,
1254  CROSS,
1255  CROSS_EXCHANGE,
1256  TWO_OPT,
1257  OR_OPT,
1258  RELOCATE_EXPENSIVE_CHAIN,
1259  LIN_KERNIGHAN,
1260  TSP_OPT,
1261  MAKE_ACTIVE,
1262  RELOCATE_AND_MAKE_ACTIVE,
1263  MAKE_ACTIVE_AND_RELOCATE,
1264  MAKE_INACTIVE,
1265  MAKE_CHAIN_INACTIVE,
1266  SWAP_ACTIVE,
1267  EXTENDED_SWAP_ACTIVE,
1268  NODE_PAIR_SWAP,
1269  PATH_LNS,
1270  FULL_PATH_LNS,
1271  TSP_LNS,
1272  INACTIVE_LNS,
1273  EXCHANGE_RELOCATE_PAIR,
1274  RELOCATE_SUBTRIP,
1275  EXCHANGE_SUBTRIP,
1276  LOCAL_SEARCH_OPERATOR_COUNTER
1277  };
1278 
1279  // Structure storing a value for a set of variable indices. Is used to store
1280  // data for index disjunctions (variable indices, max_cardinality and penalty
1281  // when unperformed).
1282  template <typename T>
1283  struct ValuedNodes {
1284  std::vector<int64> indices;
1285  T value;
1286  };
1287  struct DisjunctionValues {
1288  int64 penalty;
1289  int64 max_cardinality;
1290  };
1291  typedef ValuedNodes<DisjunctionValues> Disjunction;
1292 
1293  // Storage of a cost cache element corresponding to a cost arc ending at
1294  // node 'index' and on the cost class 'cost_class'.
1295  struct CostCacheElement {
1296  // This is usually an int64, but using an int here decreases the RAM usage,
1297  // and should be fine since in practice we never have more than 1<<31 vars.
1298  // Note(user): on 2013-11, microbenchmarks on the arc costs callbacks
1299  // also showed a 2% speed-up thanks to using int rather than int64.
1300  int index;
1301  CostClassIndex cost_class_index;
1302  int64 cost;
1303  };
1304 
1305  // Internal methods.
1306  void Initialize();
1307  void AddNoCycleConstraintInternal();
1308  bool AddDimensionWithCapacityInternal(
1309  const std::vector<int>& evaluator_indices, int64 slack_max,
1310  std::vector<int64> vehicle_capacities, bool fix_start_cumul_to_zero,
1311  const std::string& name);
1312  bool AddDimensionDependentDimensionWithVehicleCapacityInternal(
1313  const std::vector<int>& pure_transits,
1314  const std::vector<int>& dependent_transits,
1315  const RoutingDimension* base_dimension, int64 slack_max,
1316  std::vector<int64> vehicle_capacities, bool fix_start_cumul_to_zero,
1317  const std::string& name);
1318  bool InitializeDimensionInternal(
1319  const std::vector<int>& evaluator_indices,
1320  const std::vector<int>& state_dependent_evaluator_indices,
1321  int64 slack_max, bool fix_start_cumul_to_zero,
1322  RoutingDimension* dimension);
1323  DimensionIndex GetDimensionIndex(const std::string& dimension_name) const;
1324 
1325  // Stores dimensions for which global and local cumul optimizers may be used
1326  // in the corresponding dimensions_for_[global|local]_optimizer_ vectors.
1327  // This function also computes and stores the "offsets" for these dimensions,
1328  // used in the local/global optimizers to simplify LP computations.
1329  //
1330  // Note on the offsets computation:
1331  // The global/local cumul offsets are used by the respective optimizers to
1332  // have smaller numbers, and therefore better numerical behavior in the LP.
1333  // These offsets are used as a minimum value for the cumuls over the route (or
1334  // globally), i.e. a value we consider all cumuls to be greater or equal to.
1335  // When transits are all positive, the cumuls of every node on a route is
1336  // necessarily greater than the cumul of its start. Therefore, the local
1337  // offset for a vehicle can be set to the minimum of its start node's cumul,
1338  // and for the global optimizers, to the min start cumul over all vehicles.
1339  // However, to be able to distinguish between infeasible nodes (i.e. nodes for
1340  // which the cumul upper bound is less than the min cumul of the vehicle's
1341  // start), we set the offset to "min_start_cumul" - 1. By doing so, all
1342  // infeasible nodes described above will have bounds of [0, 0].
1343  // Example:
1344  // Start cumul bounds: [11, 20] --> offset = 11 - 1 = 10.
1345  // Two nodes with cumul bounds. Node1: [5, 10], Node2: [7, 20]
1346  // After applying the offset to the above windows, they become:
1347  // Vehicle: [1, 10]. Node1: [0, 0] (infeasible). Node2: [0, 10].
1348  //
1349  // On the other hand, when transits on a route can be negative, no assumption
1350  // can be made on the cumuls of nodes wrt the start cumuls, and the offset is
1351  // therefore set to 0.
1352  void StoreDimensionsForDimensionCumulOptimizers();
1353 
1354  void ComputeCostClasses(const RoutingSearchParameters& parameters);
1355  void ComputeVehicleClasses();
1356  int64 GetArcCostForClassInternal(int64 from_index, int64 to_index,
1357  CostClassIndex cost_class_index) const;
1358  void AppendHomogeneousArcCosts(const RoutingSearchParameters& parameters,
1359  int node_index,
1360  std::vector<IntVar*>* cost_elements);
1361  void AppendArcCosts(const RoutingSearchParameters& parameters, int node_index,
1362  std::vector<IntVar*>* cost_elements);
1363  Assignment* DoRestoreAssignment();
1364  static const CostClassIndex kCostClassIndexOfZeroCost;
1365  int64 SafeGetCostClassInt64OfVehicle(int64 vehicle) const {
1366  DCHECK_LT(0, vehicles_);
1367  return (vehicle >= 0 ? GetCostClassIndexOfVehicle(vehicle)
1368  : kCostClassIndexOfZeroCost)
1369  .value();
1370  }
1371  int64 GetDimensionTransitCostSum(int64 i, int64 j,
1372  const CostClass& cost_class) const;
1373  // Returns nullptr if no penalty cost, otherwise returns penalty variable.
1374  IntVar* CreateDisjunction(DisjunctionIndex disjunction);
1375  // Sets up pickup and delivery sets.
1376  void AddPickupAndDeliverySetsInternal(const std::vector<int64>& pickups,
1377  const std::vector<int64>& deliveries);
1378  // Returns the cost variable related to the soft same vehicle constraint of
1379  // index 'vehicle_index'.
1380  IntVar* CreateSameVehicleCost(int vehicle_index);
1381  // Returns the first active variable index in 'indices' starting from index
1382  // + 1.
1383  int FindNextActive(int index, const std::vector<int64>& indices) const;
1384 
1385  // Checks that all nodes on the route starting at start_index (using the
1386  // solution stored in assignment) can be visited by the given vehicle.
1387  bool RouteCanBeUsedByVehicle(const Assignment& assignment, int start_index,
1388  int vehicle) const;
1389  // Replaces the route of unused_vehicle with the route of active_vehicle in
1390  // compact_assignment. Expects that unused_vehicle is a vehicle with an empty
1391  // route and that the route of active_vehicle is non-empty. Also expects that
1392  // 'assignment' contains the original assignment, from which
1393  // compact_assignment was created.
1394  // Returns true if the vehicles were successfully swapped; otherwise, returns
1395  // false.
1396  bool ReplaceUnusedVehicle(int unused_vehicle, int active_vehicle,
1397  Assignment* compact_assignment) const;
1398 
1399  void QuietCloseModel();
1400  void QuietCloseModelWithParameters(
1401  const RoutingSearchParameters& parameters) {
1402  if (!closed_) {
1403  CloseModelWithParameters(parameters);
1404  }
1405  }
1406 
1407  // Solve matching problem with min-cost flow and store result in assignment.
1408  bool SolveMatchingModel(Assignment* assignment);
1409 #ifndef SWIG
1410  // Append an assignment to a vector of assignments if it is feasible.
1411  bool AppendAssignmentIfFeasible(
1412  const Assignment& assignment,
1413  std::vector<std::unique_ptr<Assignment>>* assignments);
1414 #endif
1415  // Log a solution.
1416  void LogSolution(const RoutingSearchParameters& parameters,
1417  const std::string& description, int64 solution_cost,
1418  int64 start_time_ms);
1419  // See CompactAssignment. Checks the final solution if
1420  // check_compact_assignement is true.
1421  Assignment* CompactAssignmentInternal(const Assignment& assignment,
1422  bool check_compact_assignment) const;
1423  // Checks that the current search parameters are valid for the current model's
1424  // specific settings. This assumes that FindErrorInSearchParameters() from
1425  // ./routing_flags.h caught no error.
1426  std::string FindErrorInSearchParametersForModel(
1427  const RoutingSearchParameters& search_parameters) const;
1428  // Sets up search objects, such as decision builders and monitors.
1429  void SetupSearch(const RoutingSearchParameters& search_parameters);
1430  // Set of auxiliary methods used to setup the search.
1431  // TODO(user): Document each auxiliary method.
1432  Assignment* GetOrCreateAssignment();
1433  Assignment* GetOrCreateTmpAssignment();
1434  RegularLimit* GetOrCreateLimit();
1435  RegularLimit* GetOrCreateLocalSearchLimit();
1436  RegularLimit* GetOrCreateLargeNeighborhoodSearchLimit();
1437  RegularLimit* GetOrCreateFirstSolutionLargeNeighborhoodSearchLimit();
1438  LocalSearchOperator* CreateInsertionOperator();
1439  LocalSearchOperator* CreateMakeInactiveOperator();
1440  void CreateNeighborhoodOperators(const RoutingSearchParameters& parameters);
1441  LocalSearchOperator* GetNeighborhoodOperators(
1442  const RoutingSearchParameters& search_parameters) const;
1443  const std::vector<LocalSearchFilter*>& GetOrCreateLocalSearchFilters();
1444  const std::vector<LocalSearchFilter*>& GetOrCreateFeasibilityFilters();
1445  DecisionBuilder* CreateSolutionFinalizer(SearchLimit* lns_limit);
1446  DecisionBuilder* CreateFinalizerForMinimizedAndMaximizedVariables();
1447  void CreateFirstSolutionDecisionBuilders(
1448  const RoutingSearchParameters& search_parameters);
1449  DecisionBuilder* GetFirstSolutionDecisionBuilder(
1450  const RoutingSearchParameters& search_parameters) const;
1451  IntVarFilteredDecisionBuilder* GetFilteredFirstSolutionDecisionBuilderOrNull(
1452  const RoutingSearchParameters& parameters) const;
1453  LocalSearchPhaseParameters* CreateLocalSearchParameters(
1454  const RoutingSearchParameters& search_parameters);
1455  DecisionBuilder* CreateLocalSearchDecisionBuilder(
1456  const RoutingSearchParameters& search_parameters);
1457  void SetupDecisionBuilders(const RoutingSearchParameters& search_parameters);
1458  void SetupMetaheuristics(const RoutingSearchParameters& search_parameters);
1459  void SetupAssignmentCollector(
1460  const RoutingSearchParameters& search_parameters);
1461  void SetupTrace(const RoutingSearchParameters& search_parameters);
1462  void SetupSearchMonitors(const RoutingSearchParameters& search_parameters);
1463  bool UsesLightPropagation(
1464  const RoutingSearchParameters& search_parameters) const;
1465  GetTabuVarsCallback tabu_var_callback_;
1466 
1467  int GetVehicleStartClass(int64 start) const;
1468 
1469  void InitSameVehicleGroups(int number_of_groups) {
1470  same_vehicle_group_.assign(Size(), 0);
1471  same_vehicle_groups_.assign(number_of_groups, {});
1472  }
1473  void SetSameVehicleGroup(int index, int group) {
1474  same_vehicle_group_[index] = group;
1475  same_vehicle_groups_[group].push_back(index);
1476  }
1477 
1478  // Model
1479  std::unique_ptr<Solver> solver_;
1480  int nodes_;
1481  int vehicles_;
1482  Constraint* no_cycle_constraint_ = nullptr;
1483  // Decision variables: indexed by int64 var index.
1484  std::vector<IntVar*> nexts_;
1485  std::vector<IntVar*> vehicle_vars_;
1486  std::vector<IntVar*> active_;
1487  std::vector<IntVar*> vehicle_costs_considered_;
1488  // is_bound_to_end_[i] will be true iff the path starting at var #i is fully
1489  // bound and reaches the end of a route, i.e. either:
1490  // - IsEnd(i) is true
1491  // - or nexts_[i] is bound and is_bound_to_end_[nexts_[i].Value()] is true.
1492  std::vector<IntVar*> is_bound_to_end_;
1493  mutable RevSwitch is_bound_to_end_ct_added_;
1494  // Dimensions
1495  absl::flat_hash_map<std::string, DimensionIndex> dimension_name_to_index_;
1496  gtl::ITIVector<DimensionIndex, RoutingDimension*> dimensions_;
1497  std::vector<RoutingDimension*> dimensions_for_global_optimizer_;
1498  std::vector<RoutingDimension*> dimensions_for_local_optimizer_;
1499  std::string primary_constrained_dimension_;
1500  // Costs
1501  IntVar* cost_ = nullptr;
1502  std::vector<int> vehicle_to_transit_cost_;
1503  std::vector<int64> fixed_cost_of_vehicle_;
1504  std::vector<CostClassIndex> cost_class_index_of_vehicle_;
1505  bool has_vehicle_with_zero_cost_class_;
1506  std::vector<int64> linear_cost_factor_of_vehicle_;
1507  std::vector<int64> quadratic_cost_factor_of_vehicle_;
1508  bool vehicle_amortized_cost_factors_set_;
1509  // consider_empty_route_costs_[vehicle] determines if "vehicle" should be
1510  // taken into account for costs (arc costs, span costs, etc.) even when the
1511  // route of the vehicle is empty (i.e. goes straight from its start to its
1512  // end).
1513  // NOTE1: A vehicle's fixed cost is added iff the vehicle serves nodes on its
1514  // route, regardless of this variable's value.
1515  // NOTE2: The default value for this boolean is 'false' for all vehicles, i.e.
1516  // by default empty routes will not contribute to the cost.
1517  std::vector<bool> consider_empty_route_costs_;
1518 #ifndef SWIG
1519  gtl::ITIVector<CostClassIndex, CostClass> cost_classes_;
1520 #endif // SWIG
1521  bool costs_are_homogeneous_across_vehicles_;
1522  bool cache_callbacks_;
1523  mutable std::vector<CostCacheElement> cost_cache_; // Index by source index.
1524  std::vector<VehicleClassIndex> vehicle_class_index_of_vehicle_;
1525 #ifndef SWIG
1526  gtl::ITIVector<VehicleClassIndex, VehicleClass> vehicle_classes_;
1527 #endif // SWIG
1528  std::function<int(int64)> vehicle_start_class_callback_;
1529  // Disjunctions
1530  gtl::ITIVector<DisjunctionIndex, Disjunction> disjunctions_;
1531  std::vector<std::vector<DisjunctionIndex>> index_to_disjunctions_;
1532  // Same vehicle costs
1533  std::vector<ValuedNodes<int64>> same_vehicle_costs_;
1534  // Allowed vehicles
1535 #ifndef SWIG
1536  std::vector<std::unordered_set<int>> allowed_vehicles_;
1537 #endif // SWIG
1538  // Pickup and delivery
1539  IndexPairs pickup_delivery_pairs_;
1540  std::vector<std::pair<DisjunctionIndex, DisjunctionIndex>>
1541  pickup_delivery_disjunctions_;
1542  // clang-format off
1543  // If node_index is a pickup, index_to_pickup_index_pairs_[node_index] is the
1544  // vector of pairs {pair_index, pickup_index} such that
1545  // (pickup_delivery_pairs_[pair_index].first)[pickup_index] == node_index
1546  std::vector<std::vector<std::pair<int, int> > > index_to_pickup_index_pairs_;
1547  // Same as above for deliveries.
1548  std::vector<std::vector<std::pair<int, int> > >
1549  index_to_delivery_index_pairs_;
1550  // clang-format on
1551  std::vector<PickupAndDeliveryPolicy> vehicle_pickup_delivery_policy_;
1552  // Same vehicle group to which a node belongs.
1553  std::vector<int> same_vehicle_group_;
1554  // Same vehicle node groups.
1555  std::vector<std::vector<int>> same_vehicle_groups_;
1556  // Node visit types
1557  // Variable index to visit type index.
1558  std::vector<int> index_to_visit_type_;
1559  // clang-format off
1560  std::vector<absl::flat_hash_set<int> >
1561  hard_incompatible_types_per_type_index_;
1562  bool has_hard_type_incompatibilities_;
1563  std::vector<absl::flat_hash_set<int> >
1564  temporal_incompatible_types_per_type_index_;
1565  bool has_temporal_type_incompatibilities_;
1566 
1567  std::vector<std::vector<absl::flat_hash_set<int> > >
1568  same_vehicle_required_type_alternatives_per_type_index_;
1569  bool has_same_vehicle_type_requirements_;
1570  std::vector<std::vector<absl::flat_hash_set<int> > >
1571  temporal_required_type_alternatives_per_type_index_;
1572  bool has_temporal_type_requirements_;
1573  absl::flat_hash_set<int> trivially_infeasible_visit_types_;
1574  // clang-format on
1575  int num_visit_types_;
1576  // Two indices are equivalent if they correspond to the same node (as given to
1577  // the constructors taking a RoutingIndexManager).
1578  std::vector<int> index_to_equivalence_class_;
1579  std::vector<int> index_to_vehicle_;
1580  std::vector<int64> starts_;
1581  std::vector<int64> ends_;
1582  // TODO(user): b/62478706 Once the port is done, this shouldn't be needed
1583  // anymore.
1584  RoutingIndexManager manager_;
1585  int start_end_count_;
1586  // Model status
1587  bool closed_ = false;
1588  Status status_ = ROUTING_NOT_SOLVED;
1589  bool enable_deep_serialization_ = true;
1590 
1591  // Search data
1592  std::vector<DecisionBuilder*> first_solution_decision_builders_;
1593  std::vector<IntVarFilteredDecisionBuilder*>
1594  first_solution_filtered_decision_builders_;
1595  Solver::IndexEvaluator2 first_solution_evaluator_;
1596  std::vector<LocalSearchOperator*> local_search_operators_;
1597  std::vector<SearchMonitor*> monitors_;
1598  SolutionCollector* collect_assignments_ = nullptr;
1599  SolutionCollector* collect_one_assignment_ = nullptr;
1600  SolutionCollector* packed_dimensions_assignment_collector_ = nullptr;
1601  DecisionBuilder* solve_db_ = nullptr;
1602  DecisionBuilder* improve_db_ = nullptr;
1603  DecisionBuilder* restore_assignment_ = nullptr;
1604  DecisionBuilder* restore_tmp_assignment_ = nullptr;
1605  Assignment* assignment_ = nullptr;
1606  Assignment* preassignment_ = nullptr;
1607  Assignment* tmp_assignment_ = nullptr;
1608  std::vector<IntVar*> extra_vars_;
1609  std::vector<IntervalVar*> extra_intervals_;
1610  std::vector<LocalSearchOperator*> extra_operators_;
1611  std::vector<LocalSearchFilter*> filters_;
1612  std::vector<LocalSearchFilter*> feasibility_filters_;
1613  std::vector<LocalSearchFilter*> extra_filters_;
1614  std::vector<IntVar*> variables_maximized_by_finalizer_;
1615  std::vector<IntVar*> variables_minimized_by_finalizer_;
1616 #ifndef SWIG
1617  std::unique_ptr<SweepArranger> sweep_arranger_;
1618 #endif
1619 
1620  RegularLimit* limit_ = nullptr;
1621  RegularLimit* ls_limit_ = nullptr;
1622  RegularLimit* lns_limit_ = nullptr;
1623  RegularLimit* first_solution_lns_limit_ = nullptr;
1624 
1625  typedef std::pair<int64, int64> CacheKey;
1626  typedef absl::flat_hash_map<CacheKey, int64> TransitCallbackCache;
1627  typedef absl::flat_hash_map<CacheKey, StateDependentTransit>
1628  StateDependentTransitCallbackCache;
1629 
1630  std::vector<TransitCallback1> unary_transit_evaluators_;
1631  std::vector<TransitCallback2> transit_evaluators_;
1632  // The following vector stores a boolean per transit_evaluator_, indicating
1633  // whether the transits are all positive.
1634  // is_transit_evaluator_positive_ will be set to true only when registering a
1635  // callback via RegisterPositiveTransitCallback(), and to false otherwise.
1636  // The actual positivity of the transit values will only be checked in debug
1637  // mode, when calling RegisterPositiveTransitCallback().
1638  // Therefore, RegisterPositiveTransitCallback() should only be called when the
1639  // transits are known to be positive, as the positivity of a callback will
1640  // allow some improvements in the solver, but will entail in errors if the
1641  // transits are falsely assumed positive.
1642  std::vector<bool> is_transit_evaluator_positive_;
1643  std::vector<VariableIndexEvaluator2> state_dependent_transit_evaluators_;
1644  std::vector<std::unique_ptr<StateDependentTransitCallbackCache>>
1645  state_dependent_transit_evaluators_cache_;
1646 
1647  friend class RoutingDimension;
1649 
1650  DISALLOW_COPY_AND_ASSIGN(RoutingModel);
1651 };
1652 
1653 // Routing model visitor.
1654 class RoutingModelVisitor : public BaseObject {
1655  public:
1656  // Constraint types.
1657  static const char kLightElement[];
1658  static const char kLightElement2[];
1659  static const char kRemoveValues[];
1660 };
1661 
1662 #if !defined(SWIG)
1663 // This class acts like a CP propagator: it takes a set of tasks given by
1664 // their start/duration/end features, and reduces the range of possible values.
1665 class DisjunctivePropagator {
1666  public:
1667  // A structure to hold tasks described by their features.
1668  // The first num_chain_tasks are considered linked by a chain of precedences,
1669  // i.e. if i < j < num_chain_tasks, then end(i) <= start(j).
1670  // This occurs frequently in routing, and can be leveraged by
1671  // some variants of classic propagators.
1672  struct Tasks {
1673  int num_chain_tasks = 0;
1674  std::vector<int64> start_min;
1675  std::vector<int64> start_max;
1676  std::vector<int64> duration_min;
1677  std::vector<int64> duration_max;
1678  std::vector<int64> end_min;
1679  std::vector<int64> end_max;
1680  std::vector<bool> is_preemptible;
1681  std::vector<const SortedDisjointIntervalList*> forbidden_intervals;
1682  std::vector<std::pair<int64, int64>> distance_duration;
1683 
1684  void Clear() {
1685  start_min.clear();
1686  start_max.clear();
1687  duration_min.clear();
1688  duration_max.clear();
1689  end_min.clear();
1690  end_max.clear();
1691  is_preemptible.clear();
1692  forbidden_intervals.clear();
1693  distance_duration.clear();
1694  }
1695  };
1696 
1697  // Computes new bounds for all tasks, returns false if infeasible.
1698  // This does not compute a fixed point, so recalling it may filter more.
1699  bool Propagate(Tasks* tasks);
1700 
1701  // Propagates the deductions from the chain of precedences, if there is one.
1702  bool Precedences(Tasks* tasks);
1703  // Transforms the problem with a time symmetry centered in 0. Returns true for
1704  // convenience.
1705  bool MirrorTasks(Tasks* tasks);
1706  // Does edge-finding deductions on all tasks.
1707  bool EdgeFinding(Tasks* tasks);
1708  // Does detectable precedences deductions on tasks in the chain precedence,
1709  // taking the time windows of nonchain tasks into account.
1710  bool DetectablePrecedencesWithChain(Tasks* tasks);
1711  // Tasks might have holes in their domain, this enforces such holes.
1712  bool ForbiddenIntervals(Tasks* tasks);
1713  bool DistanceDuration(Tasks* tasks);
1714 
1715  private:
1716  // The main algorithm uses Vilim's theta tree data structure.
1717  // See Petr Vilim's PhD thesis "Global Constraints in Scheduling".
1718  sat::ThetaLambdaTree<int64> theta_lambda_tree_;
1719  // Mappings between events and tasks.
1720  std::vector<int> tasks_by_start_min_;
1721  std::vector<int> tasks_by_end_max_;
1722  std::vector<int> event_of_task_;
1723  std::vector<int> nonchain_tasks_by_start_max_;
1724 };
1725 
1726 void AppendTasksFromPath(const std::vector<int64>& path,
1727  const std::vector<int64>& min_travels,
1728  const std::vector<int64>& max_travels,
1729  const std::vector<int64>& pre_travels,
1730  const std::vector<int64>& post_travels,
1731  const RoutingDimension& dimension,
1733 void AppendTasksFromIntervals(const std::vector<IntervalVar*>& intervals,
1735 void FillPathEvaluation(const std::vector<int64>& path,
1736  const RoutingModel::TransitCallback2& evaluator,
1737  std::vector<int64>* values);
1738 #endif // !defined(SWIG)
1739 
1740 // GlobalVehicleBreaksConstraint ensures breaks constraints are enforced on
1741 // all vehicles in the dimension passed to its constructor.
1742 // It is intended to be used for dimensions representing time.
1743 // A break constraint ensures break intervals fit on the route of a vehicle.
1744 // For a given vehicle, it forces break intervals to be disjoint from visit
1745 // intervals, where visit intervals start at CumulVar(node) and last for
1746 // node_visit_transit[node]. Moreover, it ensures that there is enough time
1747 // between two consecutive nodes of a route to do transit and vehicle breaks,
1748 // i.e. if Next(nodeA) = nodeB, CumulVar(nodeA) = tA and CumulVar(nodeB) = tB,
1749 // then SlackVar(nodeA) >= sum_{breaks \subseteq [tA, tB)} duration(break).
1750 class GlobalVehicleBreaksConstraint : public Constraint {
1751  public:
1752  explicit GlobalVehicleBreaksConstraint(const RoutingDimension* dimension);
1753 
1754  void Post() override;
1755  void InitialPropagate() override;
1756 
1757  private:
1758  void PropagateNode(int node);
1759  void PropagateVehicle(int vehicle);
1760  void PropagateMaxBreakDistance(int vehicle);
1761 
1762  const RoutingModel* model_;
1763  const RoutingDimension* const dimension_;
1764  std::vector<Demon*> vehicle_demons_;
1765  std::vector<int64> path_;
1766 
1767  // Sets path_ to be the longest sequence such that
1768  // _ path_[0] is the start of the vehicle
1769  // _ Next(path_[i-1]) is Bound() and has value path_[i],
1770  // followed by the end of the vehicle if the last node was not an end.
1771  void FillPartialPathOfVehicle(int vehicle);
1772  void FillPathTravels(const std::vector<int64>& path);
1773 
1774  // This translates pruning information to solver variables.
1775  // If constructed with an IntervalVar*, it follows the usual semantics of
1776  // IntervalVars. If constructed with an IntVar*, before_start and after_start,
1777  // operations are translated to simulate an interval that starts at
1778  // start - before_start and ends and start + after_start.
1779  // If constructed with nothing, the TaskTranslator will do nothing.
1780  // This class should have been an interface + subclasses,
1781  // but that would force pointers in the user's task vector,
1782  // which means dynamic allocation. With this union-like structure,
1783  // a vector's reserved size will adjust to usage and eventually no more
1784  // dynamic allocation will be made.
1785  class TaskTranslator {
1786  public:
1787  TaskTranslator(IntVar* start, int64 before_start, int64 after_start)
1788  : start_(start),
1789  before_start_(before_start),
1790  after_start_(after_start) {}
1791  explicit TaskTranslator(IntervalVar* interval) : interval_(interval) {}
1792  TaskTranslator() {}
1793 
1794  void SetStartMin(int64 value) {
1795  if (start_ != nullptr) {
1796  start_->SetMin(CapAdd(before_start_, value));
1797  } else if (interval_ != nullptr) {
1798  interval_->SetStartMin(value);
1799  }
1800  }
1801  void SetStartMax(int64 value) {
1802  if (start_ != nullptr) {
1803  start_->SetMax(CapAdd(before_start_, value));
1804  } else if (interval_ != nullptr) {
1805  interval_->SetStartMax(value);
1806  }
1807  }
1808  void SetDurationMin(int64 value) {
1809  if (interval_ != nullptr) {
1810  interval_->SetDurationMin(value);
1811  }
1812  }
1813  void SetEndMin(int64 value) {
1814  if (start_ != nullptr) {
1815  start_->SetMin(CapSub(value, after_start_));
1816  } else if (interval_ != nullptr) {
1817  interval_->SetEndMin(value);
1818  }
1819  }
1820  void SetEndMax(int64 value) {
1821  if (start_ != nullptr) {
1822  start_->SetMax(CapSub(value, after_start_));
1823  } else if (interval_ != nullptr) {
1824  interval_->SetEndMax(value);
1825  }
1826  }
1827 
1828  private:
1829  IntVar* start_ = nullptr;
1830  int64 before_start_;
1831  int64 after_start_;
1832  IntervalVar* interval_ = nullptr;
1833  };
1834 
1835  // Route and interval variables are normalized to the following values.
1836  std::vector<TaskTranslator> task_translators_;
1837 
1838  // This is used to restrict bounds of tasks.
1839  DisjunctivePropagator disjunctive_propagator_;
1841 
1842  // Fields used to help build tasks_ at each propagation.
1843  std::vector<int64> min_travel_;
1844  std::vector<int64> max_travel_;
1845  std::vector<int64> pre_travel_;
1846  std::vector<int64> post_travel_;
1847 };
1848 
1849 class TypeRegulationsChecker {
1850  public:
1851  explicit TypeRegulationsChecker(const RoutingModel& model);
1852  virtual ~TypeRegulationsChecker() {}
1853 
1854  bool CheckVehicle(int vehicle,
1855  const std::function<int64(int64)>& next_accessor);
1856 
1857  protected:
1858  enum PickupDeliveryStatus { PICKUP, DELIVERY, NONE };
1859  struct NodeCount {
1860  int non_pickup_delivery = 0;
1861  int pickup = 0;
1862  int delivery = 0;
1863  };
1864 
1865  // Returns the number of pickups and fixed nodes from counts_of_type_["type"].
1866  int GetNonDeliveryCount(int type) const;
1867  // Same as above, but substracting the number of deliveries of "type".
1868  int GetNonDeliveredCount(int type) const;
1869 
1870  virtual bool HasRegulationsToCheck() const = 0;
1871  virtual void InitializeCheck() {}
1872  virtual bool CheckTypeRegulations(int type) = 0;
1873  virtual bool FinalizeCheck() const { return true; }
1874 
1875  const RoutingModel& model_;
1876 
1877  private:
1878  std::vector<PickupDeliveryStatus> pickup_delivery_status_of_node_;
1879  std::vector<NodeCount> counts_of_type_;
1880 };
1881 
1882 // Checker for type incompatibilities.
1883 class TypeIncompatibilityChecker : public TypeRegulationsChecker {
1884  public:
1885  TypeIncompatibilityChecker(const RoutingModel& model,
1886  bool check_hard_incompatibilities);
1887  ~TypeIncompatibilityChecker() override {}
1888 
1889  private:
1890  bool HasRegulationsToCheck() const override;
1891  bool CheckTypeRegulations(int type) override;
1892  // NOTE(user): As temporal incompatibilities are always verified with this
1893  // checker, we only store 1 boolean indicating whether or not hard
1894  // incompatibilities are also verified.
1895  bool check_hard_incompatibilities_;
1896 };
1897 
1898 // Checker for type requirements.
1899 class TypeRequirementChecker : public TypeRegulationsChecker {
1900  public:
1901  explicit TypeRequirementChecker(const RoutingModel& model)
1902  : TypeRegulationsChecker(model) {}
1903  ~TypeRequirementChecker() override {}
1904 
1905  private:
1906  bool HasRegulationsToCheck() const override;
1907  void InitializeCheck() override {
1908  types_with_same_vehicle_requirements_on_route_.clear();
1909  }
1910  bool CheckTypeRegulations(int type) override;
1911  bool FinalizeCheck() const override;
1912 
1913  absl::flat_hash_set<int> types_with_same_vehicle_requirements_on_route_;
1914 };
1915 
1916 // The following constraint ensures that incompatibilities and requirements
1917 // between types are respected.
1918 //
1919 // It verifies both "hard" and "temporal" incompatibilities.
1920 // Two nodes with hard incompatible types cannot be served by the same vehicle
1921 // at all, while with a temporal incompatibility they can't be on the same route
1922 // at the same time.
1923 // For example, for three temporally incompatible types T1 T2 and T3, two
1924 // pickup/delivery pairs p1/d1 and p2/d2 of type T1 and T2 respectively, and a
1925 // non-pickup/delivery node n of type T3, the configuration
1926 // p1 --> d1 --> n --> p2 --> d2 is acceptable, whereas any configurations
1927 // with p1 --> p2 --> d1 --> ..., or p1 --> n --> d1 --> ... is not feasible.
1928 //
1929 // It also verifies same-vehicle and temporal type requirements.
1930 // In the above example, if T1 is a requirement for T2:
1931 // - For a same-vehicle requirement, p1/d1 must be on the same vehicle as p2/d2.
1932 // - For a temporal requirement, p2 must be visited between p1 and d1.
1933 class TypeRegulationsConstraint : public Constraint {
1934  public:
1935  explicit TypeRegulationsConstraint(const RoutingModel& model);
1936 
1937  void Post() override;
1938  void InitialPropagate() override;
1939 
1940  private:
1941  void PropagateNodeRegulations(int node);
1942  void CheckRegulationsOnVehicle(int vehicle);
1943 
1944  const RoutingModel& model_;
1945  TypeIncompatibilityChecker incompatibility_checker_;
1946  TypeRequirementChecker requirement_checker_;
1947  std::vector<Demon*> vehicle_demons_;
1948 };
1949 #if !defined SWIG
1950 // A structure meant to store soft bounds and associated violation constants.
1951 // It is 'Simple' because it has one BoundCost per element,
1952 // in contrast to 'Multiple'. Design notes:
1953 // - it is meant to store model information to be shared through pointers,
1954 // so it disallows copy and assign to avoid accidental duplication.
1955 // - it keeps soft bounds as an array of structs to help cache,
1956 // because code that uses such bounds typically use both bound and cost.
1957 // - soft bounds are named pairs, prevents some mistakes.
1958 // - using operator[] to access elements is not interesting,
1959 // because the structure will be accessed through pointers, moreover having
1960 // to type bound_cost reminds the user of the order if they do a copy
1961 // assignment of the element.
1962 class SimpleBoundCosts {
1963  public:
1964  struct BoundCost {
1965  int64 bound;
1966  int64 cost;
1967  };
1968  SimpleBoundCosts(int num_bounds, BoundCost default_bound_cost)
1969  : bound_costs_(num_bounds, default_bound_cost) {}
1970  BoundCost& bound_cost(int element) { return bound_costs_[element]; }
1971  BoundCost bound_cost(int element) const { return bound_costs_[element]; }
1972  int Size() { return bound_costs_.size(); }
1973  SimpleBoundCosts(const SimpleBoundCosts&) = delete;
1974  SimpleBoundCosts operator=(const SimpleBoundCosts&) = delete;
1975 
1976  private:
1977  std::vector<BoundCost> bound_costs_;
1978 };
1979 #endif // !defined SWIG
1980 
1981 // Dimensions represent quantities accumulated at nodes along the routes. They
1982 // represent quantities such as weights or volumes carried along the route, or
1983 // distance or times.
1984 //
1985 // Quantities at a node are represented by "cumul" variables and the increase
1986 // or decrease of quantities between nodes are represented by "transit"
1987 // variables. These variables are linked as follows:
1988 //
1989 // if j == next(i),
1990 // cumuls(j) = cumuls(i) + transits(i) + slacks(i) + state_dependent_transits(i)
1991 //
1992 // where slack is a positive slack variable (can represent waiting times for
1993 // a time dimension), and state_dependent_transits is a non-purely functional
1994 // version of transits_. Favour transits over state_dependent_transits when
1995 // possible, because purely functional callbacks allow more optimisations and
1996 // make the model faster and easier to solve.
1997 // TODO(user): Break constraints need to know the service time of nodes
1998 // for a given vehicle, it is passed as an external vector, it would be better
1999 // to have this information here.
2000 class RoutingDimension {
2001  public:
2002  ~RoutingDimension();
2003  // Returns the model on which the dimension was created.
2004  RoutingModel* model() const { return model_; }
2005  // Returns the transition value for a given pair of nodes (as var index);
2006  // this value is the one taken by the corresponding transit variable when
2007  // the 'next' variable for 'from_index' is bound to 'to_index'.
2008  int64 GetTransitValue(int64 from_index, int64 to_index, int64 vehicle) const;
2009  // Same as above but taking a vehicle class of the dimension instead of a
2010  // vehicle (the class of a vehicle can be obtained with vehicle_to_class()).
2011  int64 GetTransitValueFromClass(int64 from_index, int64 to_index,
2012  int64 vehicle_class) const {
2013  return model_->TransitCallback(class_evaluators_[vehicle_class])(from_index,
2014  to_index);
2015  }
2016  // Get the cumul, transit and slack variables for the given node (given as
2017  // int64 var index).
2018  IntVar* CumulVar(int64 index) const { return cumuls_[index]; }
2019  IntVar* TransitVar(int64 index) const { return transits_[index]; }
2020  IntVar* FixedTransitVar(int64 index) const { return fixed_transits_[index]; }
2021  IntVar* SlackVar(int64 index) const { return slacks_[index]; }
2022 
2023 #if !defined(SWIGPYTHON)
2024  // Like CumulVar(), TransitVar(), SlackVar() but return the whole variable
2025  // vectors instead (indexed by int64 var index).
2026  const std::vector<IntVar*>& cumuls() const { return cumuls_; }
2027  const std::vector<IntVar*>& fixed_transits() const { return fixed_transits_; }
2028  const std::vector<IntVar*>& transits() const { return transits_; }
2029  const std::vector<IntVar*>& slacks() const { return slacks_; }
2030 #if !defined(SWIGCSHARP) && !defined(SWIGJAVA)
2031  // Returns forbidden intervals for each node.
2032  const std::vector<SortedDisjointIntervalList>& forbidden_intervals() const {
2033  return forbidden_intervals_;
2034  }
2035  // Returns the capacities for all vehicles.
2036  const std::vector<int64>& vehicle_capacities() const {
2037  return vehicle_capacities_;
2038  }
2039  // Returns the callback evaluating the transit value between two node indices
2040  // for a given vehicle.
2041  const RoutingModel::TransitCallback2& transit_evaluator(int vehicle) const {
2042  return model_->TransitCallback(
2043  class_evaluators_[vehicle_to_class_[vehicle]]);
2044  }
2045  // Returns true iff the transit evaluator of 'vehicle' is positive for all
2046  // arcs.
2047  bool AreVehicleTransitsPositive(int vehicle) const {
2048  return model()->is_transit_evaluator_positive_
2049  [class_evaluators_[vehicle_to_class_[vehicle]]];
2050  }
2051  int vehicle_to_class(int vehicle) const { return vehicle_to_class_[vehicle]; }
2052 #endif // !defined(SWIGCSHARP) && !defined(SWIGJAVA)
2053 #endif // !defined(SWIGPYTHON)
2054  // Sets an upper bound on the dimension span on a given vehicle. This is the
2055  // preferred way to limit the "length" of the route of a vehicle according to
2056  // a dimension.
2057  void SetSpanUpperBoundForVehicle(int64 upper_bound, int vehicle);
2058  // Sets a cost proportional to the dimension span on a given vehicle,
2059  // or on all vehicles at once. "coefficient" must be nonnegative.
2060  // This is handy to model costs proportional to idle time when the dimension
2061  // represents time.
2062  // The cost for a vehicle is
2063  // span_cost = coefficient * (dimension end value - dimension start value).
2064  void SetSpanCostCoefficientForVehicle(int64 coefficient, int vehicle);
2065  void SetSpanCostCoefficientForAllVehicles(int64 coefficient);
2066  // Sets a cost proportional to the *global* dimension span, that is the
2067  // difference between the largest value of route end cumul variables and
2068  // the smallest value of route start cumul variables.
2069  // In other words:
2070  // global_span_cost =
2071  // coefficient * (Max(dimension end value) - Min(dimension start value)).
2072  void SetGlobalSpanCostCoefficient(int64 coefficient);
2073 
2074 #ifndef SWIG
2075  // Sets a piecewise linear cost on the cumul variable of a given variable
2076  // index. If f is a piecewise linear function, the resulting cost at 'index'
2077  // will be f(CumulVar(index)). As of 3/2017, only non-decreasing positive cost
2078  // functions are supported.
2079  void SetCumulVarPiecewiseLinearCost(int64 index,
2080  const PiecewiseLinearFunction& cost);
2081  // Returns true if a piecewise linear cost has been set for a given variable
2082  // index.
2083  bool HasCumulVarPiecewiseLinearCost(int64 index) const;
2084  // Returns the piecewise linear cost of a cumul variable for a given variable
2085  // index. The returned pointer has the same validity as this class.
2086  const PiecewiseLinearFunction* GetCumulVarPiecewiseLinearCost(
2087  int64 index) const;
2088 #endif
2089 
2090  // Sets a soft upper bound to the cumul variable of a given variable index. If
2091  // the value of the cumul variable is greater than the bound, a cost
2092  // proportional to the difference between this value and the bound is added to
2093  // the cost function of the model:
2094  // cumulVar <= upper_bound -> cost = 0
2095  // cumulVar > upper_bound -> cost = coefficient * (cumulVar - upper_bound)
2096  // This is also handy to model tardiness costs when the dimension represents
2097  // time.
2098  void SetCumulVarSoftUpperBound(int64 index, int64 upper_bound,
2099  int64 coefficient);
2100  // Returns true if a soft upper bound has been set for a given variable index.
2101  bool HasCumulVarSoftUpperBound(int64 index) const;
2102  // Returns the soft upper bound of a cumul variable for a given variable
2103  // index. The "hard" upper bound of the variable is returned if no soft upper
2104  // bound has been set.
2105  int64 GetCumulVarSoftUpperBound(int64 index) const;
2106  // Returns the cost coefficient of the soft upper bound of a cumul variable
2107  // for a given variable index. If no soft upper bound has been set, 0 is
2108  // returned.
2109  int64 GetCumulVarSoftUpperBoundCoefficient(int64 index) const;
2110 
2111  // Sets a soft lower bound to the cumul variable of a given variable index. If
2112  // the value of the cumul variable is less than the bound, a cost proportional
2113  // to the difference between this value and the bound is added to the cost
2114  // function of the model:
2115  // cumulVar > lower_bound -> cost = 0
2116  // cumulVar <= lower_bound -> cost = coefficient * (lower_bound - cumulVar).
2117  // This is also handy to model earliness costs when the dimension represents
2118  // time.
2119  // Note: Using soft lower and upper bounds or span costs together is, as of
2120  // 6/2014, not well supported in the sense that an optimal schedule is not
2121  // guaranteed.
2122  void SetCumulVarSoftLowerBound(int64 index, int64 lower_bound,
2123  int64 coefficient);
2124  // Returns true if a soft lower bound has been set for a given variable index.
2125  bool HasCumulVarSoftLowerBound(int64 index) const;
2126  // Returns the soft lower bound of a cumul variable for a given variable
2127  // index. The "hard" lower bound of the variable is returned if no soft lower
2128  // bound has been set.
2129  int64 GetCumulVarSoftLowerBound(int64 index) const;
2130  // Returns the cost coefficient of the soft lower bound of a cumul variable
2131  // for a given variable index. If no soft lower bound has been set, 0 is
2132  // returned.
2133  int64 GetCumulVarSoftLowerBoundCoefficient(int64 index) const;
2134  // Sets the breaks for a given vehicle. Breaks are represented by
2135  // IntervalVars. They may interrupt transits between nodes and increase
2136  // the value of corresponding slack variables.
2137  // A break may take place before the start of a vehicle, after the end of
2138  // a vehicle, or during a travel i -> j.
2139  // In that case, the interval [break.Start(), break.End()) must be a subset of
2140  // [CumulVar(i) + pre_travel(i, j), CumulVar(j) - post_travel(i, j)).
2141  // In other words, a break may not overlap any node n's visit, given by
2142  // [CumulVar(n) - post_travel(_, n), CumulVar(n) + pre_travel(n, _)).
2143  // This formula considers post_travel(_, start) and pre_travel(end, _) to be
2144  // 0; pre_travel will never be called on any (_, start) and post_travel will
2145  // never we called on any (end, _). If pre_travel_evaluator or
2146  // post_travel_evaluator is -1, it will be taken as a function that always
2147  // returns 0.
2148  // TODO(user): Remove if !defined when routing.i is repaired.
2149 #if !defined(SWIGPYTHON)
2150  void SetBreakIntervalsOfVehicle(std::vector<IntervalVar*> breaks, int vehicle,
2151  int pre_travel_evaluator,
2152  int post_travel_evaluator);
2153 #endif // !defined(SWIGPYTHON)
2154 
2155  // Deprecated, sets pre_travel(i, j) = node_visit_transit[i].
2156  void SetBreakIntervalsOfVehicle(std::vector<IntervalVar*> breaks, int vehicle,
2157  std::vector<int64> node_visit_transits);
2158 
2159  // With breaks supposed to be consecutive, this forces the distance between
2160  // breaks of size at least minimum_break_duration to be at least distance.
2161  // This supposes that the time until route start and after route end are
2162  // infinite breaks.
2163  void SetBreakDistanceDurationOfVehicle(int64 distance, int64 duration,
2164  int vehicle);
2165  // Sets up vehicle_break_intervals_, vehicle_break_distance_duration_,
2166  // pre_travel_evaluators and post_travel_evaluators.
2167  void InitializeBreaks();
2168  // Returns true if any break interval or break distance was defined.
2169  bool HasBreakConstraints() const;
2170 #if !defined(SWIGPYTHON)
2171  // Deprecated, sets pre_travel(i, j) = node_visit_transit[i]
2172  // and post_travel(i, j) = group_delays(i, j).
2173  void SetBreakIntervalsOfVehicle(
2174  std::vector<IntervalVar*> breaks, int vehicle,
2175  std::vector<int64> node_visit_transits,
2176  std::function<int64(int64, int64)> group_delays);
2177 
2178  // Returns the break intervals set by SetBreakIntervalsOfVehicle().
2179  const std::vector<IntervalVar*>& GetBreakIntervalsOfVehicle(
2180  int vehicle) const;
2181  // Returns the pairs (distance, duration) specified by break distance
2182  // constraints.
2183  // clang-format off
2184  const std::vector<std::pair<int64, int64> >&
2185  GetBreakDistanceDurationOfVehicle(int vehicle) const;
2186  // clang-format on
2187 #endif // !defined(SWIGPYTHON)
2188  int GetPreTravelEvaluatorOfVehicle(int vehicle) const;
2189  int GetPostTravelEvaluatorOfVehicle(int vehicle) const;
2190 
2191  // Returns the parent in the dependency tree if any or nullptr otherwise.
2192  const RoutingDimension* base_dimension() const { return base_dimension_; }
2193  // It makes sense to use the function only for self-dependent dimension.
2194  // For such dimensions the value of the slack of a node determines the
2195  // transition cost of the next transit. Provided that
2196  // 1. cumul[node] is fixed,
2197  // 2. next[node] and next[next[node]] (if exists) are fixed,
2198  // the value of slack[node] for which cumul[next[node]] + transit[next[node]]
2199  // is minimized can be found in O(1) using this function.
2200  int64 ShortestTransitionSlack(int64 node) const;
2201 
2202  // Returns the name of the dimension.
2203  const std::string& name() const { return name_; }
2204 
2205  // Accessors.
2206 #ifndef SWIG
2207  const ReverseArcListGraph<int, int>& GetPathPrecedenceGraph() const {
2208  return path_precedence_graph_;
2209  }
2210 #endif
2211 
2212  // Limits, in terms of maximum difference between the cumul variables, between
2213  // the pickup and delivery alternatives belonging to a single pickup/delivery
2214  // pair in the RoutingModel.
2215  // The indices passed to the function respectively correspond to the position
2216  // of the pickup in the vector of pickup alternatives, and delivery position
2217  // in the delivery alternatives for this pickup/delivery pair.
2218  // These limits should only be set when each node index appears in at most one
2219  // pickup/delivery pair, i.e. each pickup (delivery) index is in a single
2220  // pickup/delivery pair.first (pair.second).
2221  typedef std::function<int64(int, int)> PickupToDeliveryLimitFunction;
2222 
2223  void SetPickupToDeliveryLimitFunctionForPair(
2224  PickupToDeliveryLimitFunction limit_function, int pair_index);
2225 
2226  bool HasPickupToDeliveryLimits() const;
2227 #ifndef SWIG
2228  int64 GetPickupToDeliveryLimitForPair(int pair_index, int pickup,
2229  int delivery) const;
2230 
2232  int64 first_node;
2234  int64 offset;
2235  };
2236 
2237  void AddNodePrecedence(NodePrecedence precedence) {
2238  node_precedences_.push_back(precedence);
2239  }
2240  const std::vector<NodePrecedence>& GetNodePrecedences() const {
2241  return node_precedences_;
2242  }
2243 #endif // SWIG
2244 
2245  void AddNodePrecedence(int64 first_node, int64 second_node, int64 offset) {
2246  AddNodePrecedence({first_node, second_node, offset});
2247  }
2248 
2249  int64 GetSpanUpperBoundForVehicle(int vehicle) const {
2250  return vehicle_span_upper_bounds_[vehicle];
2251  }
2252 #ifndef SWIG
2253  const std::vector<int64>& vehicle_span_upper_bounds() const {
2254  return vehicle_span_upper_bounds_;
2255  }
2256 #endif // SWIG
2257  int64 GetSpanCostCoefficientForVehicle(int vehicle) const {
2258  return vehicle_span_cost_coefficients_[vehicle];
2259  }
2260 #ifndef SWIG
2261  const std::vector<int64>& vehicle_span_cost_coefficients() const {
2262  return vehicle_span_cost_coefficients_;
2263  }
2264 #endif // SWIG
2265  int64 global_span_cost_coefficient() const {
2266  return global_span_cost_coefficient_;
2267  }
2268 
2269  int64 GetGlobalOptimizerOffset() const {
2270  DCHECK_GE(global_optimizer_offset_, 0);
2271  return global_optimizer_offset_;
2272  }
2273  int64 GetLocalOptimizerOffsetForVehicle(int vehicle) const {
2274  if (vehicle >= local_optimizer_offset_for_vehicle_.size()) {
2275  return 0;
2276  }
2277  DCHECK_GE(local_optimizer_offset_for_vehicle_[vehicle], 0);
2278  return local_optimizer_offset_for_vehicle_[vehicle];
2279  }
2280 #if !defined SWIG
2281  // If the span of vehicle on this dimension is larger than bound,
2282  // the cost will be increased by cost * (span - bound).
2283  void SetSoftSpanUpperBoundForVehicle(SimpleBoundCosts::BoundCost bound_cost,
2284  int vehicle) {
2285  if (!HasSoftSpanUpperBounds()) {
2286  vehicle_soft_span_upper_bound_ = absl::make_unique<SimpleBoundCosts>(
2287  model_->vehicles(), SimpleBoundCosts::BoundCost{kint64max, 0});
2288  }
2289  vehicle_soft_span_upper_bound_->bound_cost(vehicle) = bound_cost;
2290  }
2291  bool HasSoftSpanUpperBounds() const {
2292  return vehicle_soft_span_upper_bound_ != nullptr;
2293  }
2294  SimpleBoundCosts::BoundCost GetSoftSpanUpperBoundForVehicle(
2295  int vehicle) const {
2296  DCHECK(HasSoftSpanUpperBounds());
2297  return vehicle_soft_span_upper_bound_->bound_cost(vehicle);
2298  }
2299 #endif // !defined SWIG
2300 
2301  private:
2302  struct SoftBound {
2303  IntVar* var;
2304  int64 bound;
2305  int64 coefficient;
2306  };
2307 
2308  struct PiecewiseLinearCost {
2309  PiecewiseLinearCost() : var(nullptr), cost(nullptr) {}
2310  IntVar* var;
2311  std::unique_ptr<PiecewiseLinearFunction> cost;
2312  };
2313 
2314  class SelfBased {};
2315  RoutingDimension(RoutingModel* model, std::vector<int64> vehicle_capacities,
2316  const std::string& name,
2317  const RoutingDimension* base_dimension);
2318  RoutingDimension(RoutingModel* model, std::vector<int64> vehicle_capacities,
2319  const std::string& name, SelfBased);
2320  void Initialize(const std::vector<int>& transit_evaluators,
2321  const std::vector<int>& state_dependent_transit_evaluators,
2322  int64 slack_max);
2323  void InitializeCumuls();
2324  void InitializeTransits(
2325  const std::vector<int>& transit_evaluators,
2326  const std::vector<int>& state_dependent_transit_evaluators,
2327  int64 slack_max);
2328  void InitializeTransitVariables(int64 slack_max);
2329  // Sets up the cost variables related to cumul soft upper bounds.
2330  void SetupCumulVarSoftUpperBoundCosts(
2331  std::vector<IntVar*>* cost_elements) const;
2332  // Sets up the cost variables related to cumul soft lower bounds.
2333  void SetupCumulVarSoftLowerBoundCosts(
2334  std::vector<IntVar*>* cost_elements) const;
2335  void SetupCumulVarPiecewiseLinearCosts(
2336  std::vector<IntVar*>* cost_elements) const;
2337  // Sets up the cost variables related to the global span and per-vehicle span
2338  // costs (only for the "slack" part of the latter).
2339  void SetupGlobalSpanCost(std::vector<IntVar*>* cost_elements) const;
2340  void SetupSlackAndDependentTransitCosts() const;
2341  // Finalize the model of the dimension.
2342  void CloseModel(bool use_light_propagation);
2343 
2344  void SetOffsetForGlobalOptimizer(int64 offset) {
2345  global_optimizer_offset_ = std::max(Zero(), offset);
2346  }
2347  // Moves elements of "offsets" into vehicle_offsets_for_local_optimizer_.
2348  void SetVehicleOffsetsForLocalOptimizer(std::vector<int64> offsets) {
2349  // Make sure all offsets are positive.
2350  std::transform(offsets.begin(), offsets.end(), offsets.begin(),
2351  [](int64 offset) { return std::max(Zero(), offset); });
2352  local_optimizer_offset_for_vehicle_ = std::move(offsets);
2353  }
2354 
2355  std::vector<IntVar*> cumuls_;
2356  std::vector<SortedDisjointIntervalList> forbidden_intervals_;
2357  std::vector<IntVar*> capacity_vars_;
2358  const std::vector<int64> vehicle_capacities_;
2359  std::vector<IntVar*> transits_;
2360  std::vector<IntVar*> fixed_transits_;
2361  // Values in class_evaluators_ correspond to the evaluators in
2362  // RoutingModel::transit_evaluators_ for each vehicle class.
2363  std::vector<int> class_evaluators_;
2364  std::vector<int64> vehicle_to_class_;
2365 #ifndef SWIG
2366  ReverseArcListGraph<int, int> path_precedence_graph_;
2367 #endif
2368  // For every {first_node, second_node, offset} element in node_precedences_,
2369  // if both first_node and second_node are performed, then cumuls_[second_node]
2370  // must be greater than (or equal to) cumuls_[first_node] + offset.
2371  std::vector<NodePrecedence> node_precedences_;
2372 
2373  // The transits of a dimension may depend on its cumuls or the cumuls of
2374  // another dimension. There can be no cycles, except for self loops, a typical
2375  // example for this is a time dimension.
2376  const RoutingDimension* const base_dimension_;
2377 
2378  // Values in state_dependent_class_evaluators_ correspond to the evaluators in
2379  // RoutingModel::state_dependent_transit_evaluators_ for each vehicle class.
2380  std::vector<int> state_dependent_class_evaluators_;
2381  std::vector<int64> state_dependent_vehicle_to_class_;
2382 
2383  // For each pickup/delivery pair_index for which limits have been set,
2384  // pickup_to_delivery_limits_per_pair_index_[pair_index] contains the
2385  // PickupToDeliveryLimitFunction for the pickup and deliveries in this pair.
2386  std::vector<PickupToDeliveryLimitFunction>
2387  pickup_to_delivery_limits_per_pair_index_;
2388 
2389  // Used if some vehicle has breaks in this dimension, typically time.
2390  bool break_constraints_are_initialized_ = false;
2391  // clang-format off
2392  std::vector<std::vector<IntervalVar*> > vehicle_break_intervals_;
2393  std::vector<std::vector<std::pair<int64, int64> > >
2394  vehicle_break_distance_duration_;
2395  // clang-format on
2396  // For each vehicle, stores the part of travel that is made directly
2397  // after (before) the departure (arrival) node of the travel.
2398  // These parts of the travel are non-interruptible, in particular by a break.
2399  std::vector<int> vehicle_pre_travel_evaluators_;
2400  std::vector<int> vehicle_post_travel_evaluators_;
2401 
2402  std::vector<IntVar*> slacks_;
2403  std::vector<IntVar*> dependent_transits_;
2404  std::vector<int64> vehicle_span_upper_bounds_;
2405  int64 global_span_cost_coefficient_;
2406  std::vector<int64> vehicle_span_cost_coefficients_;
2407  std::vector<SoftBound> cumul_var_soft_upper_bound_;
2408  std::vector<SoftBound> cumul_var_soft_lower_bound_;
2409  std::vector<PiecewiseLinearCost> cumul_var_piecewise_linear_cost_;
2410  RoutingModel* const model_;
2411  const std::string name_;
2412  int64 global_optimizer_offset_;
2413  std::vector<int64> local_optimizer_offset_for_vehicle_;
2414  // nullptr if not defined.
2415  std::unique_ptr<SimpleBoundCosts> vehicle_soft_span_upper_bound_;
2416  friend class RoutingModel;
2417  friend class RoutingModelInspector;
2418 
2419  DISALLOW_COPY_AND_ASSIGN(RoutingDimension);
2420 };
2421 
2422 #ifndef SWIG
2423 // Class to arrange indices by by their distance and their angles from the
2424 // depot. Used in the Sweep first solution heuristic.
2425 class SweepArranger {
2426  public:
2427  explicit SweepArranger(const std::vector<std::pair<int64, int64>>& points);
2428  virtual ~SweepArranger() {}
2429  void ArrangeIndices(std::vector<int64>* indices);
2430  void SetSectors(int sectors) { sectors_ = sectors; }
2431 
2432  private:
2433  std::vector<int> coordinates_;
2434  int sectors_;
2435 
2436  DISALLOW_COPY_AND_ASSIGN(SweepArranger);
2437 };
2438 #endif
2439 
2440 // A decision builder which tries to assign values to variables as close as
2441 // possible to target values first.
2442 DecisionBuilder* MakeSetValuesFromTargets(Solver* solver,
2443  std::vector<IntVar*> variables,
2444  std::vector<int64> targets);
2445 
2446 // Routing Search
2447 
2448 // Decision builders building a solution using local search filters to evaluate
2449 // its feasibility. This is very fast but can eventually fail when the solution
2450 // is restored if filters did not detect all infeasiblities.
2451 // More details:
2452 // Using local search filters to build a solution. The approach is pretty
2453 // straight-forward: have a general assignment storing the current solution,
2454 // build delta assigment representing possible extensions to the current
2455 // solution and validate them with filters.
2456 // The tricky bit comes from using the assignment and filter APIs in a way
2457 // which avoids the lazy creation of internal hash_maps between variables
2458 // and indices.
2459 
2460 // Generic filter-based decision builder applied to IntVars.
2461 // TODO(user): Eventually move this to the core CP solver library
2462 // when the code is mature enough.
2463 class IntVarFilteredDecisionBuilder : public DecisionBuilder {
2464  public:
2465  IntVarFilteredDecisionBuilder(Solver* solver,
2466  const std::vector<IntVar*>& vars,
2467  const std::vector<LocalSearchFilter*>& filters);
2468  ~IntVarFilteredDecisionBuilder() override {}
2469  Decision* Next(Solver* solver) override;
2470  // Virtual method to redefine to build a solution.
2471  virtual bool BuildSolution() = 0;
2472  // Returns statistics on search, number of decisions sent to filters, number
2473  // of decisions rejected by filters.
2474  int64 number_of_decisions() const { return number_of_decisions_; }
2475  int64 number_of_rejects() const { return number_of_rejects_; }
2476 
2477  protected:
2478  // Virtual method to initialize the solution.
2479  virtual bool InitializeSolution() { return true; }
2480  // Commits the modifications to the current solution if these modifications
2481  // are "filter-feasible", returns false otherwise; in any case discards
2482  // all modifications.
2483  bool Commit();
2484  // Returns true if the search must be stopped.
2485  virtual bool StopSearch() { return false; }
2486  // Modifies the current solution by setting the variable of index 'index' to
2487  // value 'value'.
2488  void SetValue(int64 index, int64 value) {
2489  if (!is_in_delta_[index]) {
2490  delta_->FastAdd(vars_[index])->SetValue(value);
2491  delta_indices_.push_back(index);
2492  is_in_delta_[index] = true;
2493  } else {
2494  delta_->SetValue(vars_[index], value);
2495  }
2496  }
2497  // Returns the value of the variable of index 'index' in the last committed
2498  // solution.
2499  int64 Value(int64 index) const {
2500  return assignment_->IntVarContainer().Element(index).Value();
2501  }
2502  // Returns true if the variable of index 'index' is in the current solution.
2503  bool Contains(int64 index) const {
2504  return assignment_->IntVarContainer().Element(index).Var() != nullptr;
2505  }
2506  // Returns the number of variables the decision builder is trying to
2507  // instantiate.
2508  int Size() const { return vars_.size(); }
2509  // Returns the variable of index 'index'.
2510  IntVar* Var(int64 index) const { return vars_[index]; }
2511 
2512  private:
2513  // Synchronizes filters with an assignment (the current solution).
2514  void SynchronizeFilters();
2515  // Checks if filters accept a given modification to the current solution
2516  // (represented by delta).
2517  bool FilterAccept();
2518 
2519  const std::vector<IntVar*> vars_;
2520  Assignment* const assignment_;
2521  Assignment* const delta_;
2522  std::vector<int> delta_indices_;
2523  std::vector<bool> is_in_delta_;
2524  Assignment* const empty_;
2525  LocalSearchFilterManager filter_manager_;
2526  // Stats on search
2527  int64 number_of_decisions_;
2528  int64 number_of_rejects_;
2529 };
2530 
2531 // Filter-based decision builder dedicated to routing.
2532 class RoutingFilteredDecisionBuilder : public IntVarFilteredDecisionBuilder {
2533  public:
2534  RoutingFilteredDecisionBuilder(
2535  RoutingModel* model, const std::vector<LocalSearchFilter*>& filters);
2536  ~RoutingFilteredDecisionBuilder() override {}
2537  RoutingModel* model() const { return model_; }
2538  // Returns the end of the start chain of vehicle,
2539  int GetStartChainEnd(int vehicle) const { return start_chain_ends_[vehicle]; }
2540  // Returns the start of the end chain of vehicle,
2541  int GetEndChainStart(int vehicle) const { return end_chain_starts_[vehicle]; }
2542  // Make nodes in the same disjunction as 'node' unperformed. 'node' is a
2543  // variable index corresponding to a node.
2544  void MakeDisjunctionNodesUnperformed(int64 node);
2545  // Make all unassigned nodes unperformed.
2546  void MakeUnassignedNodesUnperformed();
2547 
2548  protected:
2549  bool StopSearch() override { return model_->CheckLimit(); }
2550 
2551  private:
2552  // Initializes the current solution with empty or partial vehicle routes.
2553  bool InitializeSolution() override;
2554 
2555  RoutingModel* const model_;
2556  std::vector<int64> start_chain_ends_;
2557  std::vector<int64> end_chain_starts_;
2558 };
2559 
2560 class CheapestInsertionFilteredDecisionBuilder
2561  : public RoutingFilteredDecisionBuilder {
2562  public:
2563  // Takes ownership of evaluator.
2564  CheapestInsertionFilteredDecisionBuilder(
2565  RoutingModel* model, std::function<int64(int64, int64, int64)> evaluator,
2566  std::function<int64(int64)> penalty_evaluator,
2567  const std::vector<LocalSearchFilter*>& filters);
2568  ~CheapestInsertionFilteredDecisionBuilder() override {}
2569 
2570  protected:
2571  typedef std::pair<int64, int64> ValuedPosition;
2572  struct StartEndValue {
2573  int64 distance;
2574  int vehicle;
2575 
2576  bool operator<(const StartEndValue& other) const {
2577  return std::tie(distance, vehicle) <
2578  std::tie(other.distance, other.vehicle);
2579  }
2580  };
2581  typedef std::pair<StartEndValue, /*seed_node*/ int> Seed;
2582 
2583  // Computes and returns the distance of each uninserted node to every vehicle
2584  // in "vehicles" as a std::vector<std::vector<StartEndValue>>,
2585  // start_end_distances_per_node.
2586  // For each node, start_end_distances_per_node[node] is sorted in decreasing
2587  // order.
2588  // clang-format off
2589  std::vector<std::vector<StartEndValue> >
2590  ComputeStartEndDistanceForVehicles(const std::vector<int>& vehicles);
2591 
2592  // Initializes the priority_queue by inserting the best entry corresponding
2593  // to each node, i.e. the last element of start_end_distances_per_node[node],
2594  // which is supposed to be sorted in decreasing order.
2595  // Queue is a priority queue containing Seeds.
2596  template <class Queue>
2597  void InitializePriorityQueue(
2598  std::vector<std::vector<StartEndValue> >* start_end_distances_per_node,
2599  Queue* priority_queue);
2600  // clang-format on
2601 
2602  // Inserts 'node' just after 'predecessor', and just before 'successor',
2603  // resulting in the following subsequence: predecessor -> node -> successor.
2604  // If 'node' is part of a disjunction, other nodes of the disjunction are made
2605  // unperformed.
2606  void InsertBetween(int64 node, int64 predecessor, int64 successor);
2607  // Helper method to the ComputeEvaluatorSortedPositions* methods. Finds all
2608  // possible insertion positions of node 'node_to_insert' in the partial route
2609  // starting at node 'start' and adds them to 'valued_position', a list of
2610  // unsorted pairs of (cost, position to insert the node).
2611  void AppendEvaluatedPositionsAfter(
2612  int64 node_to_insert, int64 start, int64 next_after_start, int64 vehicle,
2613  std::vector<ValuedPosition>* valued_positions);
2614  // Returns the cost of unperforming node 'node_to_insert'. Returns kint64max
2615  // if penalty callback is null or if the node cannot be unperformed.
2616  int64 GetUnperformedValue(int64 node_to_insert) const;
2617 
2618  std::function<int64(int64, int64, int64)> evaluator_;
2619  std::function<int64(int64)> penalty_evaluator_;
2620 };
2621 
2622 // Filter-based decision builder which builds a solution by inserting
2623 // nodes at their cheapest position on any route; potentially several routes can
2624 // be built in parallel. The cost of a position is computed from an arc-based
2625 // cost callback. The node selected for insertion is the one which minimizes
2626 // insertion cost. If a non null penalty evaluator is passed, making nodes
2627 // unperformed is also taken into account with the corresponding penalty cost.
2628 class GlobalCheapestInsertionFilteredDecisionBuilder
2629  : public CheapestInsertionFilteredDecisionBuilder {
2630  public:
2631  // Takes ownership of evaluators.
2632  GlobalCheapestInsertionFilteredDecisionBuilder(
2633  RoutingModel* model, std::function<int64(int64, int64, int64)> evaluator,
2634  std::function<int64(int64)> penalty_evaluator,
2635  const std::vector<LocalSearchFilter*>& filters, bool is_sequential,
2636  double farthest_seeds_ratio, double neighbors_ratio);
2637  ~GlobalCheapestInsertionFilteredDecisionBuilder() override {}
2638  bool BuildSolution() override;
2639  std::string DebugString() const override {
2640  return "GlobalCheapestInsertionFilteredDecisionBuilder";
2641  }
2642 
2643  private:
2644  class PairEntry;
2645  class NodeEntry;
2646  typedef absl::flat_hash_set<PairEntry*> PairEntries;
2647  typedef absl::flat_hash_set<NodeEntry*> NodeEntries;
2648 
2649  // Inserts all non-inserted pickup and delivery pairs. Maintains a priority
2650  // queue of possible pair insertions, which is incrementally updated when a
2651  // pair insertion is committed. Incrementality is obtained by updating pair
2652  // insertion positions on the four newly modified route arcs: after the pickup
2653  // insertion position, after the pickup position, after the delivery insertion
2654  // position and after the delivery position.
2655  void InsertPairs();
2656 
2657  // Inserts non-inserted individual nodes on the given routes (or all routes if
2658  // "vehicles" is an empty vector), by constructing routes in parallel.
2659  // Maintains a priority queue of possible insertions, which is incrementally
2660  // updated when an insertion is committed.
2661  // Incrementality is obtained by updating insertion positions on the two newly
2662  // modified route arcs: after the node insertion position and after the node
2663  // position.
2664  void InsertNodesOnRoutes(const std::vector<int>& nodes,
2665  const std::vector<int>& vehicles);
2666 
2667  // Inserts non-inserted individual nodes on routes by constructing routes
2668  // sequentially.
2669  // For each new route, the vehicle to use and the first node to insert on it
2670  // are given by calling InsertSeedNode(). The route is then completed with
2671  // other nodes by calling InsertNodesOnRoutes({vehicle}).
2672  void SequentialInsertNodes(const std::vector<int>& nodes);
2673 
2674  // Goes through all vehicles in the model to check if they are already used
2675  // (i.e. Value(start) != end) or not.
2676  // Updates the three passed vectors accordingly.
2677  void DetectUsedVehicles(std::vector<bool>* is_vehicle_used,
2678  std::vector<int>* used_vehicles,
2679  std::vector<int>* unused_vehicles);
2680 
2681  // Inserts the (farthest_seeds_ratio_ * model()->vehicles()) nodes farthest
2682  // from the start/ends of the available vehicle routes as seeds on their
2683  // closest route.
2684  void InsertFarthestNodesAsSeeds();
2685 
2686  // Inserts a "seed node" based on the given priority_queue of Seeds.
2687  // A "seed" is the node used in order to start a new route.
2688  // If the Seed at the top of the priority queue cannot be inserted,
2689  // (node already inserted in the model, corresponding vehicle already used, or
2690  // unsuccessful Commit()), start_end_distances_per_node is updated and used
2691  // to insert a new entry for that node if necessary (next best vehicle).
2692  // If a seed node is successfully inserted, updates is_vehicle_used and
2693  // returns the vehice of the corresponding route. Returns -1 otherwise.
2694  template <class Queue>
2695  int InsertSeedNode(
2696  std::vector<std::vector<StartEndValue>>* start_end_distances_per_node,
2697  Queue* priority_queue, std::vector<bool>* is_vehicle_used);
2698  // clang-format on
2699 
2700  // Initializes the priority queue and the pair entries with the current state
2701  // of the solution.
2702  void InitializePairPositions(
2703  AdjustablePriorityQueue<PairEntry>* priority_queue,
2704  std::vector<PairEntries>* pickup_to_entries,
2705  std::vector<PairEntries>* delivery_to_entries);
2706  // Updates all pair entries inserting a node after node "insert_after" and
2707  // updates the priority queue accordingly.
2708  void UpdatePairPositions(int vehicle, int64 insert_after,
2709  AdjustablePriorityQueue<PairEntry>* priority_queue,
2710  std::vector<PairEntries>* pickup_to_entries,
2711  std::vector<PairEntries>* delivery_to_entries) {
2712  UpdatePickupPositions(vehicle, insert_after, priority_queue,
2713  pickup_to_entries, delivery_to_entries);
2714  UpdateDeliveryPositions(vehicle, insert_after, priority_queue,
2715  pickup_to_entries, delivery_to_entries);
2716  }
2717  // Updates all pair entries inserting their pickup node after node
2718  // "insert_after" and updates the priority queue accordingly.
2719  void UpdatePickupPositions(int vehicle, int64 pickup_insert_after,
2720  AdjustablePriorityQueue<PairEntry>* priority_queue,
2721  std::vector<PairEntries>* pickup_to_entries,
2722  std::vector<PairEntries>* delivery_to_entries);
2723  // Updates all pair entries inserting their delivery node after node
2724  // "insert_after" and updates the priority queue accordingly.
2725  void UpdateDeliveryPositions(
2726  int vehicle, int64 delivery_insert_after,
2727  AdjustablePriorityQueue<PairEntry>* priority_queue,
2728  std::vector<PairEntries>* pickup_to_entries,
2729  std::vector<PairEntries>* delivery_to_entries);
2730  // Deletes an entry, removing it from the priority queue and the appropriate
2731  // pickup and delivery entry sets.
2732  void DeletePairEntry(PairEntry* entry,
2733  AdjustablePriorityQueue<PairEntry>* priority_queue,
2734  std::vector<PairEntries>* pickup_to_entries,
2735  std::vector<PairEntries>* delivery_to_entries);
2736  // Initializes the priority queue and the node entries with the current state
2737  // of the solution on the given vehicle routes.
2738  void InitializePositions(const std::vector<int>& nodes,
2739  AdjustablePriorityQueue<NodeEntry>* priority_queue,
2740  std::vector<NodeEntries>* position_to_node_entries,
2741  const std::vector<int>& vehicles);
2742  // Updates all node entries inserting a node after node "insert_after" and
2743  // updates the priority queue accordingly.
2744  void UpdatePositions(const std::vector<int>& nodes, int vehicle,
2745  int64 insert_after,
2746  AdjustablePriorityQueue<NodeEntry>* priority_queue,
2747  std::vector<NodeEntries>* node_entries);
2748  // Deletes an entry, removing it from the priority queue and the appropriate
2749  // node entry sets.
2750  void DeleteNodeEntry(NodeEntry* entry,
2751  AdjustablePriorityQueue<NodeEntry>* priority_queue,
2752  std::vector<NodeEntries>* node_entries);
2753 
2754  // Inserts neighbor_index in
2755  // node_index_to_[pickup|delivery|single]_neighbors_per_cost_class_
2756  // [node_index][cost_class] according to whether neighbor is a pickup,
2757  // a delivery, or neither.
2758  void AddNeighborForCostClass(int cost_class, int64 node_index,
2759  int64 neighbor_index, bool neighbor_is_pickup,
2760  bool neighbor_is_delivery);
2761 
2762  // Returns true iff neighbor_index is in node_index's neighbors list
2763  // corresponding to neighbor_is_pickup and neighbor_is_delivery.
2764  bool IsNeighborForCostClass(int cost_class, int64 node_index,
2765  int64 neighbor_index) const;
2766 
2767  // Returns a reference to the set of pickup neighbors of node_index.
2768  const absl::flat_hash_set<int64>& GetPickupNeighborsOfNodeForCostClass(
2769  int cost_class, int64 node_index) {
2770  if (neighbors_ratio_ == 1) {
2771  return pickup_nodes_;
2772  }
2773  return node_index_to_pickup_neighbors_by_cost_class_[node_index]
2774  [cost_class];
2775  }
2776 
2777  // Same as above for delivery neighbors.
2778  const absl::flat_hash_set<int64>& GetDeliveryNeighborsOfNodeForCostClass(
2779  int cost_class, int64 node_index) {
2780  if (neighbors_ratio_ == 1) {
2781  return delivery_nodes_;
2782  }
2783  return node_index_to_delivery_neighbors_by_cost_class_[node_index]
2784  [cost_class];
2785  }
2786 
2787  const bool is_sequential_;
2788  const double farthest_seeds_ratio_;
2789  const double neighbors_ratio_;
2790 
2791  // clang-format off
2792  std::vector<std::vector<absl::flat_hash_set<int64> > >
2793  node_index_to_single_neighbors_by_cost_class_;
2794  std::vector<std::vector<absl::flat_hash_set<int64> > >
2795  node_index_to_pickup_neighbors_by_cost_class_;
2796  std::vector<std::vector<absl::flat_hash_set<int64> > >
2797  node_index_to_delivery_neighbors_by_cost_class_;
2798  // clang-format on
2799 
2800  // When neighbors_ratio is 1, we don't compute the neighborhood members above,
2801  // and use the following sets in the code to avoid unnecessary computations
2802  // and decrease the time and space complexities.
2803  absl::flat_hash_set<int64> pickup_nodes_;
2804  absl::flat_hash_set<int64> delivery_nodes_;
2805 };
2806 
2807 // Filter-base decision builder which builds a solution by inserting
2808 // nodes at their cheapest position. The cost of a position is computed
2809 // an arc-based cost callback. Node selected for insertion are considered in
2810 // decreasing order of distance to the start/ends of the routes, i.e. farthest
2811 // nodes are inserted first.
2812 class LocalCheapestInsertionFilteredDecisionBuilder
2813  : public CheapestInsertionFilteredDecisionBuilder {
2814  public:
2815  // Takes ownership of evaluator.
2816  LocalCheapestInsertionFilteredDecisionBuilder(
2817  RoutingModel* model, std::function<int64(int64, int64, int64)> evaluator,
2818  const std::vector<LocalSearchFilter*>& filters);
2819  ~LocalCheapestInsertionFilteredDecisionBuilder() override {}
2820  bool BuildSolution() override;
2821  std::string DebugString() const override {
2822  return "LocalCheapestInsertionFilteredDecisionBuilder";
2823  }
2824 
2825  private:
2826  // Computes the possible insertion positions of 'node' and sorts them
2827  // according to the current cost evaluator.
2828  // 'node' is a variable index corresponding to a node, 'sorted_positions' is a
2829  // vector of variable indices corresponding to nodes after which 'node' can be
2830  // inserted.
2831  void ComputeEvaluatorSortedPositions(int64 node,
2832  std::vector<int64>* sorted_positions);
2833  // Like ComputeEvaluatorSortedPositions, subject to the additional
2834  // restrictions that the node may only be inserted after node 'start' on the
2835  // route. For convenience, this method also needs the node that is right after
2836  // 'start' on the route.
2837  void ComputeEvaluatorSortedPositionsOnRouteAfter(
2838  int64 node, int64 start, int64 next_after_start,
2839  std::vector<int64>* sorted_positions);
2840 };
2841 
2842 // Filtered-base decision builder based on the addition heuristic, extending
2843 // a path from its start node with the cheapest arc.
2844 class CheapestAdditionFilteredDecisionBuilder
2845  : public RoutingFilteredDecisionBuilder {
2846  public:
2847  CheapestAdditionFilteredDecisionBuilder(
2848  RoutingModel* model, const std::vector<LocalSearchFilter*>& filters);
2849  ~CheapestAdditionFilteredDecisionBuilder() override {}
2850  bool BuildSolution() override;
2851 
2852  private:
2853  class PartialRoutesAndLargeVehicleIndicesFirst {
2854  public:
2855  explicit PartialRoutesAndLargeVehicleIndicesFirst(
2856  const CheapestAdditionFilteredDecisionBuilder& builder)
2857  : builder_(builder) {}
2858  bool operator()(int vehicle1, int vehicle2) const;
2859 
2860  private:
2861  const CheapestAdditionFilteredDecisionBuilder& builder_;
2862  };
2863  // Returns a vector of possible next indices of node from an iterator.
2864  template <typename Iterator>
2865  std::vector<int64> GetPossibleNextsFromIterator(int64 node, Iterator start,
2866  Iterator end) const {
2867  const int size = model()->Size();
2868  std::vector<int64> nexts;
2869  for (Iterator it = start; it != end; ++it) {
2870  const int64 next = *it;
2871  if (next != node && (next >= size || !Contains(next))) {
2872  nexts.push_back(next);
2873  }
2874  }
2875  return nexts;
2876  }
2877  // Sorts a vector of successors of node.
2878  virtual void SortSuccessors(int64 node, std::vector<int64>* successors) = 0;
2879  virtual int64 FindTopSuccessor(int64 node,
2880  const std::vector<int64>& successors) = 0;
2881 };
2882 
2883 // A CheapestAdditionFilteredDecisionBuilder where the notion of 'cheapest arc'
2884 // comes from an arc evaluator.
2885 class EvaluatorCheapestAdditionFilteredDecisionBuilder
2886  : public CheapestAdditionFilteredDecisionBuilder {
2887  public:
2888  // Takes ownership of evaluator.
2889  EvaluatorCheapestAdditionFilteredDecisionBuilder(
2890  RoutingModel* model, std::function<int64(int64, int64)> evaluator,
2891  const std::vector<LocalSearchFilter*>& filters);
2892  ~EvaluatorCheapestAdditionFilteredDecisionBuilder() override {}
2893  std::string DebugString() const override {
2894  return "EvaluatorCheapestAdditionFilteredDecisionBuilder";
2895  }
2896 
2897  private:
2898  // Next nodes are sorted according to the current evaluator.
2899  void SortSuccessors(int64 node, std::vector<int64>* successors) override;
2900  int64 FindTopSuccessor(int64 node,
2901  const std::vector<int64>& successors) override;
2902 
2903  std::function<int64(int64, int64)> evaluator_;
2904 };
2905 
2906 // A CheapestAdditionFilteredDecisionBuilder where the notion of 'cheapest arc'
2907 // comes from an arc comparator.
2908 class ComparatorCheapestAdditionFilteredDecisionBuilder
2909  : public CheapestAdditionFilteredDecisionBuilder {
2910  public:
2911  // Takes ownership of evaluator.
2912  ComparatorCheapestAdditionFilteredDecisionBuilder(
2913  RoutingModel* model, Solver::VariableValueComparator comparator,
2914  const std::vector<LocalSearchFilter*>& filters);
2915  ~ComparatorCheapestAdditionFilteredDecisionBuilder() override {}
2916  std::string DebugString() const override {
2917  return "ComparatorCheapestAdditionFilteredDecisionBuilder";
2918  }
2919 
2920  private:
2921  // Next nodes are sorted according to the current comparator.
2922  void SortSuccessors(int64 node, std::vector<int64>* successors) override;
2923  int64 FindTopSuccessor(int64 node,
2924  const std::vector<int64>& successors) override;
2925 
2926  Solver::VariableValueComparator comparator_;
2927 };
2928 
2929 // Filter-based decision builder which builds a solution by using
2930 // Clarke & Wright's Savings heuristic. For each pair of nodes, the savings
2931 // value is the difference between the cost of two routes visiting one node each
2932 // and one route visiting both nodes. Routes are built sequentially, each route
2933 // being initialized from the pair with the best avalaible savings value then
2934 // extended by selecting the nodes with best savings on both ends of the partial
2935 // route.
2936 // Cost is based on the arc cost function of the routing model and cost classes
2937 // are taken into account.
2938 class SavingsFilteredDecisionBuilder : public RoutingFilteredDecisionBuilder {
2939  public:
2941  // If neighbors_ratio < 1 then for each node only this ratio of its
2942  // neighbors leading to the smallest arc costs are considered.
2943  double neighbors_ratio = 1.0;
2944  // The number of neighbors considered for each node is also adapted so that
2945  // the stored Savings don't use up more than max_memory_usage_bytes bytes.
2946  double max_memory_usage_bytes = 6e9;
2947  // If add_reverse_arcs is true, the neighborhood relationships are
2948  // considered symmetrically.
2949  bool add_reverse_arcs = false;
2950  // arc_coefficient is a strictly positive parameter indicating the
2951  // coefficient of the arc being considered in the Saving formula.
2952  double arc_coefficient = 1.0;
2953  };
2954 
2955  SavingsFilteredDecisionBuilder(
2956  RoutingModel* model, RoutingIndexManager* manager,
2957  SavingsParameters parameters,
2958  const std::vector<LocalSearchFilter*>& filters);
2959  ~SavingsFilteredDecisionBuilder() override;
2960  bool BuildSolution() override;
2961 
2962  protected:
2963  typedef std::pair</*saving*/ int64, /*saving index*/ int64> Saving;
2964 
2965  template <typename S>
2967 
2970  int64 fixed_cost;
2971 
2972  bool operator<(const VehicleClassEntry& other) const {
2973  return std::tie(fixed_cost, vehicle_class) <
2974  std::tie(other.fixed_cost, other.vehicle_class);
2975  }
2976  };
2977 
2978  virtual double ExtraSavingsMemoryMultiplicativeFactor() const = 0;
2979 
2980  virtual void BuildRoutesFromSavings() = 0;
2981 
2982  // Returns the cost class from a saving.
2983  int64 GetVehicleTypeFromSaving(const Saving& saving) const {
2984  return saving.second / size_squared_;
2985  }
2986  // Returns the "before node" from a saving.
2987  int64 GetBeforeNodeFromSaving(const Saving& saving) const {
2988  return (saving.second % size_squared_) / Size();
2989  }
2990  // Returns the "after node" from a saving.
2991  int64 GetAfterNodeFromSaving(const Saving& saving) const {
2992  return (saving.second % size_squared_) % Size();
2993  }
2994  // Returns the saving value from a saving.
2995  int64 GetSavingValue(const Saving& saving) const { return saving.first; }
2996 
2997  // Finds the best available vehicle of type "type" to start a new route to
2998  // serve the arc before_node-->after_node.
2999  // Since there are different vehicle classes for each vehicle type, each
3000  // vehicle class having its own capacity constraints, we go through all
3001  // vehicle types (in each case only studying the first available vehicle) to
3002  // make sure this Saving is inserted if possible.
3003  // If possible, the arc is committed to the best vehicle, and the vehicle
3004  // index is returned. If this arc can't be served by any vehicle of this type,
3005  // the function returns -1.
3006  int StartNewRouteWithBestVehicleOfType(int type, int64 before_node,
3007  int64 after_node);
3008 
3009  std::vector<int> type_index_of_vehicle_;
3010  // clang-format off
3011  std::vector<std::set<VehicleClassEntry> > sorted_vehicle_classes_per_type_;
3012  std::vector<std::deque<int> > vehicles_per_vehicle_class_;
3013  std::unique_ptr<SavingsContainer<Saving> > savings_container_;
3014  // clang-format on
3015 
3016  private:
3017  // Used when add_reverse_arcs_ is true.
3018  // Given the vector of adjacency lists of a graph, adds symetric arcs not
3019  // already in the graph to the adjacencies (i.e. if n1-->n2 is present and not
3020  // n2-->n1, then n1 is added to adjacency_matrix[n2].
3021  // clang-format off
3022  void AddSymetricArcsToAdjacencyLists(
3023  std::vector<std::vector<int64> >* adjacency_lists);
3024  // clang-format on
3025 
3026  // Computes saving values for node pairs (see MaxNumNeighborsPerNode()) and
3027  // all vehicle types (see ComputeVehicleTypes()).
3028  // The saving index attached to each saving value is an index used to
3029  // store and recover the node pair to which the value is linked (cf. the
3030  // index conversion methods below).
3031  // The computed savings are stored and sorted using the savings_container_.
3032  void ComputeSavings();
3033  // Builds a saving from a saving value, a vehicle type and two nodes.
3034  Saving BuildSaving(int64 saving, int vehicle_type, int before_node,
3035  int after_node) const {
3036  return std::make_pair(saving, vehicle_type * size_squared_ +
3037  before_node * Size() + after_node);
3038  }
3039 
3040  // Computes the vehicle type of every vehicle and stores it in
3041  // type_index_of_vehicle_. A "vehicle type" consists of the set of vehicles
3042  // having the same cost class and start/end nodes, therefore the same savings
3043  // value for each arc.
3044  // The vehicle classes corresponding to each vehicle type index are stored and
3045  // sorted by fixed cost in sorted_vehicle_classes_per_type_, and the vehicles
3046  // for each vehicle class are stored in vehicles_per_vehicle_class_.
3047  void ComputeVehicleTypes();
3048 
3049  // Computes and returns the maximum number of (closest) neighbors to consider
3050  // for each node when computing Savings, based on the neighbors ratio and max
3051  // memory usage specified by the savings_params_.
3052  int64 MaxNumNeighborsPerNode(int num_vehicle_types) const;
3053 
3054  RoutingIndexManager* const manager_;
3055  const SavingsParameters savings_params_;
3056  int64 size_squared_;
3057 
3058  friend class SavingsFilteredDecisionBuilderTestPeer;
3059 };
3060 
3061 class SequentialSavingsFilteredDecisionBuilder
3062  : public SavingsFilteredDecisionBuilder {
3063  public:
3064  SequentialSavingsFilteredDecisionBuilder(
3065  RoutingModel* model, RoutingIndexManager* manager,
3066  SavingsParameters parameters,
3067  const std::vector<LocalSearchFilter*>& filters)
3068  : SavingsFilteredDecisionBuilder(model, manager, parameters, filters) {}
3069  ~SequentialSavingsFilteredDecisionBuilder() override{};
3070  std::string DebugString() const override {
3071  return "SequentialSavingsFilteredDecisionBuilder";
3072  }
3073 
3074  private:
3075  // Builds routes sequentially.
3076  // Once a Saving is used to start a new route, we extend this route as much as
3077  // possible from both ends by gradually inserting the best Saving at either
3078  // end of the route.
3079  void BuildRoutesFromSavings() override;
3080  double ExtraSavingsMemoryMultiplicativeFactor() const override { return 1.0; }
3081 };
3082 
3083 class ParallelSavingsFilteredDecisionBuilder
3084  : public SavingsFilteredDecisionBuilder {
3085  public:
3086  ParallelSavingsFilteredDecisionBuilder(
3087  RoutingModel* model, RoutingIndexManager* manager,
3088  SavingsParameters parameters,
3089  const std::vector<LocalSearchFilter*>& filters)
3090  : SavingsFilteredDecisionBuilder(model, manager, parameters, filters) {}
3091  ~ParallelSavingsFilteredDecisionBuilder() override{};
3092  std::string DebugString() const override {
3093  return "ParallelSavingsFilteredDecisionBuilder";
3094  }
3095 
3096  private:
3097  // Goes through the ordered computed Savings to build routes in parallel.
3098  // Given a Saving for a before-->after arc :
3099  // -- If both before and after are uncontained, we start a new route.
3100  // -- If only before is served and is the last node on its route, we try
3101  // adding after at the end of the route.
3102  // -- If only after is served and is first on its route, we try adding before
3103  // as first node on this route.
3104  // -- If both nodes are contained and are respectively the last and first
3105  // nodes on their (different) routes, we merge the routes of the two nodes
3106  // into one if possible.
3107  void BuildRoutesFromSavings() override;
3108 
3109  double ExtraSavingsMemoryMultiplicativeFactor() const override { return 2.0; }
3110 
3111  // Merges the routes of first_vehicle and second_vehicle onto the vehicle with
3112  // lower fixed cost. The routes respectively end at before_node and start at
3113  // after_node, and are merged into one by adding the arc
3114  // before_node-->after_node.
3115  void MergeRoutes(int first_vehicle, int second_vehicle, int64 before_node,
3116  int64 after_node);
3117 
3118  // First and last non start/end nodes served by each vehicle.
3119  std::vector<int64> first_node_on_route_;
3120  std::vector<int64> last_node_on_route_;
3121  // For each first/last node served by a vehicle (besides start/end nodes of
3122  // vehicle), this vector contains the index of the vehicle serving them.
3123  // For other (intermediary) nodes, contains -1.
3124  std::vector<int> vehicle_of_first_or_last_node_;
3125 };
3126 
3127 // Christofides addition heuristic. Initially created to solve TSPs, extended to
3128 // support any model by extending routes as much as possible following the path
3129 // found by the heuristic, before starting a new route.
3130 
3131 class ChristofidesFilteredDecisionBuilder
3132  : public RoutingFilteredDecisionBuilder {
3133  public:
3134  ChristofidesFilteredDecisionBuilder(
3135  RoutingModel* model, const std::vector<LocalSearchFilter*>& filters);
3136  ~ChristofidesFilteredDecisionBuilder() override {}
3137  bool BuildSolution() override;
3138  std::string DebugString() const override {
3139  return "ChristofidesFilteredDecisionBuilder";
3140  }
3141 };
3142 
3143 // Attempts to solve the model using the cp-sat solver. As of 5/2019, will solve
3144 // the TSP corresponding to the model if it has a single vehicle. Therefore the
3145 // resulting solution might not actually be feasible. Will return false if a
3146 // solution could not be found.
3147 bool SolveModelWithSat(RoutingModel* model, Assignment* solution);
3148 
3149 // Generic path-based filter class.
3150 
3151 class BasePathFilter : public IntVarLocalSearchFilter {
3152  public:
3153  BasePathFilter(const std::vector<IntVar*>& nexts, int next_domain_size,
3154  std::function<void(int64)> objective_callback);
3155  ~BasePathFilter() override {}
3156  bool Accept(Assignment* delta, Assignment* deltadelta) override;
3157  void OnSynchronize(const Assignment* delta) override;
3158 
3159  protected:
3160  static const int64 kUnassigned;
3161 
3162  int64 GetNext(int64 node) const {
3163  return (new_nexts_[node] == kUnassigned)
3164  ? (IsVarSynced(node) ? Value(node) : kUnassigned)
3165  : new_nexts_[node];
3166  }
3167  int NumPaths() const { return starts_.size(); }
3168  int64 Start(int i) const { return starts_[i]; }
3169  int GetPath(int64 node) const { return paths_[node]; }
3170  int Rank(int64 node) const { return ranks_[node]; }
3171  bool IsDisabled() const { return status_ == DISABLED; }
3172  const std::vector<int64>& GetNewSynchronizedUnperformedNodes() const {
3173  return new_synchronized_unperformed_nodes_.PositionsSetAtLeastOnce();
3174  }
3175 
3176  private:
3177  enum Status { UNKNOWN, ENABLED, DISABLED };
3178 
3179  virtual bool DisableFiltering() const { return false; }
3180  virtual void OnBeforeSynchronizePaths() {}
3181  virtual void OnAfterSynchronizePaths() {}
3182  virtual void OnSynchronizePathFromStart(int64 start) {}
3183  virtual void InitializeAcceptPath() {}
3184  virtual bool AcceptPath(int64 path_start, int64 chain_start,
3185  int64 chain_end) = 0;
3186  virtual bool FinalizeAcceptPath(Assignment* delta) { return true; }
3187  // Detects path starts, used to track which node belongs to which path.
3188  void ComputePathStarts(std::vector<int64>* path_starts,
3189  std::vector<int>* index_to_path);
3190  bool HavePathsChanged();
3191  void SynchronizeFullAssignment();
3192  void UpdateAllRanks();
3193  void UpdatePathRanksFromStart(int start);
3194 
3195  std::vector<int64> node_path_starts_;
3196  std::vector<int64> starts_;
3197  std::vector<int> paths_;
3198  SparseBitset<int64> new_synchronized_unperformed_nodes_;
3199  std::vector<int64> new_nexts_;
3200  std::vector<int> delta_touched_;
3201  SparseBitset<> touched_paths_;
3202  SparseBitset<> touched_path_nodes_;
3203  std::vector<int> ranks_;
3204 
3205  Status status_;
3206 };
3207 
3208 // This filter accepts deltas for which the assignment satisfies the constraints
3209 // of the Solver. This is verified by keeping an internal copy of the assignment
3210 // with all Next vars and their updated values, and calling RestoreAssignment()
3211 // on the assignment+delta.
3212 // TODO(user): Also call the solution finalizer on variables, with the
3213 // exception of Next Vars (woud fail on large instances).
3214 // WARNING: In the case of mandatory nodes, when all vehicles are currently
3215 // being used in the solution but uninserted nodes still remain, this filter
3216 // will reject the solution, even if the node could be inserted on one of these
3217 // routes, because all Next vars of vehicle starts are already instantiated.
3218 // TODO(user): Avoid such false negatives.
3219 class CPFeasibilityFilter : public IntVarLocalSearchFilter {
3220  public:
3221  explicit CPFeasibilityFilter(const RoutingModel* routing_model);
3222  ~CPFeasibilityFilter() override {}
3223  std::string DebugString() const override { return "CPFeasibilityFilter"; }
3224  bool Accept(Assignment* delta, Assignment* deltadelta) override;
3225  void OnSynchronize(const Assignment* delta) override;
3226 
3227  private:
3228  void AddDeltaToAssignment(const Assignment* delta, Assignment* assignment);
3229 
3230  static const int64 kUnassigned;
3231  const RoutingModel* const model_;
3232  Solver* const solver_;
3233  Assignment* const assignment_;
3234  Assignment* const temp_assignment_;
3235  DecisionBuilder* const restore_;
3236 };
3237 
3238 #if !defined(SWIG)
3239 IntVarLocalSearchFilter* MakeNodeDisjunctionFilter(
3240  const RoutingModel& routing_model,
3241  std::function<void(int64)> objective_callback);
3242 IntVarLocalSearchFilter* MakeVehicleAmortizedCostFilter(
3243  const RoutingModel& routing_model,
3244  Solver::ObjectiveWatcher objective_callback);
3245 IntVarLocalSearchFilter* MakeTypeRegulationsFilter(
3246  const RoutingModel& routing_model);
3247 std::vector<IntVarLocalSearchFilter*> MakeCumulFilters(
3248  const RoutingDimension& dimension,
3249  Solver::ObjectiveWatcher objective_callback, bool filter_objective_cost);
3250 IntVarLocalSearchFilter* MakePathCumulFilter(
3251  const RoutingDimension& dimension,
3252  Solver::ObjectiveWatcher objective_callback,
3253  bool propagate_own_objective_value, bool filter_objective_cost);
3254 IntVarLocalSearchFilter* MakeGlobalLPCumulFilter(
3255  const RoutingDimension& dimension,
3256  Solver::ObjectiveWatcher objective_callback, bool filter_objective_cost);
3257 IntVarLocalSearchFilter* MakePickupDeliveryFilter(
3258  const RoutingModel& routing_model, const RoutingModel::IndexPairs& pairs,
3259  const std::vector<RoutingModel::PickupAndDeliveryPolicy>& vehicle_policies);
3260 IntVarLocalSearchFilter* MakeVehicleVarFilter(
3261  const RoutingModel& routing_model);
3262 IntVarLocalSearchFilter* MakeVehicleBreaksFilter(
3263  const RoutingModel& routing_model, const RoutingDimension& dimension);
3264 IntVarLocalSearchFilter* MakeCPFeasibilityFilter(
3265  const RoutingModel* routing_model);
3266 #endif
3267 
3268 } // namespace operations_research
3269 #endif // OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_H_
bool HasTypeRegulations() const
Returns true iff the model has any incompatibilities or requirements set on node types.
Definition: routing.h:762
void AddSearchMonitor(SearchMonitor *const monitor)
Adds a search monitor to the search used to solve the routing model.
absl::Duration RemainingTime() const
Returns the time left in the search limit.
Definition: routing.h:1173
void SetAmortizedCostFactorsOfVehicle(int64 linear_cost_factor, int64 quadratic_cost_factor, int vehicle)
Sets the linear and quadratic cost factor of the given vehicle.
bool WriteAssignment(const std::string &file_name) const
Writes the current solution to a file containing an AssignmentProto.
bool ApplyLocksToAllVehicles(const std::vector< std::vector< int64 >> &locks, bool close_routes)
Applies lock chains to all vehicles to the next search, such that locks[p] is the lock chain for rout...
void AddTemporalRequiredTypeAlternatives(int dependent_type, absl::flat_hash_set< int > required_type_alternatives)
If type_D temporally depends on type_R, any non-delivery node_D of type_D requires at least one non-d...
int GetCostClassesCount() const
Returns the number of different cost classes in the model.
Definition: routing.h:1119
void SetFirstSolutionEvaluator(Solver::IndexEvaluator2 evaluator)
Takes ownership of evaluator.
Definition: routing.h:845
IntVar * NextVar(int64 index) const
Returns the next variable of the node corresponding to index.
Definition: routing.h:1066
const Solver::IndexEvaluator2 & first_solution_evaluator() const
Search Gets/sets the evaluator used during the search.
Definition: routing.h:840
std::vector< const SortedDisjointIntervalList * > forbidden_intervals
Definition: routing.h:1681
bool HasTemporalTypeRequirements() const
Definition: routing.h:756
int vehicles() const
Returns the number of vehicle routes in the model.
Definition: routing.h:1182
bool IsMatchingModel() const
Returns true if a vehicle/node matching problem is detected.
int GetNonZeroCostClassesCount() const
Ditto, minus the 'always zero', built-in cost class.
Definition: routing.h:1121
bool HasTemporalTypeIncompatibilities() const
Definition: routing.h:723
Assignment * RestoreAssignment(const Assignment &solution)
Restores an assignment as a solution in the routing model and returns the new solution.
std::vector< std::pair< int64, int64 > > distance_duration
Definition: routing.h:1682
const std::vector< int64 > & GetAmortizedLinearCostFactorOfVehicles() const
Definition: routing.h:819
void ConsiderEmptyRouteCostsForVehicle(bool consider_costs, int vehicle)
Definition: routing.h:826
static std::unique_ptr< LocalSearchOperator > MakeGreedyDescentLSOperator(std::vector< IntVar * > variables)
void AssignmentToRoutes(const Assignment &assignment, std::vector< std::vector< int64 >> *const routes) const
Converts the solution in the given assignment to routes for all vehicles.
Assignment * CompactAndCheckAssignment(const Assignment &assignment) const
Same as CompactAssignment() but also checks the validity of the final compact solution; if it is not ...
std::vector< int64 > duration_min
Definition: routing.h:1676
void AddSameVehicleRequiredTypeAlternatives(int dependent_type, absl::flat_hash_set< int > required_type_alternatives)
Requirements:
const Assignment * Solve(const Assignment *assignment=nullptr)
Solves the current routing model; closes the current model.
bool HasSameVehicleTypeRequirements() const
clang-format on Returns true iff any same-route (resp.
Definition: routing.h:753
IntVar * VehicleVar(int64 index) const
Returns the vehicle variable of the node corresponding to index.
Definition: routing.h:1076
int64 Zero()
-------— Misc -------—
bool HasHardTypeIncompatibilities() const
Returns true iff any hard (resp.
Definition: routing.h:720
int64 GetHomogeneousCost(int64 from_index, int64 to_index) const
Returns the cost of the segment between two nodes supposing all vehicle costs are the same (returns t...
Definition: routing.h:1090
IntVar * VehicleCostsConsideredVar(int vehicle) const
Returns the variable specifying whether or not costs are considered for vehicle.
Definition: routing.h:1071
IntVar * ActiveVar(int64 index) const
Returns the active variable of the node corresponding to index.
Definition: routing.h:1068
const Assignment * SolveWithParameters(const RoutingSearchParameters &search_parameters, std::vector< const Assignment * > *solutions=nullptr)
Solves the current routing model with the given parameters.
std::function< int64(int64, int64)> RoutingTransitCallback2
Definition: routing_types.h:42
bool IsEnd(int64 index) const
Returns true if 'index' represents the last node of a route.
Definition: routing.h:1045
CostClassIndex GetCostClassIndexOfVehicle(int64 vehicle) const
Get the cost class index of the given vehicle.
Definition: routing.h:1105
IntVar * CostVar() const
Returns the global cost variable which is being minimized.
Definition: routing.h:1078
bool IsStart(int64 index) const
Returns true if 'index' represents the first node of a route.
int64 Next(const Assignment &assignment, int64 index) const
Assignment inspection Returns the variable index of the node directly after the node corresponding to...
const Assignment *const PreAssignment() const
Returns an assignment used to fix some of the variables of the problem.
Definition: routing.h:935
void AddHardTypeIncompatibility(int type1, int type2)
Incompatibilities: Two nodes with "hard" incompatible types cannot share the same route at all,...
const absl::flat_hash_set< int > & GetTemporalTypeIncompatibilitiesOfType(int type) const
std::function< bool(int64, int64, int64)> VariableValueComparator
bool IsVehicleUsed(const Assignment &assignment, int vehicle) const
Returns true if the route of 'vehicle' is non empty in 'assignment'.
int64 ComputeLowerBound()
Computes a lower bound to the routing problem solving a linear assignment problem.
Assignment * ReadAssignmentFromRoutes(const std::vector< std::vector< int64 >> &routes, bool ignore_inactive_indices)
Restores the routes as the current solution.
const std::vector< IntVar * > & VehicleVars() const
Returns all vehicle variables of the model, such that VehicleVars(i) is the vehicle variable of the n...
Definition: routing.h:1062
void CloseModelWithParameters(const RoutingSearchParameters &search_parameters)
Same as above taking search parameters (as of 10/2015 some the parameters have to be set when closing...
bool CheckLimit()
Returns true if the search limit has been crossed.
Definition: routing.h:1167
int64 UnperformedPenaltyOrValue(int64 default_value, int64 var_index) const
Same as above except that it returns default_value instead of 0 when penalty is not well defined (def...
int64 GetArcCostForVehicle(int64 from_index, int64 to_index, int64 vehicle) const
Returns the cost of the transit arc between two nodes for a given vehicle.
std::string DebugOutputAssignment(const Assignment &solution_assignment, const std::string &dimension_to_print) const
Print some debugging information about an assignment, including the feasible intervals of the CumulVa...
void CloseModel()
Closes the current routing model; after this method is called, no modification to the model can be do...
int64 End(int vehicle) const
Returns the variable index of the ending node of a vehicle route.
Definition: routing.h:1041
void AddVariableMinimizedByFinalizer(IntVar *var)
Adds a variable to minimize in the solution finalizer.
std::function< std::vector< operations_research::IntVar * >(RoutingModel *)> GetTabuVarsCallback
Sets the callback returning the variable to use for the Tabu Search metaheuristic.
Definition: routing.h:1200
int64 GetArcCostForClass(int64 from_index, int64 to_index, int64 cost_class_index) const
Returns the cost of the segment between two nodes for a given cost class.
void AddIntervalToAssignment(IntervalVar *const interval)
DecisionBuilder * MakeGuidedSlackFinalizer(const RoutingDimension *dimension, std::function< int64(int64)> initializer)
The next few members are in the public section only for testing purposes.
void SetArcCostEvaluatorOfAllVehicles(int evaluator_index)
Sets the cost function of the model such that the cost of a segment of a route between node 'from' an...
std::vector< int64 > duration_max
Definition: routing.h:1677
void SetFixedCostOfAllVehicles(int64 cost)
Sets the fixed cost of all vehicle routes.
void CloseVisitTypes()
This function should be called once all node visit types have been set and prior to adding any incomp...
int64 GetDepot() const
Returns the variable index of the first starting or ending node of all routes.
std::function< int64(int64)> RoutingTransitCallback1
Definition: routing_types.h:41
int VehicleIndex(int index) const
Returns the vehicle of the given start/end index, and -1 if the given index is not a vehicle start/en...
Definition: routing.h:1048
friend class RoutingModelInspector
Definition: routing.h:1648
int GetVehicleClassesCount() const
Returns the number of different vehicle classes in the model.
Definition: routing.h:1129
void SetSweepArranger(SweepArranger *sweep_arranger)
Definition: routing.h:1018
int64 UnperformedPenalty(int64 var_index) const
Get the "unperformed" penalty of a node.
bool CostsAreHomogeneousAcrossVehicles() const
Whether costs are homogeneous across all vehicles.
Definition: routing.h:1085
routing_no_lns(default:false) int GetVisitType(int64 index) const
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in c...
int64 Start(int vehicle) const
Model inspection.
Definition: routing.h:1039
const Assignment * PackCumulsOfOptimizerDimensionsFromAssignment(const Assignment *original_assignment, absl::Duration duration_limit)
For every dimension in the model's dimensions_for_local/global_optimizer_, this method tries to pack ...
const absl::flat_hash_set< int > & GetHardTypeIncompatibilitiesOfType(int type) const
Returns visit types incompatible with a given type.
Status status() const
Returns the current status of the routing model.
Definition: routing.h:912
bool HasVehicleWithCostClassIndex(CostClassIndex cost_class_index) const
Returns true iff the model contains a vehicle with the given cost_class_index.
Definition: routing.h:1111
void AddLocalSearchFilter(LocalSearchFilter *filter)
Adds a custom local search filter to the list of filters used to speed up local search by pruning unf...
Definition: routing.h:1029
void AddTemporalTypeIncompatibility(int type1, int type2)
int64 GetNumberOfDecisionsInFirstSolution(const RoutingSearchParameters &search_parameters) const
Returns statistics on first solution search, number of decisions sent to filters, number of decisions...
bool AreEmptyRouteCostsConsideredForVehicle(int vehicle) const
Definition: routing.h:831
bool operator<(const StartEndValue &other) const
Definition: routing.h:2576
A structure to hold tasks described by their features.
Definition: routing.h:1672
std::vector< int64 > end_min
Definition: routing.h:1678
void AddLocalSearchOperator(LocalSearchOperator *ls_operator)
Adds a local search operator to the set of operators used to solve the vehicle routing problem.
Assignment * MutablePreAssignment()
Definition: routing.h:936
void AddVariableMaximizedByFinalizer(IntVar *var)
Adds a variable to maximize in the solution finalizer (see above for information on the solution fina...
void SetAssignmentFromOtherModelAssignment(Assignment *target_assignment, const RoutingModel *source_model, const Assignment *source_assignment)
Given a "source_model" and its "source_assignment", resets "target_assignment" with the IntVar variab...
int nodes() const
Sizes and indices Returns the number of nodes in the model.
Definition: routing.h:1180
void SetTabuVarsCallback(GetTabuVarsCallback tabu_var_callback)
const std::vector< int64 > & GetAmortizedQuadraticCostFactorOfVehicles() const
Definition: routing.h:822
bool operator<(const VehicleClassEntry &other) const
Definition: routing.h:2972
std::vector< int64 > start_min
Definition: routing.h:1674
const std::vector< IntVar * > & Nexts() const
Variables.
Definition: routing.h:1059
IntVar * ApplyLocks(const std::vector< int64 > &locks)
Applies a lock chain to the next search.
int64 GetFixedCostOfVehicle(int vehicle) const
Returns the route fixed cost taken into account if the route of the vehicle is not empty,...
bool ArcIsMoreConstrainedThanArc(int64 from, int64 to1, int64 to2)
Returns whether the arc from->to1 is more constrained than from->to2, taking into account,...
Assignment * CompactAssignment(const Assignment &assignment) const
Returns a compacted version of the given assignment, in which all vehicles with id lower or equal to ...
void SetFixedCostOfVehicle(int64 cost, int vehicle)
Sets the fixed cost of one vehicle route.
std::function< void(int64)> ObjectiveWatcher
void SetArcCostEvaluatorOfVehicle(int evaluator_index, int vehicle)
Sets the cost function for a given vehicle route.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in c...
bool RoutesToAssignment(const std::vector< std::vector< int64 >> &routes, bool ignore_inactive_indices, bool close_routes, Assignment *const assignment) const
Fills an assignment from a specification of the routes of the vehicles.
SweepArranger * sweep_arranger() const
Returns the sweep arranger to be used by routing heuristics.
Definition: routing.h:1022
int64 GetNumberOfRejectsInFirstSolution(const RoutingSearchParameters &search_parameters) const
Solver * solver() const
Returns the underlying constraint solver.
Definition: routing.h:1164
quadratic_cost_factor_of_vehicle_ *[v] square of length of route v void SetAmortizedCostFactorsOfAllVehicles(int64 linear_cost_factor, int64 quadratic_cost_factor)
The following methods set the linear and quadratic cost factors of vehicles (must be positive values)...
std::vector< bool > is_preemptible
Definition: routing.h:1680
VehicleClassIndex GetVehicleClassIndexOfVehicle(int64 vehicle) const
Definition: routing.h:1124
int GetNumberOfVisitTypes() const
Definition: routing.h:706
std::vector< RoutingIndexPair > RoutingIndexPairs
Definition: routing_types.h:45
void AddAtSolutionCallback(std::function< void()> callback)
Adds a callback called each time a solution is found during the search.
*RoutingModel model(manager)
std::function< int64(int64, int64)> IndexEvaluator2
const std::vector< absl::flat_hash_set< int > > & GetTemporalRequiredTypeAlternativesOfType(int type) const
std::vector< int64 > end_max
Definition: routing.h:1679
std::pair< std::vector< int64 >, std::vector< int64 > > RoutingIndexPair
NOTE(user): keep the "> >" for SWIG.
Definition: routing_types.h:44
const Assignment * SolveFromAssignmentWithParameters(const Assignment *assignment, const RoutingSearchParameters &search_parameters, std::vector< const Assignment * > *solutions=nullptr)
DecisionBuilder * MakeSelfDependentDimensionFinalizer(const RoutingDimension *dimension)
MakeSelfDependentDimensionFinalizer is a finalizer for the slacks of a self-dependent dimension.
Assignment * ReadAssignment(const std::string &file_name)
Reads an assignment from a file and returns the current solution.
const std::vector< absl::flat_hash_set< int > > & GetSameVehicleRequiredTypeAlternativesOfType(int type) const
clang-format off Returns the sets of same-vehicle/temporal requirement alternatives for the given typ...
int64 Size() const
Returns the number of next variables in the model.
Definition: routing.h:1184
int64 GetArcCostForFirstSolution(int64 from_index, int64 to_index) const
Returns the cost of the arc in the context of the first solution strategy.
void AddToAssignment(IntVar *const var)
Adds an extra variable to the vehicle routing assignment.
friend class RoutingDimension
Definition: routing.h:1647
const std::vector< int > & GetSameVehicleIndicesOfIndex(int node) const
Returns variable indices of nodes constrained to be on the same route.
Definition: routing.h:1131
std::vector< int64 > start_max
Definition: routing.h:1675