OR-Tools  8.0
routing_lp_scheduling.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 #ifndef OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_LP_SCHEDULING_H_
15 #define OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_LP_SCHEDULING_H_
16 
17 #include "absl/container/flat_hash_map.h"
18 #include "absl/memory/memory.h"
19 #include "ortools/base/mathutil.h"
21 #include "ortools/glop/lp_solver.h"
23 #include "ortools/sat/cp_model.h"
26 
27 namespace operations_research {
28 
29 // Classes to solve dimension cumul placement (aka scheduling) problems using
30 // linear programming.
31 
32 // Utility class used in the core optimizer to tighten the cumul bounds as much
33 // as possible based on the model precedences.
35  public:
37 
38  // Tightens the cumul bounds starting from the current cumul var min/max,
39  // and propagating the precedences resulting from the next_accessor, and the
40  // dimension's precedence rules.
41  // Returns false iff the precedences are infeasible with the given routes.
42  // Otherwise, the user can call CumulMin() and CumulMax() to retrieve the new
43  // bounds of an index.
44  bool PropagateCumulBounds(const std::function<int64(int64)>& next_accessor,
45  int64 cumul_offset);
46 
47  int64 CumulMin(int index) const {
48  return propagated_bounds_[PositiveNode(index)];
49  }
50 
51  int64 CumulMax(int index) const {
52  const int64 negated_upper_bound = propagated_bounds_[NegativeNode(index)];
53  return negated_upper_bound == kint64min ? kint64max : -negated_upper_bound;
54  }
55 
56  const RoutingDimension& dimension() const { return dimension_; }
57 
58  private:
59  // An arc "tail --offset--> head" represents the relation
60  // tail + offset <= head.
61  // As arcs are stored by tail, we don't store it in the struct.
62  struct ArcInfo {
63  int head;
64  int64 offset;
65  };
66  static const int kNoParent;
67  static const int kParentToBePropagated;
68 
69  // Return the node corresponding to the lower bound of the cumul of index and
70  // -index respectively.
71  int PositiveNode(int index) const { return 2 * index; }
72  int NegativeNode(int index) const { return 2 * index + 1; }
73 
74  void AddNodeToQueue(int node) {
75  if (!node_in_queue_[node]) {
76  bf_queue_.push_back(node);
77  node_in_queue_[node] = true;
78  }
79  }
80 
81  // Adds the relation first_index + offset <= second_index, by adding arcs
82  // first_index --offset--> second_index and
83  // -second_index --offset--> -first_index.
84  void AddArcs(int first_index, int second_index, int64 offset);
85 
86  bool InitializeArcsAndBounds(const std::function<int64(int64)>& next_accessor,
87  int64 cumul_offset);
88 
89  bool UpdateCurrentLowerBoundOfNode(int node, int64 new_lb, int64 offset);
90 
91  bool DisassembleSubtree(int source, int target);
92 
93  bool CleanupAndReturnFalse() {
94  // We clean-up node_in_queue_ for future calls, and return false.
95  for (int node_to_cleanup : bf_queue_) {
96  node_in_queue_[node_to_cleanup] = false;
97  }
98  bf_queue_.clear();
99  return false;
100  }
101 
102  const RoutingDimension& dimension_;
103  const int64 num_nodes_;
104 
105  // TODO(user): Investigate if all arcs for a given tail can be created
106  // at the same time, in which case outgoing_arcs_ could point to an absl::Span
107  // for each tail index.
108  std::vector<std::vector<ArcInfo>> outgoing_arcs_;
109 
110  std::deque<int> bf_queue_;
111  std::vector<bool> node_in_queue_;
112  std::vector<int> tree_parent_node_of_;
113  // After calling PropagateCumulBounds(), for each node index n,
114  // propagated_bounds_[2*n] and -propagated_bounds_[2*n+1] respectively contain
115  // the propagated lower and upper bounds of n's cumul variable.
116  std::vector<int64> propagated_bounds_;
117 
118  // Vector used in DisassembleSubtree() to avoid memory reallocation.
119  std::vector<int> tmp_dfs_stack_;
120 
121  // Used to store the pickup/delivery pairs encountered on the routes.
122  std::vector<std::pair<int64, int64>>
123  visited_pickup_delivery_indices_for_pair_;
124 };
125 
127  // An optimal solution was found respecting all constraints.
128  OPTIMAL,
129  // An optimal solution was found, however constraints which were relaxed were
130  // violated.
132  // A solution could not be found.
133  INFEASIBLE
134 };
135 
137  public:
139  virtual void Clear() = 0;
140  virtual int CreateNewPositiveVariable() = 0;
141  virtual bool SetVariableBounds(int index, int64 lower_bound,
142  int64 upper_bound) = 0;
144  const std::vector<int64>& starts,
145  const std::vector<int64>& ends) = 0;
146  virtual int64 GetVariableLowerBound(int index) const = 0;
147  virtual void SetObjectiveCoefficient(int index, double coefficient) = 0;
148  virtual double GetObjectiveCoefficient(int index) const = 0;
149  virtual void ClearObjective() = 0;
150  virtual int NumVariables() const = 0;
151  virtual int CreateNewConstraint(int64 lower_bound, int64 upper_bound) = 0;
152  virtual void SetCoefficient(int ct, int index, double coefficient) = 0;
153  virtual bool IsCPSATSolver() = 0;
154  virtual void AddMaximumConstraint(int max_var, std::vector<int> vars) = 0;
155  virtual void AddProductConstraint(int product_var, std::vector<int> vars) = 0;
156  virtual void SetEnforcementLiteral(int ct, int condition) = 0;
157  virtual DimensionSchedulingStatus Solve(absl::Duration duration_limit) = 0;
158  virtual int64 GetObjectiveValue() const = 0;
159  virtual double GetValue(int index) const = 0;
160  virtual bool SolutionIsInteger() const = 0;
161 
162  // Adds a variable with bounds [lower_bound, upper_bound].
163  int AddVariable(int64 lower_bound, int64 upper_bound) {
164  CHECK_LE(lower_bound, upper_bound);
165  const int variable = CreateNewPositiveVariable();
166  SetVariableBounds(variable, lower_bound, upper_bound);
167  return variable;
168  }
169  // Adds a linear constraint, enforcing
170  // lower_bound <= sum variable * coeff <= upper_bound,
171  // and returns the identifier of that constraint.
173  int64 lower_bound, int64 upper_bound,
174  const std::vector<std::pair<int, double>>& variable_coeffs) {
175  CHECK_LE(lower_bound, upper_bound);
176  const int ct = CreateNewConstraint(lower_bound, upper_bound);
177  for (const auto& variable_coeff : variable_coeffs) {
178  SetCoefficient(ct, variable_coeff.first, variable_coeff.second);
179  }
180  return ct;
181  }
182  // Adds a linear constraint and a 0/1 variable that is true iff
183  // lower_bound <= sum variable * coeff <= upper_bound,
184  // and returns the identifier of that variable.
186  int64 lower_bound, int64 upper_bound,
187  const std::vector<std::pair<int, double>>& weighted_variables) {
188  const int reification_ct = AddLinearConstraint(1, 1, {});
189  if (kint64min < lower_bound) {
190  const int under_lower_bound = AddVariable(0, 1);
191  SetCoefficient(reification_ct, under_lower_bound, 1);
192  const int under_lower_bound_ct =
193  AddLinearConstraint(kint64min, lower_bound - 1, weighted_variables);
194  SetEnforcementLiteral(under_lower_bound_ct, under_lower_bound);
195  }
196  if (upper_bound < kint64max) {
197  const int above_upper_bound = AddVariable(0, 1);
198  SetCoefficient(reification_ct, above_upper_bound, 1);
199  const int above_upper_bound_ct =
200  AddLinearConstraint(upper_bound + 1, kint64max, weighted_variables);
201  SetEnforcementLiteral(above_upper_bound_ct, above_upper_bound);
202  }
203  const int within_bounds = AddVariable(0, 1);
204  SetCoefficient(reification_ct, within_bounds, 1);
205  const int within_bounds_ct =
206  AddLinearConstraint(lower_bound, upper_bound, weighted_variables);
207  SetEnforcementLiteral(within_bounds_ct, within_bounds);
208  return within_bounds;
209  }
210 };
211 
213  public:
214  explicit RoutingGlopWrapper(const glop::GlopParameters& parameters) {
215  lp_solver_.SetParameters(parameters);
216  linear_program_.SetMaximizationProblem(false);
217  }
218  void Clear() override {
219  linear_program_.Clear();
220  linear_program_.SetMaximizationProblem(false);
221  allowed_intervals_.clear();
222  }
223  int CreateNewPositiveVariable() override {
224  return linear_program_.CreateNewVariable().value();
225  }
226  bool SetVariableBounds(int index, int64 lower_bound,
227  int64 upper_bound) override {
228  DCHECK_GE(lower_bound, 0);
229  // When variable upper bounds are greater than this threshold, precision
230  // issues arise in GLOP. In this case we are just going to suppose that
231  // these high bound values are infinite and not set the upper bound.
232  const int64 kMaxValue = 1e10;
233  const double lp_min = lower_bound;
234  const double lp_max =
235  (upper_bound > kMaxValue) ? glop::kInfinity : upper_bound;
236  if (lp_min <= lp_max) {
237  linear_program_.SetVariableBounds(glop::ColIndex(index), lp_min, lp_max);
238  return true;
239  }
240  // The linear_program would not be feasible, and it cannot handle the
241  // lp_min > lp_max case, so we must detect infeasibility here.
242  return false;
243  }
244  void SetVariableDisjointBounds(int index, const std::vector<int64>& starts,
245  const std::vector<int64>& ends) override {
246  // TODO(user): Investigate if we can avoid rebuilding the interval list
247  // each time (we could keep a reference to the forbidden interval list in
248  // RoutingDimension but we would need to store cumul offsets and use them
249  // when checking intervals).
250  allowed_intervals_[index] =
251  absl::make_unique<SortedDisjointIntervalList>(starts, ends);
252  }
253  int64 GetVariableLowerBound(int index) const override {
254  return linear_program_.variable_lower_bounds()[glop::ColIndex(index)];
255  }
256  void SetObjectiveCoefficient(int index, double coefficient) override {
257  linear_program_.SetObjectiveCoefficient(glop::ColIndex(index), coefficient);
258  }
259  double GetObjectiveCoefficient(int index) const override {
260  return linear_program_.objective_coefficients()[glop::ColIndex(index)];
261  }
262  void ClearObjective() override {
263  for (glop::ColIndex i(0); i < linear_program_.num_variables(); ++i) {
264  linear_program_.SetObjectiveCoefficient(i, 0);
265  }
266  }
267  int NumVariables() const override {
268  return linear_program_.num_variables().value();
269  }
270  int CreateNewConstraint(int64 lower_bound, int64 upper_bound) override {
271  const glop::RowIndex ct = linear_program_.CreateNewConstraint();
272  linear_program_.SetConstraintBounds(
273  ct, (lower_bound == kint64min) ? -glop::kInfinity : lower_bound,
274  (upper_bound == kint64max) ? glop::kInfinity : upper_bound);
275  return ct.value();
276  }
277  void SetCoefficient(int ct, int index, double coefficient) override {
278  linear_program_.SetCoefficient(glop::RowIndex(ct), glop::ColIndex(index),
279  coefficient);
280  }
281  bool IsCPSATSolver() override { return false; }
282  void AddMaximumConstraint(int max_var, std::vector<int> vars) override{};
283  void AddProductConstraint(int product_var, std::vector<int> vars) override{};
284  void SetEnforcementLiteral(int ct, int condition) override{};
285  DimensionSchedulingStatus Solve(absl::Duration duration_limit) override {
286  lp_solver_.GetMutableParameters()->set_max_time_in_seconds(
287  absl::ToDoubleSeconds(duration_limit));
288 
289  // Because we construct the lp one constraint at a time and we never call
290  // SetCoefficient() on the same variable twice for a constraint, we know
291  // that the columns do not contain duplicates and are already ordered by
292  // constraint so we do not need to call linear_program->CleanUp() which can
293  // be costly. Note that the assumptions are DCHECKed() in the call below.
294  linear_program_.NotifyThatColumnsAreClean();
295  VLOG(2) << linear_program_.Dump();
296  const glop::ProblemStatus status = lp_solver_.Solve(linear_program_);
297  if (status != glop::ProblemStatus::OPTIMAL &&
298  status != glop::ProblemStatus::IMPRECISE) {
299  linear_program_.Clear();
301  }
302  for (const auto& allowed_interval : allowed_intervals_) {
303  const double value_double = GetValue(allowed_interval.first);
304  const int64 value = (value_double >= kint64max)
305  ? kint64max
306  : MathUtil::FastInt64Round(value_double);
307  const SortedDisjointIntervalList* const interval_list =
308  allowed_interval.second.get();
309  const auto it = interval_list->FirstIntervalGreaterOrEqual(value);
310  if (it == interval_list->end() || value < it->start) {
312  }
313  }
315  }
316  int64 GetObjectiveValue() const override {
317  return MathUtil::FastInt64Round(lp_solver_.GetObjectiveValue());
318  }
319  double GetValue(int index) const override {
320  return lp_solver_.variable_values()[glop::ColIndex(index)];
321  }
322  bool SolutionIsInteger() const override {
323  return linear_program_.SolutionIsInteger(lp_solver_.variable_values(),
324  /*absolute_tolerance*/ 1e-3);
325  }
326 
327  private:
328  glop::LinearProgram linear_program_;
329  glop::LPSolver lp_solver_;
330  absl::flat_hash_map<int, std::unique_ptr<SortedDisjointIntervalList>>
331  allowed_intervals_;
332 };
333 
335  public:
336  RoutingCPSatWrapper() : objective_offset_(0), first_constraint_to_offset_(0) {
337  parameters_.set_num_search_workers(1);
338  // Keeping presolve but with 0 iterations; as of 11/2019 it is
339  // significantly faster than both full presolve and no presolve.
340  parameters_.set_cp_model_presolve(true);
341  parameters_.set_max_presolve_iterations(0);
342  parameters_.set_catch_sigint_signal(false);
343  parameters_.set_mip_max_bound(1e8);
344  }
345  ~RoutingCPSatWrapper() override {}
346  void Clear() override {
347  model_.Clear();
348  response_.Clear();
349  objective_coefficients_.clear();
350  objective_offset_ = 0;
351  variable_offset_.clear();
352  constraint_offset_.clear();
353  first_constraint_to_offset_ = 0;
354  }
355  int CreateNewPositiveVariable() override {
356  const int index = model_.variables_size();
357  if (index >= variable_offset_.size()) {
358  variable_offset_.resize(index + 1, 0);
359  }
360  sat::IntegerVariableProto* const variable = model_.add_variables();
361  variable->add_domain(0);
362  variable->add_domain(static_cast<int64>(parameters_.mip_max_bound()));
363  return index;
364  }
365  bool SetVariableBounds(int index, int64 lower_bound,
366  int64 upper_bound) override {
367  DCHECK_GE(lower_bound, 0);
368  // TODO(user): Find whether there is a way to make the offsetting
369  // system work with other CP-SAT constraints than linear constraints.
370  // variable_offset_[index] = lower_bound;
371  variable_offset_[index] = 0;
372  const int64 offset_upper_bound =
373  std::min<int64>(CapSub(upper_bound, variable_offset_[index]),
374  parameters_.mip_max_bound());
375  const int64 offset_lower_bound =
376  CapSub(lower_bound, variable_offset_[index]);
377  if (offset_lower_bound > offset_upper_bound) return false;
378  sat::IntegerVariableProto* const variable = model_.mutable_variables(index);
379  variable->set_domain(0, offset_lower_bound);
380  variable->set_domain(1, offset_upper_bound);
381  return true;
382  }
383  void SetVariableDisjointBounds(int index, const std::vector<int64>& starts,
384  const std::vector<int64>& ends) override {
385  DCHECK_EQ(starts.size(), ends.size());
386  const int ct = CreateNewConstraint(1, 1);
387  for (int i = 0; i < starts.size(); ++i) {
388  const int variable = CreateNewPositiveVariable();
389  SetVariableBounds(variable, 0, 1);
390  SetCoefficient(ct, variable, 1);
391  const int window_ct = CreateNewConstraint(starts[i], ends[i]);
392  SetCoefficient(window_ct, index, 1);
393  model_.mutable_constraints(window_ct)->add_enforcement_literal(variable);
394  }
395  }
396  int64 GetVariableLowerBound(int index) const override {
397  return CapAdd(model_.variables(index).domain(0), variable_offset_[index]);
398  }
399  void SetObjectiveCoefficient(int index, double coefficient) override {
400  // TODO(user): Check variable bounds are never set after setting the
401  // objective coefficient.
402  if (index >= objective_coefficients_.size()) {
403  objective_coefficients_.resize(index + 1, 0);
404  }
405  objective_coefficients_[index] = coefficient;
406  sat::CpObjectiveProto* const objective = model_.mutable_objective();
407  objective->add_vars(index);
408  objective->add_coeffs(coefficient);
409  objective_offset_ += coefficient * variable_offset_[index];
410  }
411  double GetObjectiveCoefficient(int index) const override {
412  return (index < objective_coefficients_.size())
413  ? objective_coefficients_[index]
414  : 0;
415  }
416  void ClearObjective() override {
417  model_.mutable_objective()->Clear();
418  objective_offset_ = 0;
419  }
420  int NumVariables() const override { return model_.variables_size(); }
421  int CreateNewConstraint(int64 lower_bound, int64 upper_bound) override {
422  const int ct_index = model_.constraints_size();
423  if (ct_index >= constraint_offset_.size()) {
424  constraint_offset_.resize(ct_index + 1, 0);
425  }
426  sat::LinearConstraintProto* const ct =
427  model_.add_constraints()->mutable_linear();
428  ct->add_domain(lower_bound);
429  ct->add_domain(upper_bound);
430  return ct_index;
431  }
432  void SetCoefficient(int ct_index, int index, double coefficient) override {
433  // TODO(user): Check variable bounds are never set after setting the
434  // variable coefficient.
435  sat::LinearConstraintProto* const ct =
436  model_.mutable_constraints(ct_index)->mutable_linear();
437  ct->add_vars(index);
438  ct->add_coeffs(coefficient);
439  constraint_offset_[ct_index] =
440  CapAdd(constraint_offset_[ct_index],
441  CapProd(variable_offset_[index], coefficient));
442  }
443  bool IsCPSATSolver() override { return true; }
444  void AddMaximumConstraint(int max_var, std::vector<int> vars) override {
445  sat::LinearArgumentProto* const ct =
446  model_.add_constraints()->mutable_lin_max();
447  ct->mutable_target()->add_vars(max_var);
448  ct->mutable_target()->add_coeffs(1);
449  for (const int var : vars) {
450  sat::LinearExpressionProto* const expr = ct->add_exprs();
451  expr->add_vars(var);
452  expr->add_coeffs(1);
453  }
454  }
455  void AddProductConstraint(int product_var, std::vector<int> vars) override {
456  sat::IntegerArgumentProto* const ct =
457  model_.add_constraints()->mutable_int_prod();
458  ct->set_target(product_var);
459  for (const int var : vars) {
460  ct->add_vars(var);
461  }
462  }
463  void SetEnforcementLiteral(int ct, int condition) override {
464  DCHECK_LT(ct, constraint_offset_.size());
465  model_.mutable_constraints(ct)->add_enforcement_literal(condition);
466  }
467  DimensionSchedulingStatus Solve(absl::Duration duration_limit) override {
468  // Set constraint offsets
469  for (int ct_index = first_constraint_to_offset_;
470  ct_index < constraint_offset_.size(); ++ct_index) {
471  if (!model_.mutable_constraints(ct_index)->has_linear()) continue;
472  sat::LinearConstraintProto* const ct =
473  model_.mutable_constraints(ct_index)->mutable_linear();
474  ct->set_domain(0, CapSub(ct->domain(0), constraint_offset_[ct_index]));
475  ct->set_domain(1, CapSub(ct->domain(1), constraint_offset_[ct_index]));
476  }
477  first_constraint_to_offset_ = constraint_offset_.size();
478  parameters_.set_max_time_in_seconds(absl::ToDoubleSeconds(duration_limit));
479  VLOG(2) << model_.DebugString();
480  if (hint_.vars_size() == model_.variables_size()) {
481  *model_.mutable_solution_hint() = hint_;
482  }
484  model.Add(sat::NewSatParameters(parameters_));
485  response_ = sat::SolveCpModel(model_, &model);
486  VLOG(2) << response_.DebugString();
487  if (response_.status() == sat::CpSolverStatus::OPTIMAL ||
488  (response_.status() == sat::CpSolverStatus::FEASIBLE &&
489  !model_.has_objective())) {
490  hint_.Clear();
491  for (int i = 0; i < response_.solution_size(); ++i) {
492  hint_.add_vars(i);
493  hint_.add_values(response_.solution(i));
494  }
496  }
498  }
499  int64 GetObjectiveValue() const override {
500  return MathUtil::FastInt64Round(response_.objective_value() +
501  objective_offset_);
502  }
503  double GetValue(int index) const override {
504  return response_.solution(index) + variable_offset_[index];
505  }
506  bool SolutionIsInteger() const override { return true; }
507 
508  private:
509  sat::CpModelProto model_;
510  sat::CpSolverResponse response_;
511  sat::SatParameters parameters_;
512  std::vector<double> objective_coefficients_;
513  double objective_offset_;
514  std::vector<int64> variable_offset_;
515  std::vector<int64> constraint_offset_;
516  int first_constraint_to_offset_;
517  sat::PartialVariableAssignment hint_;
518 };
519 
520 // Utility class used in Local/GlobalDimensionCumulOptimizer to set the linear
521 // solver constraints and solve the problem.
523  public:
525  bool use_precedence_propagator);
526 
527  // In the OptimizeSingleRoute() and Optimize() methods, if both "cumul_values"
528  // and "cost" parameters are null, we don't optimize the cost and stop at the
529  // first feasible solution in the linear solver (since in this case only
530  // feasibility is of interest).
532  int vehicle, const std::function<int64(int64)>& next_accessor,
533  RoutingLinearSolverWrapper* solver, std::vector<int64>* cumul_values,
534  std::vector<int64>* break_values, int64* cost, int64* transit_cost,
535  bool clear_lp = true);
536 
537  bool Optimize(const std::function<int64(int64)>& next_accessor,
539  std::vector<int64>* cumul_values,
540  std::vector<int64>* break_values, int64* cost,
541  int64* transit_cost, bool clear_lp = true);
542 
543  bool OptimizeAndPack(const std::function<int64(int64)>& next_accessor,
545  std::vector<int64>* cumul_values,
546  std::vector<int64>* break_values);
547 
549  int vehicle, const std::function<int64(int64)>& next_accessor,
550  RoutingLinearSolverWrapper* solver, std::vector<int64>* cumul_values,
551  std::vector<int64>* break_values);
552 
553  const RoutingDimension* dimension() const { return dimension_; }
554 
555  private:
556  // Initializes the containers and given solver. Must be called prior to
557  // setting any contraints and solving.
558  void InitOptimizer(RoutingLinearSolverWrapper* solver);
559 
560  // Computes the minimum/maximum of cumuls for nodes on "route", and sets them
561  // in current_route_[min|max]_cumuls_ respectively.
562  // If the propagator_ is not null, uses the bounds tightened by the
563  // propagator.
564  // Otherwise, the bounds are computed by going over the nodes on the route
565  // using the CP bounds, and the fixed transits are used to tighten them.
566  bool ComputeRouteCumulBounds(const std::vector<int64>& route,
567  const std::vector<int64>& fixed_transits,
568  int64 cumul_offset);
569 
570  // Sets the constraints for all nodes on "vehicle"'s route according to
571  // "next_accessor". If optimize_costs is true, also sets the objective
572  // coefficients for the LP.
573  // Returns false if some infeasibility was detected, true otherwise.
574  bool SetRouteCumulConstraints(
575  int vehicle, const std::function<int64(int64)>& next_accessor,
576  int64 cumul_offset, bool optimize_costs,
577  RoutingLinearSolverWrapper* solver, int64* route_transit_cost,
578  int64* route_cost_offset);
579 
580  // Sets the global constraints on the dimension, and adds global objective
581  // cost coefficients if optimize_costs is true.
582  // NOTE: When called, the call to this function MUST come after
583  // SetRouteCumulConstraints() has been called on all routes, so that
584  // index_to_cumul_variable_ and min_start/max_end_cumul_ are correctly
585  // initialized.
586  void SetGlobalConstraints(bool optimize_costs,
588 
589  void SetValuesFromLP(const std::vector<int>& lp_variables, int64 offset,
591  std::vector<int64>* lp_values);
592 
593  // This function packs the routes of the given vehicles while keeping the cost
594  // of the LP lower than its current (supposed optimal) objective value.
595  // It does so by setting the current objective variables' coefficient to 0 and
596  // setting the coefficient of the route ends to 1, to first minimize the route
597  // ends' cumuls, and then maximizes the starts' cumuls without increasing the
598  // ends.
599  DimensionSchedulingStatus PackRoutes(std::vector<int> vehicles,
601 
602  std::unique_ptr<CumulBoundsPropagator> propagator_;
603  std::vector<int64> current_route_min_cumuls_;
604  std::vector<int64> current_route_max_cumuls_;
605  const RoutingDimension* const dimension_;
606  // Scheduler variables for current route cumuls and for all nodes cumuls.
607  std::vector<int> current_route_cumul_variables_;
608  std::vector<int> index_to_cumul_variable_;
609  // Scheduler variables for current route breaks and all vehicle breaks.
610  // There are two variables for each break: start and end.
611  // current_route_break_variables_ has variables corresponding to
612  // break[0] start, break[0] end, break[1] start, break[1] end, etc.
613  std::vector<int> current_route_break_variables_;
614  // Vector all_break_variables contains the break variables of all vehicles,
615  // in the same format as current_route_break_variables.
616  // It is the concatenation of break variables of vehicles in [0, #vehicles).
617  std::vector<int> all_break_variables_;
618  // Allows to retrieve break variables of a given vehicle: those go from
619  // all_break_variables_[vehicle_to_all_break_variables_offset_[vehicle]] to
620  // all_break_variables[vehicle_to_all_break_variables_offset_[vehicle+1]-1].
621  std::vector<int> vehicle_to_all_break_variables_offset_;
622 
623  int max_end_cumul_;
624  int min_start_cumul_;
625  std::vector<std::pair<int64, int64>>
626  visited_pickup_delivery_indices_for_pair_;
627 };
628 
629 // Class used to compute optimal values for dimension cumuls of routes,
630 // minimizing cumul soft lower and upper bound costs, and vehicle span costs of
631 // a route.
632 // In its methods, next_accessor is a callback returning the next node of a
633 // given node on a route.
635  public:
638  RoutingSearchParameters::SchedulingSolver solver_type);
639 
640  // If feasible, computes the optimal cost of the route performed by a vehicle,
641  // minimizing cumul soft lower and upper bound costs and vehicle span costs,
642  // and stores it in "optimal_cost" (if not null).
643  // Returns true iff the route respects all constraints.
645  int vehicle, const std::function<int64(int64)>& next_accessor,
646  int64* optimal_cost);
647 
648  // Same as ComputeRouteCumulCost, but the cost computed does not contain
649  // the part of the vehicle span cost due to fixed transits.
651  int vehicle, const std::function<int64(int64)>& next_accessor,
652  int64* optimal_cost_without_transits);
653 
654  // If feasible, computes the optimal values for cumul and break variables
655  // of the route performed by a vehicle, minimizing cumul soft lower, upper
656  // bound costs and vehicle span costs, stores them in "optimal_cumuls"
657  // (if not null), and optimal_breaks, and returns true.
658  // Returns false if the route is not feasible.
660  int vehicle, const std::function<int64(int64)>& next_accessor,
661  std::vector<int64>* optimal_cumuls, std::vector<int64>* optimal_breaks);
662 
663  // Similar to ComputeRouteCumuls, but also tries to pack the cumul values on
664  // the route, such that the cost remains the same, the cumul of route end is
665  // minimized, and then the cumul of the start of the route is maximized.
667  int vehicle, const std::function<int64(int64)>& next_accessor,
668  std::vector<int64>* packed_cumuls, std::vector<int64>* packed_breaks);
669 
670  const RoutingDimension* dimension() const {
671  return optimizer_core_.dimension();
672  }
673 
674  private:
675  std::vector<std::unique_ptr<RoutingLinearSolverWrapper>> solver_;
676  DimensionCumulOptimizerCore optimizer_core_;
677 };
678 
680  public:
682  // If feasible, computes the optimal cost of the entire model with regards to
683  // the optimizer_core_'s dimension costs, minimizing cumul soft lower/upper
684  // bound costs and vehicle/global span costs, and stores it in "optimal_cost"
685  // (if not null).
686  // Returns true iff all the constraints can be respected.
688  const std::function<int64(int64)>& next_accessor,
689  int64* optimal_cost_without_transits);
690  // If feasible, computes the optimal values for cumul and break variables,
691  // minimizing cumul soft lower/upper bound costs and vehicle/global span
692  // costs, stores them in "optimal_cumuls" (if not null) and optimal breaks,
693  // and returns true.
694  // Returns false if the routes are not feasible.
695  bool ComputeCumuls(const std::function<int64(int64)>& next_accessor,
696  std::vector<int64>* optimal_cumuls,
697  std::vector<int64>* optimal_breaks);
698 
699  // Returns true iff the routes resulting from the next_accessor are feasible
700  // wrt the constraints on the optimizer_core_.dimension()'s cumuls.
701  bool IsFeasible(const std::function<int64(int64)>& next_accessor);
702 
703  // Similar to ComputeCumuls, but also tries to pack the cumul values on all
704  // routes, such that the cost remains the same, the cumuls of route ends are
705  // minimized, and then the cumuls of the starts of the routes are maximized.
706  bool ComputePackedCumuls(const std::function<int64(int64)>& next_accessor,
707  std::vector<int64>* packed_cumuls,
708  std::vector<int64>* packed_breaks);
709 
710  const RoutingDimension* dimension() const {
711  return optimizer_core_.dimension();
712  }
713 
714  private:
715  std::unique_ptr<RoutingLinearSolverWrapper> solver_;
716  DimensionCumulOptimizerCore optimizer_core_;
717 };
718 
719 } // namespace operations_research
720 
721 #endif // OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_LP_SCHEDULING_H_
operations_research::RoutingLinearSolverWrapper::CreateNewPositiveVariable
virtual int CreateNewPositiveVariable()=0
operations_research::RoutingCPSatWrapper::SetVariableDisjointBounds
void SetVariableDisjointBounds(int index, const std::vector< int64 > &starts, const std::vector< int64 > &ends) override
Definition: routing_lp_scheduling.h:383
var
IntVar * var
Definition: expr_array.cc:1858
operations_research::glop::LPSolver::GetMutableParameters
GlopParameters * GetMutableParameters()
Definition: lp_solver.cc:117
operations_research::DimensionCumulOptimizerCore::OptimizeAndPackSingleRoute
DimensionSchedulingStatus OptimizeAndPackSingleRoute(int vehicle, const std::function< int64(int64)> &next_accessor, RoutingLinearSolverWrapper *solver, std::vector< int64 > *cumul_values, std::vector< int64 > *break_values)
Definition: routing_lp_scheduling.cc:595
operations_research::RoutingLinearSolverWrapper::Solve
virtual DimensionSchedulingStatus Solve(absl::Duration duration_limit)=0
operations_research::sat::FEASIBLE
@ FEASIBLE
Definition: cp_model.pb.h:230
operations_research::RoutingGlopWrapper::GetObjectiveCoefficient
double GetObjectiveCoefficient(int index) const override
Definition: routing_lp_scheduling.h:259
operations_research::GlobalDimensionCumulOptimizer::ComputeCumuls
bool ComputeCumuls(const std::function< int64(int64)> &next_accessor, std::vector< int64 > *optimal_cumuls, std::vector< int64 > *optimal_breaks)
Definition: routing_lp_scheduling.cc:1332
cp_model.pb.h
operations_research::CapSub
int64 CapSub(int64 x, int64 y)
Definition: saturated_arithmetic.h:154
operations_research::RoutingLinearSolverWrapper::GetValue
virtual double GetValue(int index) const =0
operations_research::RoutingCPSatWrapper::~RoutingCPSatWrapper
~RoutingCPSatWrapper() override
Definition: routing_lp_scheduling.h:345
operations_research::glop::LPSolver::SetParameters
void SetParameters(const GlopParameters &parameters)
Definition: lp_solver.cc:111
operations_research::RoutingLinearSolverWrapper::IsCPSATSolver
virtual bool IsCPSATSolver()=0
operations_research::glop::ProblemStatus::IMPRECISE
@ IMPRECISE
operations_research::CapProd
int64 CapProd(int64 x, int64 y)
Definition: saturated_arithmetic.h:231
operations_research::RoutingCPSatWrapper::SetVariableBounds
bool SetVariableBounds(int index, int64 lower_bound, int64 upper_bound) override
Definition: routing_lp_scheduling.h:365
operations_research::glop::LinearProgram::variable_lower_bounds
const DenseRow & variable_lower_bounds() const
Definition: lp_data.h:229
operations_research::glop::LinearProgram::CreateNewConstraint
RowIndex CreateNewConstraint()
Definition: lp_data.cc:189
operations_research::RoutingCPSatWrapper::GetVariableLowerBound
int64 GetVariableLowerBound(int index) const override
Definition: routing_lp_scheduling.h:396
operations_research::RoutingLinearSolverWrapper::AddReifiedLinearConstraint
int AddReifiedLinearConstraint(int64 lower_bound, int64 upper_bound, const std::vector< std::pair< int, double >> &weighted_variables)
Definition: routing_lp_scheduling.h:185
operations_research::RoutingGlopWrapper::SetEnforcementLiteral
void SetEnforcementLiteral(int ct, int condition) override
Definition: routing_lp_scheduling.h:284
operations_research::LocalDimensionCumulOptimizer::dimension
const RoutingDimension * dimension() const
Definition: routing_lp_scheduling.h:670
operations_research::DimensionSchedulingStatus::RELAXED_OPTIMAL_ONLY
@ RELAXED_OPTIMAL_ONLY
operations_research::GlobalDimensionCumulOptimizer
Definition: routing_lp_scheduling.h:679
operations_research::RoutingGlopWrapper
Definition: routing_lp_scheduling.h:212
operations_research::RoutingGlopWrapper::Clear
void Clear() override
Definition: routing_lp_scheduling.h:218
operations_research::CumulBoundsPropagator::dimension
const RoutingDimension & dimension() const
Definition: routing_lp_scheduling.h:56
routing.h
operations_research::RoutingLinearSolverWrapper::CreateNewConstraint
virtual int CreateNewConstraint(int64 lower_bound, int64 upper_bound)=0
operations_research::glop::LinearProgram::SetObjectiveCoefficient
void SetObjectiveCoefficient(ColIndex col, Fractional value)
Definition: lp_data.cc:324
operations_research::RoutingLinearSolverWrapper::GetObjectiveValue
virtual int64 GetObjectiveValue() const =0
operations_research::RoutingLinearSolverWrapper::AddVariable
int AddVariable(int64 lower_bound, int64 upper_bound)
Definition: routing_lp_scheduling.h:163
operations_research::RoutingLinearSolverWrapper::SolutionIsInteger
virtual bool SolutionIsInteger() const =0
value
int64 value
Definition: demon_profiler.cc:43
operations_research::RoutingCPSatWrapper::SetCoefficient
void SetCoefficient(int ct_index, int index, double coefficient) override
Definition: routing_lp_scheduling.h:432
operations_research::DimensionCumulOptimizerCore::DimensionCumulOptimizerCore
DimensionCumulOptimizerCore(const RoutingDimension *dimension, bool use_precedence_propagator)
Definition: routing_lp_scheduling.cc:438
operations_research::SortedDisjointIntervalList::FirstIntervalGreaterOrEqual
Iterator FirstIntervalGreaterOrEqual(int64 value) const
Returns an iterator to either:
Definition: sorted_interval_list.cc:716
saturated_arithmetic.h
operations_research
The vehicle routing library lets one model and solve generic vehicle routing problems ranging from th...
Definition: dense_doubly_linked_list.h:21
operations_research::GlobalDimensionCumulOptimizer::dimension
const RoutingDimension * dimension() const
Definition: routing_lp_scheduling.h:710
operations_research::RoutingGlopWrapper::Solve
DimensionSchedulingStatus Solve(absl::Duration duration_limit) override
Definition: routing_lp_scheduling.h:285
operations_research::RoutingCPSatWrapper::Solve
DimensionSchedulingStatus Solve(absl::Duration duration_limit) override
Definition: routing_lp_scheduling.h:467
operations_research::DimensionSchedulingStatus
DimensionSchedulingStatus
Definition: routing_lp_scheduling.h:126
operations_research::glop::LinearProgram
Definition: lp_data.h:55
kint64min
static const int64 kint64min
Definition: integral_types.h:60
int64
int64_t int64
Definition: integral_types.h:34
operations_research::RoutingCPSatWrapper::IsCPSATSolver
bool IsCPSATSolver() override
Definition: routing_lp_scheduling.h:443
operations_research::GlobalDimensionCumulOptimizer::ComputeCumulCostWithoutFixedTransits
bool ComputeCumulCostWithoutFixedTransits(const std::function< int64(int64)> &next_accessor, int64 *optimal_cost_without_transits)
Definition: routing_lp_scheduling.cc:1317
operations_research::glop::LPSolver
Definition: lp_solver.h:29
operations_research::RoutingCPSatWrapper::NumVariables
int NumVariables() const override
Definition: routing_lp_scheduling.h:420
operations_research::sat::Model
Class that owns everything related to a particular optimization model.
Definition: sat/model.h:38
operations_research::glop::LinearProgram::SetConstraintBounds
void SetConstraintBounds(RowIndex row, Fractional lower_bound, Fractional upper_bound)
Definition: lp_data.cc:307
index
int index
Definition: pack.cc:508
operations_research::RoutingLinearSolverWrapper::GetVariableLowerBound
virtual int64 GetVariableLowerBound(int index) const =0
operations_research::glop::LinearProgram::num_variables
ColIndex num_variables() const
Definition: lp_data.h:205
operations_research::SortedDisjointIntervalList
This class represents a sorted list of disjoint, closed intervals.
Definition: sorted_interval_list.h:387
operations_research::DimensionCumulOptimizerCore::OptimizeSingleRoute
DimensionSchedulingStatus OptimizeSingleRoute(int vehicle, const std::function< int64(int64)> &next_accessor, RoutingLinearSolverWrapper *solver, std::vector< int64 > *cumul_values, std::vector< int64 > *break_values, int64 *cost, int64 *transit_cost, bool clear_lp=true)
Definition: routing_lp_scheduling.cc:462
operations_research::glop::LinearProgram::SetMaximizationProblem
void SetMaximizationProblem(bool maximize)
Definition: lp_data.cc:341
operations_research::RoutingCPSatWrapper::GetValue
double GetValue(int index) const override
Definition: routing_lp_scheduling.h:503
operations_research::RoutingGlopWrapper::RoutingGlopWrapper
RoutingGlopWrapper(const glop::GlopParameters &parameters)
Definition: routing_lp_scheduling.h:214
operations_research::MathUtil::FastInt64Round
static int64 FastInt64Round(double x)
Definition: mathutil.h:138
operations_research::GlobalDimensionCumulOptimizer::IsFeasible
bool IsFeasible(const std::function< int64(int64)> &next_accessor)
Definition: routing_lp_scheduling.cc:1339
operations_research::CumulBoundsPropagator::CumulMin
int64 CumulMin(int index) const
Definition: routing_lp_scheduling.h:47
operations_research::RoutingLinearSolverWrapper::SetObjectiveCoefficient
virtual void SetObjectiveCoefficient(int index, double coefficient)=0
operations_research::glop::kInfinity
const double kInfinity
Definition: lp_types.h:83
cost
int64 cost
Definition: routing_flow.cc:130
operations_research::RoutingGlopWrapper::CreateNewPositiveVariable
int CreateNewPositiveVariable() override
Definition: routing_lp_scheduling.h:223
operations_research::RoutingGlopWrapper::CreateNewConstraint
int CreateNewConstraint(int64 lower_bound, int64 upper_bound) override
Definition: routing_lp_scheduling.h:270
operations_research::RoutingGlopWrapper::SetObjectiveCoefficient
void SetObjectiveCoefficient(int index, double coefficient) override
Definition: routing_lp_scheduling.h:256
operations_research::RoutingLinearSolverWrapper::AddMaximumConstraint
virtual void AddMaximumConstraint(int max_var, std::vector< int > vars)=0
operations_research::RoutingGlopWrapper::AddProductConstraint
void AddProductConstraint(int product_var, std::vector< int > vars) override
Definition: routing_lp_scheduling.h:283
operations_research::LocalDimensionCumulOptimizer
Definition: routing_lp_scheduling.h:634
operations_research::RoutingCPSatWrapper::RoutingCPSatWrapper
RoutingCPSatWrapper()
Definition: routing_lp_scheduling.h:336
operations_research::glop::LinearProgram::SetCoefficient
void SetCoefficient(RowIndex row, ColIndex col, Fractional value)
Definition: lp_data.cc:315
operations_research::RoutingCPSatWrapper::CreateNewConstraint
int CreateNewConstraint(int64 lower_bound, int64 upper_bound) override
Definition: routing_lp_scheduling.h:421
operations_research::glop::LPSolver::Solve
ABSL_MUST_USE_RESULT ProblemStatus Solve(const LinearProgram &lp)
Definition: lp_solver.cc:119
operations_research::RoutingGlopWrapper::AddMaximumConstraint
void AddMaximumConstraint(int max_var, std::vector< int > vars) override
Definition: routing_lp_scheduling.h:282
operations_research::RoutingGlopWrapper::SetVariableBounds
bool SetVariableBounds(int index, int64 lower_bound, int64 upper_bound) override
Definition: routing_lp_scheduling.h:226
operations_research::DimensionSchedulingStatus::INFEASIBLE
@ INFEASIBLE
operations_research::RoutingCPSatWrapper::SolutionIsInteger
bool SolutionIsInteger() const override
Definition: routing_lp_scheduling.h:506
operations_research::DimensionCumulOptimizerCore
Definition: routing_lp_scheduling.h:522
operations_research::RoutingLinearSolverWrapper
Definition: routing_lp_scheduling.h:136
operations_research::CapAdd
int64 CapAdd(int64 x, int64 y)
Definition: saturated_arithmetic.h:124
operations_research::DimensionSchedulingStatus::OPTIMAL
@ OPTIMAL
operations_research::RoutingCPSatWrapper::AddMaximumConstraint
void AddMaximumConstraint(int max_var, std::vector< int > vars) override
Definition: routing_lp_scheduling.h:444
cp_model.h
operations_research::RoutingGlopWrapper::NumVariables
int NumVariables() const override
Definition: routing_lp_scheduling.h:267
operations_research::RoutingGlopWrapper::SetVariableDisjointBounds
void SetVariableDisjointBounds(int index, const std::vector< int64 > &starts, const std::vector< int64 > &ends) override
Definition: routing_lp_scheduling.h:244
operations_research::RoutingCPSatWrapper::GetObjectiveValue
int64 GetObjectiveValue() const override
Definition: routing_lp_scheduling.h:499
operations_research::RoutingGlopWrapper::GetValue
double GetValue(int index) const override
Definition: routing_lp_scheduling.h:319
mathutil.h
operations_research::RoutingDimension
Dimensions represent quantities accumulated at nodes along the routes.
Definition: routing.h:2288
operations_research::RoutingLinearSolverWrapper::AddLinearConstraint
int AddLinearConstraint(int64 lower_bound, int64 upper_bound, const std::vector< std::pair< int, double >> &variable_coeffs)
Definition: routing_lp_scheduling.h:172
operations_research::glop::LinearProgram::SetVariableBounds
void SetVariableBounds(ColIndex col, Fractional lower_bound, Fractional upper_bound)
Definition: lp_data.cc:247
operations_research::glop::LinearProgram::Dump
std::string Dump() const
Definition: lp_data.cc:529
operations_research::CumulBoundsPropagator::PropagateCumulBounds
bool PropagateCumulBounds(const std::function< int64(int64)> &next_accessor, int64 cumul_offset)
Definition: routing_lp_scheduling.cc:385
operations_research::SortedDisjointIntervalList::end
ConstIterator end() const
Definition: sorted_interval_list.h:481
operations_research::RoutingLinearSolverWrapper::Clear
virtual void Clear()=0
ct
const Constraint * ct
Definition: demon_profiler.cc:42
operations_research::RoutingCPSatWrapper::AddProductConstraint
void AddProductConstraint(int product_var, std::vector< int > vars) override
Definition: routing_lp_scheduling.h:455
operations_research::RoutingGlopWrapper::SetCoefficient
void SetCoefficient(int ct, int index, double coefficient) override
Definition: routing_lp_scheduling.h:277
operations_research::CumulBoundsPropagator::CumulBoundsPropagator
CumulBoundsPropagator(const RoutingDimension *dimension)
Definition: routing_lp_scheduling.cc:225
operations_research::sat::OPTIMAL
@ OPTIMAL
Definition: cp_model.pb.h:232
operations_research::RoutingCPSatWrapper::GetObjectiveCoefficient
double GetObjectiveCoefficient(int index) const override
Definition: routing_lp_scheduling.h:411
operations_research::sat::NewSatParameters
std::function< SatParameters(Model *)> NewSatParameters(const std::string &params)
Creates parameters for the solver, which you can add to the model with.
Definition: cp_model_solver.cc:871
operations_research::RoutingCPSatWrapper
Definition: routing_lp_scheduling.h:334
operations_research::RoutingCPSatWrapper::CreateNewPositiveVariable
int CreateNewPositiveVariable() override
Definition: routing_lp_scheduling.h:355
model
GRBmodel * model
Definition: gurobi_interface.cc:195
operations_research::RoutingCPSatWrapper::SetObjectiveCoefficient
void SetObjectiveCoefficient(int index, double coefficient) override
Definition: routing_lp_scheduling.h:399
operations_research::RoutingGlopWrapper::SolutionIsInteger
bool SolutionIsInteger() const override
Definition: routing_lp_scheduling.h:322
operations_research::RoutingLinearSolverWrapper::SetEnforcementLiteral
virtual void SetEnforcementLiteral(int ct, int condition)=0
operations_research::sat::SolveCpModel
CpSolverResponse SolveCpModel(const CpModelProto &model_proto, Model *model)
Solves the given CpModelProto.
Definition: cp_model_solver.cc:2822
operations_research::GlobalDimensionCumulOptimizer::ComputePackedCumuls
bool ComputePackedCumuls(const std::function< int64(int64)> &next_accessor, std::vector< int64 > *packed_cumuls, std::vector< int64 > *packed_breaks)
Definition: routing_lp_scheduling.cc:1345
operations_research::RoutingGlopWrapper::GetObjectiveValue
int64 GetObjectiveValue() const override
Definition: routing_lp_scheduling.h:316
operations_research::RoutingLinearSolverWrapper::SetCoefficient
virtual void SetCoefficient(int ct, int index, double coefficient)=0
operations_research::LocalDimensionCumulOptimizer::ComputeRouteCumulCostWithoutFixedTransits
DimensionSchedulingStatus ComputeRouteCumulCostWithoutFixedTransits(int vehicle, const std::function< int64(int64)> &next_accessor, int64 *optimal_cost_without_transits)
Definition: routing_lp_scheduling.cc:190
operations_research::RoutingCPSatWrapper::SetEnforcementLiteral
void SetEnforcementLiteral(int ct, int condition) override
Definition: routing_lp_scheduling.h:463
operations_research::glop::ProblemStatus::OPTIMAL
@ OPTIMAL
operations_research::glop::LinearProgram::objective_coefficients
const DenseRow & objective_coefficients() const
Definition: lp_data.h:223
coefficient
int64 coefficient
Definition: routing_search.cc:973
operations_research::RoutingLinearSolverWrapper::SetVariableDisjointBounds
virtual void SetVariableDisjointBounds(int index, const std::vector< int64 > &starts, const std::vector< int64 > &ends)=0
operations_research::CumulBoundsPropagator
Definition: routing_lp_scheduling.h:34
operations_research::glop::ProblemStatus
ProblemStatus
Definition: lp_types.h:101
operations_research::RoutingCPSatWrapper::ClearObjective
void ClearObjective() override
Definition: routing_lp_scheduling.h:416
operations_research::glop::LinearProgram::NotifyThatColumnsAreClean
void NotifyThatColumnsAreClean()
Definition: lp_data.h:539
operations_research::DimensionCumulOptimizerCore::OptimizeAndPack
bool OptimizeAndPack(const std::function< int64(int64)> &next_accessor, RoutingLinearSolverWrapper *solver, std::vector< int64 > *cumul_values, std::vector< int64 > *break_values)
Definition: routing_lp_scheduling.cc:567
operations_research::RoutingLinearSolverWrapper::AddProductConstraint
virtual void AddProductConstraint(int product_var, std::vector< int > vars)=0
operations_research::RoutingGlopWrapper::GetVariableLowerBound
int64 GetVariableLowerBound(int index) const override
Definition: routing_lp_scheduling.h:253
operations_research::glop::LinearProgram::SolutionIsInteger
bool SolutionIsInteger(const DenseRow &solution, Fractional absolute_tolerance) const
Definition: lp_data.cc:486
operations_research::LocalDimensionCumulOptimizer::ComputePackedRouteCumuls
DimensionSchedulingStatus ComputePackedRouteCumuls(int vehicle, const std::function< int64(int64)> &next_accessor, std::vector< int64 > *packed_cumuls, std::vector< int64 > *packed_breaks)
Definition: routing_lp_scheduling.cc:214
operations_research::CumulBoundsPropagator::CumulMax
int64 CumulMax(int index) const
Definition: routing_lp_scheduling.h:51
operations_research::RoutingLinearSolverWrapper::SetVariableBounds
virtual bool SetVariableBounds(int index, int64 lower_bound, int64 upper_bound)=0
operations_research::glop::LPSolver::variable_values
const DenseRow & variable_values() const
Definition: lp_solver.h:100
operations_research::RoutingGlopWrapper::IsCPSATSolver
bool IsCPSATSolver() override
Definition: routing_lp_scheduling.h:281
operations_research::LocalDimensionCumulOptimizer::ComputeRouteCumulCost
DimensionSchedulingStatus ComputeRouteCumulCost(int vehicle, const std::function< int64(int64)> &next_accessor, int64 *optimal_cost)
Definition: routing_lp_scheduling.cc:181
lp_types.h
operations_research::RoutingLinearSolverWrapper::NumVariables
virtual int NumVariables() const =0
operations_research::LocalDimensionCumulOptimizer::ComputeRouteCumuls
DimensionSchedulingStatus ComputeRouteCumuls(int vehicle, const std::function< int64(int64)> &next_accessor, std::vector< int64 > *optimal_cumuls, std::vector< int64 > *optimal_breaks)
Definition: routing_lp_scheduling.cc:205
head
int64 head
Definition: routing_flow.cc:128
operations_research::LocalDimensionCumulOptimizer::LocalDimensionCumulOptimizer
LocalDimensionCumulOptimizer(const RoutingDimension *dimension, RoutingSearchParameters::SchedulingSolver solver_type)
Definition: routing_lp_scheduling.cc:154
operations_research::glop::LPSolver::GetObjectiveValue
Fractional GetObjectiveValue() const
Definition: lp_solver.cc:444
operations_research::RoutingLinearSolverWrapper::GetObjectiveCoefficient
virtual double GetObjectiveCoefficient(int index) const =0
operations_research::glop::LinearProgram::CreateNewVariable
ColIndex CreateNewVariable()
Definition: lp_data.cc:160
operations_research::RoutingLinearSolverWrapper::~RoutingLinearSolverWrapper
virtual ~RoutingLinearSolverWrapper()
Definition: routing_lp_scheduling.h:138
parameters
SatParameters parameters
Definition: cp_model_fz_solver.cc:107
operations_research::DimensionCumulOptimizerCore::dimension
const RoutingDimension * dimension() const
Definition: routing_lp_scheduling.h:553
operations_research::RoutingGlopWrapper::ClearObjective
void ClearObjective() override
Definition: routing_lp_scheduling.h:262
operations_research::RoutingLinearSolverWrapper::ClearObjective
virtual void ClearObjective()=0
kint64max
static const int64 kint64max
Definition: integral_types.h:62
lp_solver.h
operations_research::DimensionCumulOptimizerCore::Optimize
bool Optimize(const std::function< int64(int64)> &next_accessor, RoutingLinearSolverWrapper *solver, std::vector< int64 > *cumul_values, std::vector< int64 > *break_values, int64 *cost, int64 *transit_cost, bool clear_lp=true)
Definition: routing_lp_scheduling.cc:505
operations_research::RoutingCPSatWrapper::Clear
void Clear() override
Definition: routing_lp_scheduling.h:346
operations_research::glop::LinearProgram::Clear
void Clear()
Definition: lp_data.cc:132
operations_research::GlobalDimensionCumulOptimizer::GlobalDimensionCumulOptimizer
GlobalDimensionCumulOptimizer(const RoutingDimension *dimension)
Definition: routing_lp_scheduling.cc:1308