OR-Tools  9.0
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;
139  solver_->ExportModelToProto(request.mutable_model());
140  request.set_solver_specific_parameters(
141  EncodeSatParametersAsString(parameters_));
142  request.set_enable_internal_solver_output(!quiet_);
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
#define VLOG(verboselevel)
Definition: base/logging.h:986
The class for constraints of a Mathematical Programming (MP) model.
This mathematical programming (MP) solver class is the main class though which users build and solve ...
ResultStatus
The status of solving the problem.
@ FEASIBLE
feasible, or stopped by limit.
@ NOT_SOLVED
not been solved yet.
@ INFEASIBLE
proven infeasible.
@ ABNORMAL
abnormal, i.e., error of some kind.
@ MODEL_INVALID
the model is trivially invalid (NaN coefficients, etc).
bool SetSolverSpecificParametersAsString(const std::string &parameters)
Advanced usage: pass solver specific parameters in text format.
void ExportModelToProto(MPModelProto *output_model) const
Exports model to protocol buffer.
BasisStatus
Advanced usage: possible basis status values for a variable and the slack variable of a linear constr...
void set_constraint_as_extracted(int ct_index, bool extracted)
void set_variable_as_extracted(int var_index, bool extracted)
void SetCommonParameters(const MPSolverParameters &param)
This class stores parameter settings for LP and MIP solvers.
The class for variables of a Mathematical Programming (MP) model.
void SetScalingMode(int value) override
void SetDualTolerance(double value) override
void AddRowConstraint(MPConstraint *const ct) override
void SetLpAlgorithm(int value) override
SatInterface(MPSolver *const solver)
bool IsContinuous() const override
MPSolver::ResultStatus Solve(const MPSolverParameters &param) override
void SetPrimalTolerance(double value) override
void ClearConstraint(MPConstraint *const constraint) override
bool SetSolverSpecificParametersAsString(const std::string &parameters) override
void SetObjectiveCoefficient(const MPVariable *const variable, double coefficient) override
void SetCoefficient(MPConstraint *const constraint, const MPVariable *const variable, double new_value, double old_value) override
MPSolver::BasisStatus row_status(int constraint_index) const override
void SetObjectiveOffset(double value) override
void SetVariableInteger(int index, bool integer) override
void SetParameters(const MPSolverParameters &param) override
std::string SolverVersion() const override
void SetRelativeMipGap(double value) override
void SetConstraintBounds(int index, double lb, double ub) override
absl::Status SetNumThreads(int num_threads) override
void SetPresolveMode(int value) override
void SetVariableBounds(int index, double lb, double ub) override
void AddVariable(MPVariable *const var) override
int64_t nodes() const override
int64_t iterations() const override
bool AddIndicatorConstraint(MPConstraint *const ct) override
void SetOptimizationDirection(bool maximize) override
MPSolver::BasisStatus column_status(int variable_index) const override
SatParameters parameters
SharedResponseManager * response
const Constraint * ct
int64_t value
IntVar * var
Definition: expr_array.cc:1874
A C++ wrapper that provides a simple and unified interface to several linear programming and mixed in...
Collection of objects used to extend the Constraint Solver library.
bool ProtobufTextFormatMergeFromString(const std::string &proto_text_string, ProtoType *proto)
std::string EncodeSatParametersAsString(const sat::SatParameters &parameters)
MPSolverInterface * BuildSatInterface(MPSolver *const solver)
absl::StatusOr< MPSolutionResponse > SatSolveProto(MPModelRequest request, std::atomic< bool > *interrupt_solve)
int index
Definition: pack.cc:509
int64_t coefficient