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