OR-Tools  9.1
sat_interface.cc
Go to the documentation of this file.
1 // Copyright 2010-2021 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 #include <atomic>
15 #include <cstdint>
16 #include <string>
17 #include <vector>
18 
19 #include "absl/status/status.h"
20 #include "absl/status/statusor.h"
21 #include "ortools/base/hash.h"
23 #include "ortools/base/logging.h"
30 #include "ortools/sat/lp_utils.h"
31 #include "ortools/sat/model.h"
33 
34 namespace operations_research {
35 
36 #if defined(PROTOBUF_INTERNAL_IMPL)
37 using google::protobuf::Message;
38 #else
39 using google::protobuf::Message;
40 #endif
41 
43  public:
44  explicit SatInterface(MPSolver* const solver);
45  ~SatInterface() override;
46 
47  // ----- Solve -----
48  MPSolver::ResultStatus Solve(const MPSolverParameters& param) override;
49  bool InterruptSolve() override;
50 
51  // ----- Model modifications and extraction -----
52  void Reset() override;
53  void SetOptimizationDirection(bool maximize) override;
54  void SetVariableBounds(int index, double lb, double ub) override;
55  void SetVariableInteger(int index, bool integer) override;
56  void SetConstraintBounds(int index, double lb, double ub) override;
57  void AddRowConstraint(MPConstraint* const ct) override;
58  void AddVariable(MPVariable* const var) override;
59  void SetCoefficient(MPConstraint* const constraint,
60  const MPVariable* const variable, double new_value,
61  double old_value) override;
62  void ClearConstraint(MPConstraint* const constraint) override;
63  void SetObjectiveCoefficient(const MPVariable* const variable,
64  double coefficient) override;
65  void SetObjectiveOffset(double value) override;
66  void ClearObjective() override;
67 
68  bool AddIndicatorConstraint(MPConstraint* const ct) override { return true; }
69 
70  // ------ Query statistics on the solution and the solve ------
71  int64_t iterations() const override;
72  int64_t nodes() const override;
73  MPSolver::BasisStatus row_status(int constraint_index) const override;
74  MPSolver::BasisStatus column_status(int variable_index) const override;
75 
76  // ----- Misc -----
77  bool IsContinuous() const override;
78  bool IsLP() const override;
79  bool IsMIP() const override;
80 
81  std::string SolverVersion() const override;
82  void* underlying_solver() override;
83 
84  void ExtractNewVariables() override;
85  void ExtractNewConstraints() override;
86  void ExtractObjective() override;
87 
88  void SetParameters(const MPSolverParameters& param) override;
89  void SetRelativeMipGap(double value) override;
90  void SetPrimalTolerance(double value) override;
91  void SetDualTolerance(double value) override;
92  void SetPresolveMode(int value) override;
93  void SetScalingMode(int value) override;
94  void SetLpAlgorithm(int value) override;
96  const std::string& parameters) override;
97  absl::Status SetNumThreads(int num_threads) override;
98 
99  private:
100  void NonIncrementalChange();
101 
102  std::atomic<bool> interrupt_solve_;
103  sat::SatParameters parameters_;
104  int num_threads_ = 8;
105 };
106 
108  : MPSolverInterface(solver), interrupt_solve_(false) {}
109 
111 
113  interrupt_solve_ = false;
114 
115  // Reset extraction as this interface is not incremental yet.
116  Reset();
117  ExtractModel();
118 
119  SetParameters(param);
121  solver_->solver_specific_parameter_string_);
122 
123  // Time limit.
124  if (solver_->time_limit()) {
125  VLOG(1) << "Setting time limit = " << solver_->time_limit() << " ms.";
126  parameters_.set_max_time_in_seconds(
127  static_cast<double>(solver_->time_limit()) / 1000.0);
128  }
129 
130  // Mark variables and constraints as extracted.
131  for (int i = 0; i < solver_->variables_.size(); ++i) {
132  set_variable_as_extracted(i, true);
133  }
134  for (int i = 0; i < solver_->constraints_.size(); ++i) {
136  }
137 
138  MPModelRequest request;
141  EncodeSatParametersAsString(parameters_));
143  const absl::StatusOr<MPSolutionResponse> status_or =
144  SatSolveProto(std::move(request), &interrupt_solve_);
145 
146  if (!status_or.ok()) return MPSolver::ABNORMAL;
147  const MPSolutionResponse& response = status_or.value();
148 
149  // The solution must be marked as synchronized even when no solution exists.
151  switch (response.status()) {
152  case MPSOLVER_OPTIMAL:
154  break;
155  case MPSOLVER_FEASIBLE:
157  break;
158  case MPSOLVER_INFEASIBLE:
160  break;
163  break;
164  default:
166  break;
167  }
168 
169  // TODO(user): Just use LoadSolutionFromProto(), but fix that function first
170  // to load everything and not just the solution.
171  if (response.status() == MPSOLVER_FEASIBLE ||
172  response.status() == MPSOLVER_OPTIMAL) {
173  objective_value_ = response.objective_value();
174  best_objective_bound_ = response.best_objective_bound();
175  const size_t num_vars = solver_->variables_.size();
176  for (int var_id = 0; var_id < num_vars; ++var_id) {
177  MPVariable* const var = solver_->variables_[var_id];
178  var->set_solution_value(response.variable_value(var_id));
179  }
180  }
181 
182  return result_status_;
183 }
184 
186  interrupt_solve_ = true;
187  return true;
188 }
189 
191 
193  NonIncrementalChange();
194 }
195 
196 void SatInterface::SetVariableBounds(int index, double lb, double ub) {
197  NonIncrementalChange();
198 }
199 
200 void SatInterface::SetVariableInteger(int index, bool integer) {
201  NonIncrementalChange();
202 }
203 
204 void SatInterface::SetConstraintBounds(int index, double lb, double ub) {
205  NonIncrementalChange();
206 }
207 
209  NonIncrementalChange();
210 }
211 
213  NonIncrementalChange();
214 }
215 
217  const MPVariable* const variable,
218  double new_value, double old_value) {
219  NonIncrementalChange();
220 }
221 
223  NonIncrementalChange();
224 }
225 
227  double coefficient) {
228  NonIncrementalChange();
229 }
230 
231 void SatInterface::SetObjectiveOffset(double value) { NonIncrementalChange(); }
232 
233 void SatInterface::ClearObjective() { NonIncrementalChange(); }
234 
235 int64_t SatInterface::iterations() const {
236  return 0; // FIXME
237 }
238 
239 int64_t SatInterface::nodes() const { return 0; }
240 
241 MPSolver::BasisStatus SatInterface::row_status(int constraint_index) const {
242  return MPSolver::BasisStatus::FREE; // FIXME
243 }
244 
246  return MPSolver::BasisStatus::FREE; // FIXME
247 }
248 
249 bool SatInterface::IsContinuous() const { return false; }
250 bool SatInterface::IsLP() const { return false; }
251 bool SatInterface::IsMIP() const { return true; }
252 
253 std::string SatInterface::SolverVersion() const {
254  return "SAT Based MIP Solver";
255 }
256 
257 void* SatInterface::underlying_solver() { return nullptr; }
258 
259 void SatInterface::ExtractNewVariables() { NonIncrementalChange(); }
260 
261 void SatInterface::ExtractNewConstraints() { NonIncrementalChange(); }
262 
263 void SatInterface::ExtractObjective() { NonIncrementalChange(); }
264 
266  // By default, we use 8 threads as it allows to try a good set of orthogonal
267  // parameters. This can be overridden by the user.
268  parameters_.set_num_search_workers(num_threads_);
269  parameters_.set_log_search_progress(!quiet_);
270  SetCommonParameters(param);
271 }
272 
273 absl::Status SatInterface::SetNumThreads(int num_threads) {
274  num_threads_ = num_threads;
275  return absl::OkStatus();
276 }
277 
278 // All these have no effect.
284 
285 // TODO(user): Implement me.
287 
289  const std::string& parameters) {
290  return ProtobufTextFormatMergeFromString(parameters, &parameters_);
291 }
292 
293 void SatInterface::NonIncrementalChange() {
294  // The current implementation is not incremental.
296 }
297 
298 // Register Sat in the global linear solver factory.
300  return new SatInterface(solver);
301 }
302 
303 } // namespace operations_research
ResultStatus
The status of solving the problem.
void SetConstraintBounds(int index, double lb, double ub) override
void set_variable_as_extracted(int var_index, bool extracted)
void SetVariableBounds(int index, double lb, double ub) override
void SetPrimalTolerance(double value) override
SatInterface(MPSolver *const solver)
absl::StatusOr< MPSolutionResponse > SatSolveProto(MPModelRequest request, std::atomic< bool > *interrupt_solve, std::function< void(const std::string &)> logging_callback)
void set_constraint_as_extracted(int ct_index, bool extracted)
void SetParameters(const MPSolverParameters &param) override
#define VLOG(verboselevel)
Definition: base/logging.h:979
MPSolver::ResultStatus Solve(const MPSolverParameters &param) override
void SetPresolveMode(int value) override
A C++ wrapper that provides a simple and unified interface to several linear programming and mixed in...
void SetObjectiveOffset(double value) override
int64_t nodes() const override
std::string SolverVersion() const override
void set_solver_specific_parameters(ArgT0 &&arg0, ArgT... args)
BasisStatus
Advanced usage: possible basis status values for a variable and the slack variable of a linear constr...
int64_t coefficient
bool ProtobufTextFormatMergeFromString(const std::string &proto_text_string, ProtoType *proto)
void SetObjectiveCoefficient(const MPVariable *const variable, double coefficient) override
void SetScalingMode(int value) override
void AddVariable(MPVariable *const var) override
int64_t iterations() const override
The class for variables of a Mathematical Programming (MP) model.
MPSolver::BasisStatus row_status(int constraint_index) const override
bool SetSolverSpecificParametersAsString(const std::string &parameters)
Advanced usage: pass solver specific parameters in text format.
void SetRelativeMipGap(double value) override
the model is trivially invalid (NaN coefficients, etc).
absl::Status SetNumThreads(int num_threads) override
MPSolver::BasisStatus column_status(int variable_index) const override
bool AddIndicatorConstraint(MPConstraint *const ct) override
void SetCommonParameters(const MPSolverParameters &param)
bool SetSolverSpecificParametersAsString(const std::string &parameters) override
void SetDualTolerance(double value) override
int index
Definition: pack.cc:509
The class for constraints of a Mathematical Programming (MP) model.
feasible, or stopped by limit.
void SetVariableInteger(int index, bool integer) override
void set_num_search_workers(::PROTOBUF_NAMESPACE_ID::int32 value)
SharedResponseManager * response
void SetLpAlgorithm(int value) override
::operations_research::MPModelProto * mutable_model()
void SetOptimizationDirection(bool maximize) override
std::string EncodeSatParametersAsString(const sat::SatParameters &parameters)
void set_enable_internal_solver_output(bool value)
MPSolverInterface * BuildSatInterface(MPSolver *const solver)
This mathematical programming (MP) solver class is the main class though which users build and solve ...
Collection of objects used to extend the Constraint Solver library.
abnormal, i.e., error of some kind.
SatParameters parameters
This class stores parameter settings for LP and MIP solvers.
bool IsContinuous() const override
void SetCoefficient(MPConstraint *const constraint, const MPVariable *const variable, double new_value, double old_value) override
IntVar * var
Definition: expr_array.cc:1874
void ExportModelToProto(MPModelProto *output_model) const
Exports model to protocol buffer.
void ClearConstraint(MPConstraint *const constraint) override
int64_t value
void AddRowConstraint(MPConstraint *const ct) override
const Constraint * ct