OR-Tools  9.6
bop_base.h
Go to the documentation of this file.
1 // Copyright 2010-2022 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_BOP_BOP_BASE_H_
15 #define OR_TOOLS_BOP_BOP_BASE_H_
16 
17 #include <cstdint>
18 #include <limits>
19 #include <ostream>
20 #include <string>
21 #include <vector>
22 
23 #include "absl/strings/string_view.h"
24 #include "absl/synchronization/mutex.h"
27 #include "ortools/bop/bop_parameters.pb.h"
30 #include "ortools/sat/boolean_problem.pb.h"
31 #include "ortools/sat/clause.h"
32 #include "ortools/sat/sat_base.h"
33 #include "ortools/util/stats.h"
35 
36 namespace operations_research {
37 namespace bop {
38 
39 // Forward declaration.
40 struct LearnedInfo;
41 class ProblemState;
42 
43 // Base class used to optimize a ProblemState.
44 // Optimizers implementing this class are used in a sort of portfolio and
45 // are run sequentially or concurrently. See for instance BopRandomLNSOptimizer.
47  public:
48  explicit BopOptimizerBase(absl::string_view name);
49  virtual ~BopOptimizerBase();
50 
51  // Returns the name given at construction.
52  const std::string& name() const { return name_; }
53 
54  // Returns true if this optimizer should be run on the given problem state.
55  // Some optimizer requires a feasible solution to run for instance.
56  //
57  // Note that a similar effect can be achieved if Optimize() returns ABORT
58  // right away. However, doing the later will lower the chance of this
59  // optimizer to be called again since it will count as a failure to improve
60  // the current state.
61  virtual bool ShouldBeRun(const ProblemState& problem_state) const = 0;
62 
63  // Return status of the Optimize() function below.
64  //
65  // TODO(user): To redesign, some are not needed anymore thanks to the
66  // problem state, e.g. IsOptimal().
67  enum Status {
72 
73  // Some information was learned and the problem state will need to be
74  // updated. This will trigger a new optimization round.
75  //
76  // TODO(user): replace by learned_info->IsEmpty()? but we will need to clear
77  // the BopSolution there first.
79 
80  // This optimizer didn't learn any information yet but can be called again
81  // on the same problem state to resume its work.
83 
84  // There is no need to call this optimizer again on the same problem state.
85  ABORT
86  };
87 
88  // Tries to infer more information about the problem state, i.e. reduces the
89  // gap by increasing the lower bound or finding a better solution.
90  // Returns SOLUTION_FOUND when a new solution with a better objective cost is
91  // found before a time limit.
92  // The learned information is cleared and the filled with any new information
93  // about the problem, e.g. a new lower bound.
94  //
95  // Preconditions: ShouldBeRun() must returns true.
96  virtual Status Optimize(const BopParameters& parameters,
97  const ProblemState& problem_state,
98  LearnedInfo* learned_info, TimeLimit* time_limit) = 0;
99 
100  // Returns a string describing the status.
101  static std::string GetStatusString(Status status);
102 
103  protected:
104  const std::string name_;
105 
107 };
108 
109 inline std::ostream& operator<<(std::ostream& os,
112  return os;
113 }
114 
115 // This class represents the current state of the problem with all the
116 // information that the solver learned about it at a given time.
118  public:
119  explicit ProblemState(const sat::LinearBooleanProblem& problem);
120 
121  // Sets parameters, used for instance to get the tolerance, the gap limit...
122  void SetParameters(const BopParameters& parameters) {
123  parameters_ = parameters;
124  }
125 
126  const BopParameters& GetParameters() const { return parameters_; }
127 
128  // Sets an assignment preference for each variable.
129  // This is only used for warm start.
130  void set_assignment_preference(const std::vector<bool>& a) {
131  assignment_preference_ = a;
132  }
133  const std::vector<bool> assignment_preference() const {
134  return assignment_preference_;
135  }
136 
137  // Merges the learned information with the current problem state. For
138  // instance, if variables x, and y are fixed in the current state, and z is
139  // learned to be fixed, the result of the merge will be x, y, and z being
140  // fixed in the problem state.
141  // Note that the LP values contained in the learned information (if any)
142  // will replace the LP values of the problem state, whatever the cost is.
143  // Returns true when the merge has changed the problem state.
144  bool MergeLearnedInfo(const LearnedInfo& learned_info,
145  BopOptimizerBase::Status optimization_status);
146 
147  // Returns all the information learned so far.
148  // TODO(user): In the current implementation the learned information only
149  // contains binary clauses added since the last call to
150  // SynchronizationDone().
151  // Add an iterator on the sat::BinaryClauseManager.
152  LearnedInfo GetLearnedInfo() const;
153 
154  // The stamp represents an upper bound on the number of times the problem
155  // state has been updated. If the stamp changed since last time one has
156  // checked the state, it's worth trying again as it might have changed
157  // (no guarantee).
158  static const int64_t kInitialStampValue;
159  int64_t update_stamp() const { return update_stamp_; }
160 
161  // Marks the problem state as optimal.
162  void MarkAsOptimal();
163 
164  // Marks the problem state as infeasible.
165  void MarkAsInfeasible();
166 
167  // Returns true when the current state is proved to be optimal. In such a case
168  // solution() returns the optimal solution.
169  bool IsOptimal() const {
170  return solution_.IsFeasible() && solution_.GetCost() == lower_bound();
171  }
172 
173  // Returns true when the problem is proved to be infeasible.
174  bool IsInfeasible() const { return lower_bound() > upper_bound(); }
175 
176  // Returns true when the variable var is fixed in the current problem state.
177  // The value of the fixed variable is returned by GetVariableFixedValue(var).
178  bool IsVariableFixed(VariableIndex var) const { return is_fixed_[var]; }
180  return is_fixed_;
181  }
182 
183  // Returns the value of the fixed variable var. Should be only called on fixed
184  // variables (CHECKed).
185  bool GetVariableFixedValue(VariableIndex var) const {
186  return fixed_values_[var];
187  }
189  return fixed_values_;
190  }
191 
192  // Returns the values of the LP relaxation of the problem. Returns an empty
193  // vector when the LP has not been populated.
194  const glop::DenseRow& lp_values() const { return lp_values_; }
195 
196  // Returns the solution to the current state problem.
197  // Note that the solution might not be feasible because until we find one, it
198  // will just be the all-false assignment.
199  const BopSolution& solution() const { return solution_; }
200 
201  // Returns the original problem. Note that the current problem might be
202  // different, e.g. fixed variables, but equivalent, i.e. a solution to one
203  // should be a solution to the other too.
204  const sat::LinearBooleanProblem& original_problem() const {
205  return original_problem_;
206  }
207 
208  // Returns the current lower (resp. upper) bound of the objective cost.
209  // For internal use only: this is the unscaled version of the lower (resp.
210  // upper) bound, and so should be compared only to the unscaled cost given by
211  // solution.GetCost().
212  int64_t lower_bound() const { return lower_bound_; }
213  int64_t upper_bound() const { return upper_bound_; }
214 
215  // Returns the scaled lower bound of the original problem.
216  double GetScaledLowerBound() const {
217  return (lower_bound() + original_problem_.objective().offset()) *
218  original_problem_.objective().scaling_factor();
219  }
220 
221  // Returns the newly added binary clause since the last SynchronizationDone().
222  const std::vector<sat::BinaryClause>& NewlyAddedBinaryClauses() const;
223 
224  // Resets what is considered "new" information. This is meant to be called
225  // once all the optimize have been synchronized.
226  void SynchronizationDone();
227 
228  private:
229  const sat::LinearBooleanProblem& original_problem_;
230  BopParameters parameters_;
231  int64_t update_stamp_;
234  glop::DenseRow lp_values_;
235  BopSolution solution_;
236  std::vector<bool> assignment_preference_;
237 
238  int64_t lower_bound_;
239  int64_t upper_bound_;
240 
241  // Manage the set of the problem binary clauses (including the learned ones).
242  sat::BinaryClauseManager binary_clause_manager_;
243 
244  DISALLOW_COPY_AND_ASSIGN(ProblemState);
245 };
246 
247 // This struct represents what has been learned on the problem state by
248 // running an optimizer. The goal is then to merge the learned information
249 // with the problem state in order to get a more constrained problem to be used
250 // by the next called optimizer.
251 struct LearnedInfo {
252  explicit LearnedInfo(const sat::LinearBooleanProblem& problem)
253  : fixed_literals(),
254  solution(problem, "AllZero"),
255  lower_bound(std::numeric_limits<int64_t>::min()),
256  lp_values(),
257  binary_clauses() {}
258 
259  // Clears all just as if the object were a brand new one. This can be used
260  // to reduce the number of creation / deletion of objects.
261  void Clear() {
262  fixed_literals.clear();
264  lp_values.clear();
265  binary_clauses.clear();
266  }
267 
268  // Vector of all literals that have been fixed.
269  std::vector<sat::Literal> fixed_literals;
270 
271  // New solution. Note that the solution might be infeasible.
273 
274  // A lower bound (for multi-threading purpose).
275  int64_t lower_bound;
276 
277  // An assignment for the relaxed linear programming problem (can be empty).
278  // This is meant to be the optimal LP solution, but can just be a feasible
279  // solution or any floating point assignment if the LP solver didn't solve
280  // the relaxed problem optimally.
282 
283  // New binary clauses.
284  std::vector<sat::BinaryClause> binary_clauses;
285 };
286 } // namespace bop
287 } // namespace operations_research
288 #endif // OR_TOOLS_BOP_BOP_BASE_H_
int64_t min
Definition: alldiff_cst.cc:139
A simple class to enforce both an elapsed time limit and a deterministic time limit in the same threa...
Definition: time_limit.h:106
static std::string GetStatusString(Status status)
Definition: bop_base.cc:41
virtual Status Optimize(const BopParameters &parameters, const ProblemState &problem_state, LearnedInfo *learned_info, TimeLimit *time_limit)=0
BopOptimizerBase(absl::string_view name)
Definition: bop_base.cc:32
virtual bool ShouldBeRun(const ProblemState &problem_state) const =0
const std::string & name() const
Definition: bop_base.h:52
const BopParameters & GetParameters() const
Definition: bop_base.h:126
const sat::LinearBooleanProblem & original_problem() const
Definition: bop_base.h:204
const std::vector< bool > assignment_preference() const
Definition: bop_base.h:133
const glop::DenseRow & lp_values() const
Definition: bop_base.h:194
bool MergeLearnedInfo(const LearnedInfo &learned_info, BopOptimizerBase::Status optimization_status)
Definition: bop_base.cc:94
const std::vector< sat::BinaryClause > & NewlyAddedBinaryClauses() const
Definition: bop_base.cc:251
LearnedInfo GetLearnedInfo() const
Definition: bop_base.cc:217
bool IsVariableFixed(VariableIndex var) const
Definition: bop_base.h:178
static const int64_t kInitialStampValue
Definition: bop_base.h:158
bool GetVariableFixedValue(VariableIndex var) const
Definition: bop_base.h:185
void SetParameters(const BopParameters &parameters)
Definition: bop_base.h:122
ProblemState(const sat::LinearBooleanProblem &problem)
Definition: bop_base.cc:69
const BopSolution & solution() const
Definition: bop_base.h:199
void set_assignment_preference(const std::vector< bool > &a)
Definition: bop_base.h:130
const absl::StrongVector< VariableIndex, bool > & is_fixed() const
Definition: bop_base.h:179
const absl::StrongVector< VariableIndex, bool > & fixed_values() const
Definition: bop_base.h:188
int64_t a
SatParameters parameters
ModelSharedTimeLimit * time_limit
IntVar * var
Definition: expr_array.cc:1874
absl::Status status
Definition: g_gurobi.cc:41
std::ostream & operator<<(std::ostream &os, BopOptimizerBase::Status status)
Definition: bop_base.h:109
Collection of objects used to extend the Constraint Solver library.
std::vector< sat::Literal > fixed_literals
Definition: bop_base.h:269
LearnedInfo(const sat::LinearBooleanProblem &problem)
Definition: bop_base.h:252
std::vector< sat::BinaryClause > binary_clauses
Definition: bop_base.h:284