OR-Tools  9.2
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/base/attributes.h"
20 #include "absl/status/status.h"
21 #include "absl/status/statusor.h"
22 #include "ortools/base/hash.h"
24 #include "ortools/base/logging.h"
31 #include "ortools/sat/lp_utils.h"
32 #include "ortools/sat/model.h"
34 
35 namespace operations_research {
36 
37 #if defined(PROTOBUF_INTERNAL_IMPL)
38 using google::protobuf::Message;
39 #else
40 using google::protobuf::Message;
41 #endif
42 
44  public:
45  explicit SatInterface(MPSolver* const solver);
46  ~SatInterface() override;
47 
48  // ----- Solve -----
49  MPSolver::ResultStatus Solve(const MPSolverParameters& param) override;
50  absl::optional<MPSolutionResponse> DirectlySolveProto(
51  const MPModelRequest& request, std::atomic<bool>* interrupt) override;
52  bool InterruptSolve() override;
53 
54  // ----- Model modifications and extraction -----
55  void Reset() override;
56  void SetOptimizationDirection(bool maximize) override;
57  void SetVariableBounds(int index, double lb, double ub) override;
58  void SetVariableInteger(int index, bool integer) override;
59  void SetConstraintBounds(int index, double lb, double ub) override;
60  void AddRowConstraint(MPConstraint* const ct) override;
61  void AddVariable(MPVariable* const var) override;
62  void SetCoefficient(MPConstraint* const constraint,
63  const MPVariable* const variable, double new_value,
64  double old_value) override;
65  void ClearConstraint(MPConstraint* const constraint) override;
66  void SetObjectiveCoefficient(const MPVariable* const variable,
67  double coefficient) override;
68  void SetObjectiveOffset(double value) override;
69  void ClearObjective() override;
70 
71  bool AddIndicatorConstraint(MPConstraint* const ct) override { return true; }
72 
73  // ------ Query statistics on the solution and the solve ------
74  int64_t iterations() const override;
75  int64_t nodes() const override;
76  MPSolver::BasisStatus row_status(int constraint_index) const override;
77  MPSolver::BasisStatus column_status(int variable_index) const override;
78 
79  // ----- Misc -----
80  bool IsContinuous() const override;
81  bool IsLP() const override;
82  bool IsMIP() const override;
83 
84  std::string SolverVersion() const override;
85  void* underlying_solver() override;
86 
87  void ExtractNewVariables() override;
88  void ExtractNewConstraints() override;
89  void ExtractObjective() override;
90 
91  void SetParameters(const MPSolverParameters& param) override;
92  void SetRelativeMipGap(double value) override;
93  void SetPrimalTolerance(double value) override;
94  void SetDualTolerance(double value) override;
95  void SetPresolveMode(int value) override;
96  void SetScalingMode(int value) override;
97  void SetLpAlgorithm(int value) override;
99  const std::string& parameters) override;
100  absl::Status SetNumThreads(int num_threads) override;
101 
102  private:
103  void NonIncrementalChange();
104 
105  std::atomic<bool> interrupt_solve_;
106  sat::SatParameters parameters_;
107  int num_threads_ = 0;
108 };
109 
111  : MPSolverInterface(solver), interrupt_solve_(false) {}
112 
114 
116  interrupt_solve_ = false;
117 
118  // Reset extraction as this interface is not incremental yet.
119  Reset();
120  ExtractModel();
121 
122  SetParameters(param);
124  solver_->solver_specific_parameter_string_);
125 
126  // Time limit.
127  if (solver_->time_limit()) {
128  VLOG(1) << "Setting time limit = " << solver_->time_limit() << " ms.";
129  parameters_.set_max_time_in_seconds(
130  static_cast<double>(solver_->time_limit()) / 1000.0);
131  }
132 
133  // Mark variables and constraints as extracted.
134  for (int i = 0; i < solver_->variables_.size(); ++i) {
135  set_variable_as_extracted(i, true);
136  }
137  for (int i = 0; i < solver_->constraints_.size(); ++i) {
139  }
140 
141  MPModelRequest request;
144  EncodeSatParametersAsString(parameters_));
146  const absl::StatusOr<MPSolutionResponse> status_or =
147  SatSolveProto(std::move(request), &interrupt_solve_);
148 
149  if (!status_or.ok()) return MPSolver::ABNORMAL;
150  const MPSolutionResponse& response = status_or.value();
151 
152  // The solution must be marked as synchronized even when no solution exists.
154  result_status_ = static_cast<MPSolver::ResultStatus>(response.status());
155 
156  if (response.status() == MPSOLVER_FEASIBLE ||
157  response.status() == MPSOLVER_OPTIMAL) {
158  const absl::Status result = solver_->LoadSolutionFromProto(response);
159  if (!result.ok()) {
160  LOG(ERROR) << "LoadSolutionFromProto failed: " << result;
161  }
162  }
163 
164  return result_status_;
165 }
166 
167 absl::optional<MPSolutionResponse> SatInterface::DirectlySolveProto(
168  const MPModelRequest& request, std::atomic<bool>* interrupt) {
169  absl::StatusOr<MPSolutionResponse> status_or =
170  SatSolveProto(request, interrupt);
171  if (status_or.ok()) return std::move(status_or).value();
172  if (request.enable_internal_solver_output()) {
173  LOG(INFO) << "Failed SAT solve: " << status_or.status();
174  }
176  // As of 2021-08, the sole non-OK status returned by SatSolveProto is an
177  // INVALID_ARGUMENT error caused by invalid solver parameters.
178  // TODO(user): Move that conversion to SatSolveProto, which should always
179  // return a MPSolutionResponse, even for errors.
180  response.set_status(absl::IsInvalidArgument(status_or.status())
183  response.set_status_str(status_or.status().ToString());
184  return response;
185 }
186 
188  interrupt_solve_ = true;
189  return true;
190 }
191 
193 
195  NonIncrementalChange();
196 }
197 
198 void SatInterface::SetVariableBounds(int index, double lb, double ub) {
199  NonIncrementalChange();
200 }
201 
202 void SatInterface::SetVariableInteger(int index, bool integer) {
203  NonIncrementalChange();
204 }
205 
206 void SatInterface::SetConstraintBounds(int index, double lb, double ub) {
207  NonIncrementalChange();
208 }
209 
211  NonIncrementalChange();
212 }
213 
215  NonIncrementalChange();
216 }
217 
219  const MPVariable* const variable,
220  double new_value, double old_value) {
221  NonIncrementalChange();
222 }
223 
225  NonIncrementalChange();
226 }
227 
229  double coefficient) {
230  NonIncrementalChange();
231 }
232 
233 void SatInterface::SetObjectiveOffset(double value) { NonIncrementalChange(); }
234 
235 void SatInterface::ClearObjective() { NonIncrementalChange(); }
236 
237 int64_t SatInterface::iterations() const {
238  return 0; // FIXME
239 }
240 
241 int64_t SatInterface::nodes() const { return 0; }
242 
243 MPSolver::BasisStatus SatInterface::row_status(int constraint_index) const {
244  return MPSolver::BasisStatus::FREE; // FIXME
245 }
246 
248  return MPSolver::BasisStatus::FREE; // FIXME
249 }
250 
251 bool SatInterface::IsContinuous() const { return false; }
252 bool SatInterface::IsLP() const { return false; }
253 bool SatInterface::IsMIP() const { return true; }
254 
255 std::string SatInterface::SolverVersion() const {
256  return "SAT Based MIP Solver";
257 }
258 
259 void* SatInterface::underlying_solver() { return nullptr; }
260 
261 void SatInterface::ExtractNewVariables() { NonIncrementalChange(); }
262 
263 void SatInterface::ExtractNewConstraints() { NonIncrementalChange(); }
264 
265 void SatInterface::ExtractObjective() { NonIncrementalChange(); }
266 
268  parameters_.set_num_search_workers(num_threads_);
269  SetCommonParameters(param);
270 }
271 
272 absl::Status SatInterface::SetNumThreads(int num_threads) {
273  num_threads_ = num_threads;
274  return absl::OkStatus();
275 }
276 
277 // All these have no effect.
283 
284 // TODO(user): Implement me.
286 
288  const std::string& parameters) {
289  return ProtobufTextFormatMergeFromString(parameters, &parameters_);
290 }
291 
292 void SatInterface::NonIncrementalChange() {
293  // The current implementation is not incremental.
295 }
296 
297 // Register Sat in the global linear solver factory.
299  return new SatInterface(solver);
300 }
301 
302 } // 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)
void set_constraint_as_extracted(int ct_index, bool extracted)
void SetParameters(const MPSolverParameters &param) override
#define VLOG(verboselevel)
Definition: base/logging.h:983
const int ERROR
Definition: log_severity.h:32
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
#define LOG(severity)
Definition: base/logging.h:420
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
absl::optional< MPSolutionResponse > DirectlySolveProto(const MPModelRequest &request, std::atomic< bool > *interrupt) override
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
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.
void SetVariableInteger(int index, bool integer) override
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.
absl::StatusOr< MPSolutionResponse > SatSolveProto(MPModelRequest request, std::atomic< bool > *interrupt_solve, std::function< void(const std::string &)> logging_callback, std::function< void(const MPSolution &)> solution_callback)
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
absl::Status LoadSolutionFromProto(const MPSolutionResponse &response, double tolerance=std::numeric_limits< double >::infinity())
Load a solution encoded in a protocol buffer onto this solver for easy access via the MPSolver interf...
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
const int INFO
Definition: log_severity.h:31