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