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)
Similar to ComputeCumuls, but also tries to pack the cumul values on all routes, such that the cost r...
int vehicles() const
Returns the number of vehicle routes in the model.
Definition: routing.h:1188
LocalDimensionCumulOptimizer(const RoutingDimension *dimension)
bool ComputeRouteCumuls(int vehicle, const std::function< int64(int64)> &next_accessor, std::vector< int64 > *optimal_cumuls)
If feasible, computes the optimal cumul values of the route performed by a vehicle,...
bool ComputePackedRouteCumuls(int vehicle, const std::function< int64(int64)> &next_accessor, std::vector< int64 > *packed_cumuls)
Similar to ComputeRouteCumuls, but also tries to pack the cumul values on the route,...
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)
Returns true iff the routes resulting from the next_accessor are feasible wrt the constraints on the ...
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)
Class used to compute optimal values for dimension cumuls of routes, minimizing cumul soft lower and ...
bool ComputeRouteCumulCostWithoutFixedTransits(int vehicle, const std::function< int64(int64)> &next_accessor, int64 *optimal_cost_without_transits)
Same as ComputeRouteCumulCost, but the cost computed does not contain the part of the vehicle span co...
bool ComputeRouteCumulCost(int vehicle, const std::function< int64(int64)> &next_accessor, int64 *optimal_cost)
If feasible, computes the optimal cost of the route performed by a vehicle, minimizing cumul soft low...
Classes to solve dimension cumul placement (aka scheduling) problems using linear programming.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in c...
bool ComputeCumulCostWithoutFixedTransits(const std::function< int64(int64)> &next_accessor, int64 *optimal_cost_without_transits)
If feasible, computes the optimal cost of the entire model with regards to the optimizer_core_'s dime...
*RoutingModel model(manager)
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)
In the OptimizeSingleRoute() and Optimize() methods, if both "cumul_values" and "cost" parameters are...
bool ComputeCumuls(const std::function< int64(int64)> &next_accessor, std::vector< int64 > *optimal_cumuls)
If feasible, computes the optimal cumul values, minimizing cumul soft lower/upper bound costs and veh...
friend class RoutingDimension
Definition: routing.h:1655