OR-Tools  8.1
feasibility_pump.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_SAT_FEASIBILITY_PUMP_H_
15 #define OR_TOOLS_SAT_FEASIBILITY_PUMP_H_
16 
22 #include "ortools/sat/integer.h"
24 #include "ortools/sat/sat_solver.h"
26 #include "ortools/sat/util.h"
27 
28 namespace operations_research {
29 namespace sat {
30 
32  public:
33  explicit FeasibilityPump(Model* model);
35 
36  typedef glop::RowIndex ConstraintIndex;
37 
38  void SetMaxFPIterations(int max_iter) {
39  max_fp_iterations_ = std::max(1, max_iter);
40  }
41 
42  // Add a new linear constraint to this LP.
44 
45  // Set the coefficient of the variable in the objective. Calling it twice will
46  // overwrite the previous value. Note that this doesn't set the objective
47  // coefficient if the variable doesn't appear in any constraints. So this has
48  // to be called after all the constraints are added.
49  void SetObjectiveCoefficient(IntegerVariable ivar, IntegerValue coeff);
50 
51  // Returns the LP value of a variable in the current
52  // solution. These functions should only be called when HasSolution() is true.
53  bool HasLPSolution() const { return lp_solution_is_set_; }
54  double LPSolutionObjectiveValue() const { return lp_objective_; }
55  double GetLPSolutionValue(IntegerVariable variable) const;
56  bool LPSolutionIsInteger() const { return lp_solution_is_integer_; }
57  double LPSolutionFractionality() const { return lp_solution_fractionality_; }
58 
59  // Returns the Integer solution value of a variable in the current rounded
60  // solution. These functions should only be called when HasIntegerSolution()
61  // is true.
62  bool HasIntegerSolution() const { return integer_solution_is_set_; }
64  return integer_solution_objective_;
65  }
67  return integer_solution_is_feasible_;
68  }
69  int64 GetIntegerSolutionValue(IntegerVariable variable) const;
70 
71  // Returns false if the model is proven to be infeasible.
72  bool Solve();
73 
74  private:
75  // Solve the LP, returns false if something went wrong in the LP solver.
76  bool SolveLp();
77 
78  // Calls the specified rounding method in the parameters. Returns false if the
79  // rounding couldn't be finished.
80  bool Round();
81 
82  // Round the fractional LP solution values to nearest integer values. This
83  // rounding always finishes so always returns true.
84  bool NearestIntegerRounding();
85 
86  // Counts the number of up and down locks as defined below.
87  // #up_locks = #upper bounded constraints with positive coeff for var
88  // + #lower bounded constraints with negative coeff for var.
89  // #down_locks = #lower bounded constraints with positive coeff for var
90  // + #upper bounded constraints with negative coeff for var.
91  // Rounds the variable in the direction of lesser locks. When the
92  // fractionality is low (less than 0.1), this reverts to nearest integer
93  // rounding to avoid rounding almost integer values in wrong direction.
94  // This rounding always finishes so always returns true.
95  bool LockBasedRounding();
96 
97  // Similar to LockBasedRounding except this only considers locks of active
98  // constraints.
99  bool ActiveLockBasedRounding();
100 
101  // This is expensive rounding algorithm. We round variables one by one and
102  // propagate the bounds in between. If none of the rounded values fall in
103  // the continuous domain specified by lower and upper bound, we use the
104  // current lower/upper bound (whichever one is closest) instead of rounding
105  // the fractional lp solution value. If both the rounded values are in the
106  // domain, we round to nearest integer. This idea was presented in the paper
107  // "Feasibility pump 2.0" (2009) by Matteo Fischetti, Domenico Salvagnin.
108  //
109  // This rounding might not finish either because the time limit is reached or
110  // the model is detected to be unsat. Returns false in those cases.
111  bool PropagationRounding();
112 
113  void FillIntegerSolutionStats();
114 
115  // Loads the lp_data_.
116  void InitializeWorkingLP();
117 
118  // Changes the LP objective and bounds of the norm constraints so the new
119  // objective also tries to minimize the distance to the rounded solution.
120  void L1DistanceMinimize();
121 
122  // Stores the solutions in the shared repository. Stores LP solution if it is
123  // integer and stores the integer solution if it is feasible.
124  void MaybePushToRepo();
125 
126  void PrintStats();
127 
128  // Returns the variable value on the same scale as the CP variable value.
129  double GetVariableValueAtCpScale(glop::ColIndex var);
130 
131  // Shortcut for an integer linear expression type.
132  using LinearExpression = std::vector<std::pair<glop::ColIndex, IntegerValue>>;
133 
134  // Gets or creates an LP variable that mirrors a model variable.
135  // The variable should be a positive reference.
136  glop::ColIndex GetOrCreateMirrorVariable(IntegerVariable positive_variable);
137 
138  // Updates the bounds of the LP variables from the CP bounds.
139  void UpdateBoundsOfLpVariables();
140 
141  // This epsilon is related to the precision of the value returned by the LP
142  // once they have been scaled back into the CP domain. So for large domain or
143  // cost coefficient, we may have some issues.
144  static const double kCpEpsilon;
145 
146  // Initial problem in integer form.
147  // We always sort the inner vectors by increasing glop::ColIndex.
148  struct LinearConstraintInternal {
149  IntegerValue lb;
150  IntegerValue ub;
151  LinearExpression terms;
152  };
153  LinearExpression integer_objective_;
154  IntegerValue objective_infinity_norm_ = IntegerValue(0);
155  double objective_normalization_factor_ = 0.0;
156  double mixing_factor_ = 1.0;
157 
159  int model_vars_size_ = 0;
160 
161  // Underlying LP solver API.
162  glop::LinearProgram lp_data_;
163  glop::RevisedSimplex simplex_;
164 
165  glop::ColMapping norm_variables_;
166  glop::ColToRowMapping norm_lhs_constraints_;
167  glop::ColToRowMapping norm_rhs_constraints_;
168 
169  // For the scaling.
170  glop::LpScalingHelper scaler_;
171 
172  // Structures used for mirroring IntegerVariables inside the underlying LP
173  // solver: an integer variable var is mirrored by mirror_lp_variable_[var].
174  // Note that these indices are dense in [0, mirror_lp_variable_.size()] so
175  // they can be used as vector indices.
176  std::vector<IntegerVariable> integer_variables_;
177  absl::flat_hash_map<IntegerVariable, glop::ColIndex> mirror_lp_variable_;
178 
179  // True if the variable was binary before we apply scaling.
180  std::vector<bool> var_is_binary_;
181 
182  // The following lock information is computed only once.
183  // Number of constraints restricting variable to take higher (resp. lower)
184  // values.
185  std::vector<int> var_up_locks_;
186  std::vector<int> var_down_locks_;
187 
188  // We need to remember what to optimize if an objective is given, because
189  // then we will switch the objective between feasibility and optimization.
190  bool objective_is_defined_ = false;
191 
192  // Singletons from Model.
193  const SatParameters& sat_parameters_;
194  TimeLimit* time_limit_;
195  IntegerTrail* integer_trail_;
196  Trail* trail_;
197  IntegerEncoder* integer_encoder_;
198  SharedIncompleteSolutionManager* incomplete_solutions_;
199  SatSolver* sat_solver_;
200  IntegerDomains* domains_;
201  const CpModelMapping* mapping_;
202 
203  // Last OPTIMAL/Feasible solution found by a call to the underlying LP solver.
204  bool lp_solution_is_set_ = false;
205  bool lp_solution_is_integer_ = false;
206  double lp_objective_;
207  std::vector<double> lp_solution_;
208  std::vector<double> best_lp_solution_;
209  // We use max fractionality of all variables.
210  double lp_solution_fractionality_;
211 
212  // Rounded Integer solution. This might not be feasible.
213  bool integer_solution_is_set_ = false;
214  bool integer_solution_is_feasible_ = false;
215  int64 integer_solution_objective_;
216  std::vector<int64> integer_solution_;
217  std::vector<int64> best_integer_solution_;
218  int num_infeasible_constraints_;
219  // We use max infeasibility of all constraints.
220  int64 integer_solution_infeasibility_;
221 
222  // Sum of all simplex iterations performed by this class. This is useful to
223  // test the incrementality and compare to other solvers.
224  int64 total_num_simplex_iterations_ = 0;
225 
226  // TODO(user): Tune default value. Expose as parameter.
227  int max_fp_iterations_ = 20;
228 
229  bool model_is_unsat_ = false;
230 };
231 
232 } // namespace sat
233 } // namespace operations_research
234 
235 #endif // OR_TOOLS_SAT_FEASIBILITY_PUMP_H_
synchronization.h
var
IntVar * var
Definition: expr_array.cc:1858
max
int64 max
Definition: alldiff_cst.cc:139
lp_data.h
linear_constraint.h
operations_research::sat::FeasibilityPump::HasLPSolution
bool HasLPSolution() const
Definition: feasibility_pump.h:53
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
int64
int64_t int64
Definition: integral_types.h:34
sat_solver.h
operations_research::TimeLimit
A simple class to enforce both an elapsed time limit and a deterministic time limit in the same threa...
Definition: time_limit.h:105
revised_simplex.h
operations_research::sat::LinearConstraint
Definition: linear_constraint.h:39
lp_data_utils.h
operations_research::sat::FeasibilityPump::Solve
bool Solve()
Definition: feasibility_pump.cc:143
operations_research::sat::FeasibilityPump::GetIntegerSolutionValue
int64 GetIntegerSolutionValue(IntegerVariable variable) const
Definition: feasibility_pump.cc:428
operations_research::glop::RevisedSimplex
Definition: revised_simplex.h:147
operations_research::sat::FeasibilityPump::IntegerSolutionObjectiveValue
int64 IntegerSolutionObjectiveValue() const
Definition: feasibility_pump.h:63
operations_research::sat::FeasibilityPump::ConstraintIndex
glop::RowIndex ConstraintIndex
Definition: feasibility_pump.h:36
operations_research::glop::LpScalingHelper
Definition: lp_data_utils.h:51
operations_research::glop::StrictITIVector< ColIndex, ColIndex >
operations_research::sat::LinearExpression
Definition: linear_constraint.h:173
operations_research::sat::FeasibilityPump
Definition: feasibility_pump.h:31
operations_research::sat::FeasibilityPump::SetMaxFPIterations
void SetMaxFPIterations(int max_iter)
Definition: feasibility_pump.h:38
operations_research::sat::Model
Class that owns everything related to a particular optimization model.
Definition: sat/model.h:38
ct
const Constraint * ct
Definition: demon_profiler.cc:42
model
GRBmodel * model
Definition: gurobi_interface.cc:269
operations_research::sat::FeasibilityPump::SetObjectiveCoefficient
void SetObjectiveCoefficient(IntegerVariable ivar, IntegerValue coeff)
Definition: feasibility_pump.cc:90
operations_research::sat::FeasibilityPump::GetLPSolutionValue
double GetLPSolutionValue(IntegerVariable variable) const
Definition: feasibility_pump.cc:416
operations_research::sat::FeasibilityPump::LPSolutionFractionality
double LPSolutionFractionality() const
Definition: feasibility_pump.h:57
absl::StrongVector< glop::RowIndex, LinearConstraintInternal >
util.h
operations_research::sat::FeasibilityPump::~FeasibilityPump
~FeasibilityPump()
Definition: feasibility_pump.cc:59
operations_research::sat::FeasibilityPump::AddLinearConstraint
void AddLinearConstraint(const LinearConstraint &ct)
Definition: feasibility_pump.cc:64
operations_research::glop::LinearProgram
Definition: lp_data.h:55
operations_research::Trail
Definition: constraint_solver.cc:723
cp_model_loader.h
operations_research::sat::FeasibilityPump::FeasibilityPump
FeasibilityPump(Model *model)
Definition: feasibility_pump.cc:37
operations_research::sat::FeasibilityPump::LPSolutionIsInteger
bool LPSolutionIsInteger() const
Definition: feasibility_pump.h:56
operations_research::sat::FeasibilityPump::HasIntegerSolution
bool HasIntegerSolution() const
Definition: feasibility_pump.h:62
lp_types.h
operations_research::sat::FeasibilityPump::LPSolutionObjectiveValue
double LPSolutionObjectiveValue() const
Definition: feasibility_pump.h:54
integer.h
operations_research::sat::FeasibilityPump::IntegerSolutionIsFeasible
bool IntegerSolutionIsFeasible() const
Definition: feasibility_pump.h:66