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 
18 #include "ortools/glop/lp_solver.h"
19 
20 namespace operations_research {
21 
22 // Classes to solve dimension cumul placement (aka scheduling) problems using
23 // linear programming.
24 
25 // Utility class used in Local/GlobalDimensionCumulOptimizer to set the LP
26 // constraints and solve the problem.
28  public:
30  : dimension_(dimension),
31  visited_pickup_index_for_pair_(
32  dimension->model()->GetPickupAndDeliveryPairs().size(), -1) {}
33 
34  // In the OptimizeSingleRoute() and Optimize() methods, if both "cumul_values"
35  // and "cost" parameters are null, we don't optimize the cost and stop at the
36  // first feasible solution in the LP (since in this case only feasibility is
37  // of interest).
38  bool OptimizeSingleRoute(int vehicle,
39  const std::function<int64(int64)>& next_accessor,
40  glop::LinearProgram* linear_program,
41  glop::LPSolver* lp_solver,
42  std::vector<int64>* cumul_values, int64* cost,
43  int64* transit_cost, bool clear_lp = true);
44 
45  bool Optimize(const std::function<int64(int64)>& next_accessor,
46  glop::LinearProgram* linear_program, glop::LPSolver* lp_solver,
47  std::vector<int64>* cumul_values, int64* cost,
48  int64* transit_cost, bool clear_lp = true);
49 
50  bool OptimizeAndPack(const std::function<int64(int64)>& next_accessor,
51  glop::LinearProgram* linear_program,
52  glop::LPSolver* lp_solver,
53  std::vector<int64>* cumul_values);
54 
56  int vehicle, const std::function<int64(int64)>& next_accessor,
57  glop::LinearProgram* linear_program, glop::LPSolver* lp_solver,
58  std::vector<int64>* cumul_values);
59 
60  const RoutingDimension* dimension() const { return dimension_; }
61 
62  private:
63  // Initializes the containers and given linear program. Must be called prior
64  // to setting any contraints and solving.
65  void InitOptimizer(glop::LinearProgram* linear_program);
66 
67  // Sets the constraints for all nodes on "vehicle"'s route according to
68  // "next_accessor". If optimize_costs is true, also sets the objective
69  // coefficients for the LP.
70  // Returns false if some infeasibility was detected, true otherwise.
71  bool SetRouteCumulConstraints(
72  int vehicle, const std::function<int64(int64)>& next_accessor,
73  int64 cumul_offset, bool optimize_costs,
74  glop::LinearProgram* linear_program, int64* route_transit_cost,
75  int64* route_cost_offset);
76 
77  // Sets the global constraints on the dimension, and adds global objective
78  // cost coefficients if optimize_costs is true.
79  // NOTE: When called, the call to this function MUST come after
80  // SetRouteCumulConstraints() has been called on all routes, so that
81  // index_to_cumul_variable_ and min_start/max_end_cumul_ are correctly
82  // initialized.
83  void SetGlobalConstraints(bool optimize_costs,
84  glop::LinearProgram* linear_program);
85 
86  bool FinalizeAndSolve(glop::LinearProgram* linear_program,
87  glop::LPSolver* lp_solver);
88 
89  void SetCumulValuesFromLP(const std::vector<glop::ColIndex>& cumul_variables,
90  int64 offset, const glop::LPSolver& lp_solver,
91  std::vector<int64>* cumul_values);
92 
93  // This function packs the routes of the given vehicles while keeping the cost
94  // of the LP lower than its current (supposed optimal) objective value.
95  // It does so by setting the current objective variables' coefficient to 0 and
96  // setting the coefficient of the route ends to 1, to first minimize the route
97  // ends' cumuls, and then maximizes the starts' cumuls without increasing the
98  // ends.
99  bool PackRoutes(std::vector<int> vehicles,
100  glop::LinearProgram* linear_program,
101  glop::LPSolver* lp_solver);
102 
103  const RoutingDimension* const dimension_;
104  std::vector<glop::ColIndex> current_route_cumul_variables_;
105  std::vector<glop::ColIndex> index_to_cumul_variable_;
106  glop::ColIndex max_end_cumul_;
107  glop::ColIndex min_start_cumul_;
108  std::vector<int64> visited_pickup_index_for_pair_;
109 };
110 
111 // Class used to compute optimal values for dimension cumuls of routes,
112 // minimizing cumul soft lower and upper bound costs, and vehicle span costs of
113 // a route.
114 // In its methods, next_accessor is a callback returning the next node of a
115 // given node on a route.
117  public:
119 
120  // If feasible, computes the optimal cost of the route performed by a vehicle,
121  // minimizing cumul soft lower and upper bound costs and vehicle span costs,
122  // and stores it in "optimal_cost" (if not null).
123  // Returns true iff the route respects all constraints.
124  bool ComputeRouteCumulCost(int vehicle,
125  const std::function<int64(int64)>& next_accessor,
126  int64* optimal_cost);
127 
128  // Same as ComputeRouteCumulCost, but the cost computed does not contain
129  // the part of the vehicle span cost due to fixed transits.
131  int vehicle, const std::function<int64(int64)>& next_accessor,
132  int64* optimal_cost_without_transits);
133 
134  // If feasible, computes the optimal cumul values of the route performed by a
135  // vehicle, minimizing cumul soft lower and upper bound costs and vehicle span
136  // costs, stores them in "optimal_cumuls" (if not null), and returns true.
137  // Returns false if the route is not feasible.
138  bool ComputeRouteCumuls(int vehicle,
139  const std::function<int64(int64)>& next_accessor,
140  std::vector<int64>* optimal_cumuls);
141 
142  // Similar to ComputeRouteCumuls, but also tries to pack the cumul values on
143  // the route, such that the cost remains the same, the cumul of route end is
144  // minimized, and then the cumul of the start of the route is maximized.
146  int vehicle, const std::function<int64(int64)>& next_accessor,
147  std::vector<int64>* packed_cumuls);
148 
149  const RoutingDimension* dimension() const {
150  return optimizer_core_.dimension();
151  }
152 
153  private:
154  std::vector<std::unique_ptr<glop::LPSolver>> lp_solver_;
155  std::vector<std::unique_ptr<glop::LinearProgram>> linear_program_;
156  DimensionCumulOptimizerCore optimizer_core_;
157 };
158 
160  public:
162  // If feasible, computes the optimal cost of the entire model with regards to
163  // the optimizer_core_'s dimension costs, minimizing cumul soft lower/upper
164  // bound costs and vehicle/global span costs, and stores it in "optimal_cost"
165  // (if not null).
166  // Returns true iff all the constraints can be respected.
168  const std::function<int64(int64)>& next_accessor,
169  int64* optimal_cost_without_transits);
170  // If feasible, computes the optimal cumul values, minimizing cumul soft
171  // lower/upper bound costs and vehicle/global span costs, stores them in
172  // "optimal_cumuls" (if not null), and returns true.
173  // Returns false if the routes are not feasible.
174  bool ComputeCumuls(const std::function<int64(int64)>& next_accessor,
175  std::vector<int64>* optimal_cumuls);
176 
177  // Returns true iff the routes resulting from the next_accessor are feasible
178  // wrt the constraints on the optimizer_core_.dimension()'s cumuls.
179  bool IsFeasible(const std::function<int64(int64)>& next_accessor);
180 
181  // Similar to ComputeCumuls, but also tries to pack the cumul values on all
182  // routes, such that the cost remains the same, the cumuls of route ends are
183  // minimized, and then the cumuls of the starts of the routes are maximized.
184  bool ComputePackedCumuls(const std::function<int64(int64)>& next_accessor,
185  std::vector<int64>* packed_cumuls);
186 
187  const RoutingDimension* dimension() const {
188  return optimizer_core_.dimension();
189  }
190 
191  private:
192  glop::LPSolver lp_solver_;
193  glop::LinearProgram linear_program_;
194  DimensionCumulOptimizerCore optimizer_core_;
195 };
196 
197 } // namespace operations_research
198 
199 #endif // OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_LP_SCHEDULING_H_
bool ComputePackedCumuls(const std::function< int64(int64)> &next_accessor, std::vector< int64 > *packed_cumuls)
LocalDimensionCumulOptimizer(const RoutingDimension *dimension)
Dimensions represent quantities accumulated at nodes along the routes.
Definition: routing.h:2023
bool ComputeRouteCumuls(int vehicle, const std::function< int64(int64)> &next_accessor, std::vector< int64 > *optimal_cumuls)
bool ComputePackedRouteCumuls(int vehicle, const std::function< int64(int64)> &next_accessor, std::vector< int64 > *packed_cumuls)
bool Optimize(const std::function< int64(int64)> &next_accessor, glop::LinearProgram *linear_program, glop::LPSolver *lp_solver, std::vector< int64 > *cumul_values, int64 *cost, int64 *transit_cost, bool clear_lp=true)
bool OptimizeAndPack(const std::function< int64(int64)> &next_accessor, glop::LinearProgram *linear_program, glop::LPSolver *lp_solver, std::vector< int64 > *cumul_values)
bool IsFeasible(const std::function< int64(int64)> &next_accessor)
GlobalDimensionCumulOptimizer(const RoutingDimension *dimension)
bool OptimizeAndPackSingleRoute(int vehicle, const std::function< int64(int64)> &next_accessor, glop::LinearProgram *linear_program, glop::LPSolver *lp_solver, std::vector< int64 > *cumul_values)
bool ComputeRouteCumulCostWithoutFixedTransits(int vehicle, const std::function< int64(int64)> &next_accessor, int64 *optimal_cost_without_transits)
bool ComputeRouteCumulCost(int vehicle, const std::function< int64(int64)> &next_accessor, int64 *optimal_cost)
The vehicle routing library lets one model and solve generic vehicle routing problems ranging from th...
bool ComputeCumulCostWithoutFixedTransits(const std::function< int64(int64)> &next_accessor, int64 *optimal_cost_without_transits)
DimensionCumulOptimizerCore(const RoutingDimension *dimension)
bool OptimizeSingleRoute(int vehicle, const std::function< int64(int64)> &next_accessor, glop::LinearProgram *linear_program, glop::LPSolver *lp_solver, std::vector< int64 > *cumul_values, int64 *cost, int64 *transit_cost, bool clear_lp=true)
bool ComputeCumuls(const std::function< int64(int64)> &next_accessor, std::vector< int64 > *optimal_cumuls)