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"
31#include "ortools/sat/model.h"
33
34namespace operations_research {
35
36#if defined(PROTOBUF_INTERNAL_IMPL)
37using google::protobuf::Message;
38#else
39using 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 absl::optional<MPSolutionResponse> DirectlySolveProto(
50 const MPModelRequest& request, std::atomic<bool>* interrupt) override;
51 bool InterruptSolve() override;
52
53 // ----- Model modifications and extraction -----
54 void Reset() override;
55 void SetOptimizationDirection(bool maximize) override;
56 void SetVariableBounds(int index, double lb, double ub) override;
57 void SetVariableInteger(int index, bool integer) override;
58 void SetConstraintBounds(int index, double lb, double ub) override;
59 void AddRowConstraint(MPConstraint* const ct) override;
60 void AddVariable(MPVariable* const var) override;
61 void SetCoefficient(MPConstraint* const constraint,
62 const MPVariable* const variable, double new_value,
63 double old_value) override;
64 void ClearConstraint(MPConstraint* const constraint) override;
65 void SetObjectiveCoefficient(const MPVariable* const variable,
66 double coefficient) override;
67 void SetObjectiveOffset(double value) override;
68 void ClearObjective() override;
69
70 bool AddIndicatorConstraint(MPConstraint* const ct) override { return true; }
71
72 // ------ Query statistics on the solution and the solve ------
73 int64_t iterations() const override;
74 int64_t nodes() const override;
75 MPSolver::BasisStatus row_status(int constraint_index) const override;
76 MPSolver::BasisStatus column_status(int variable_index) const override;
77
78 // ----- Misc -----
79 bool IsContinuous() const override;
80 bool IsLP() const override;
81 bool IsMIP() const override;
82
83 std::string SolverVersion() const override;
84 void* underlying_solver() override;
85
86 void ExtractNewVariables() override;
87 void ExtractNewConstraints() override;
88 void ExtractObjective() override;
89
90 void SetParameters(const MPSolverParameters& param) override;
91 void SetRelativeMipGap(double value) override;
92 void SetPrimalTolerance(double value) override;
93 void SetDualTolerance(double value) override;
94 void SetPresolveMode(int value) override;
95 void SetScalingMode(int value) override;
96 void SetLpAlgorithm(int value) override;
98 const std::string& parameters) override;
99 absl::Status SetNumThreads(int num_threads) override;
100
101 private:
102 void NonIncrementalChange();
103
104 std::atomic<bool> interrupt_solve_;
105 sat::SatParameters parameters_;
106 int num_threads_ = 0;
107};
108
110 : MPSolverInterface(solver), interrupt_solve_(false) {}
111
113
115 interrupt_solve_ = false;
116
117 // Reset extraction as this interface is not incremental yet.
118 Reset();
119 ExtractModel();
120
121 SetParameters(param);
123 solver_->solver_specific_parameter_string_);
124
125 // Time limit.
126 if (solver_->time_limit()) {
127 VLOG(1) << "Setting time limit = " << solver_->time_limit() << " ms.";
128 parameters_.set_max_time_in_seconds(
129 static_cast<double>(solver_->time_limit()) / 1000.0);
130 }
131
132 // Mark variables and constraints as extracted.
133 for (int i = 0; i < solver_->variables_.size(); ++i) {
135 }
136 for (int i = 0; i < solver_->constraints_.size(); ++i) {
138 }
139
140 MPModelRequest request;
143 EncodeSatParametersAsString(parameters_));
145 const absl::StatusOr<MPSolutionResponse> status_or =
146 SatSolveProto(std::move(request), &interrupt_solve_);
147
148 if (!status_or.ok()) return MPSolver::ABNORMAL;
149 const MPSolutionResponse& response = status_or.value();
150
151 // The solution must be marked as synchronized even when no solution exists.
153 switch (response.status()) {
154 case MPSOLVER_OPTIMAL:
156 break;
159 break;
162 break;
165 break;
166 default:
168 break;
169 }
170
171 // TODO(user): Just use LoadSolutionFromProto(), but fix that function first
172 // to load everything and not just the solution.
173 if (response.status() == MPSOLVER_FEASIBLE ||
174 response.status() == MPSOLVER_OPTIMAL) {
175 objective_value_ = response.objective_value();
176 best_objective_bound_ = response.best_objective_bound();
177 const size_t num_vars = solver_->variables_.size();
178 for (int var_id = 0; var_id < num_vars; ++var_id) {
179 MPVariable* const var = solver_->variables_[var_id];
180 var->set_solution_value(response.variable_value(var_id));
181 }
182 }
183
184 return result_status_;
185}
186
187absl::optional<MPSolutionResponse> SatInterface::DirectlySolveProto(
188 const MPModelRequest& request, std::atomic<bool>* interrupt) {
189 absl::StatusOr<MPSolutionResponse> status_or =
190 SatSolveProto(request, interrupt);
191 if (status_or.ok()) return std::move(status_or).value();
192 if (request.enable_internal_solver_output()) {
193 LOG(INFO) << "Failed SAT solve: " << status_or.status();
194 }
196 // As of 2021-08, the sole non-OK status returned by SatSolveProto is an
197 // INVALID_ARGUMENT error caused by invalid solver parameters.
198 // TODO(user): Move that conversion to SatSolveProto, which should always
199 // return a MPSolutionResponse, even for errors.
200 response.set_status(absl::IsInvalidArgument(status_or.status())
203 response.set_status_str(status_or.status().ToString());
204 return response;
205}
206
208 interrupt_solve_ = true;
209 return true;
210}
211
213
215 NonIncrementalChange();
216}
217
218void SatInterface::SetVariableBounds(int index, double lb, double ub) {
219 NonIncrementalChange();
220}
221
223 NonIncrementalChange();
224}
225
226void SatInterface::SetConstraintBounds(int index, double lb, double ub) {
227 NonIncrementalChange();
228}
229
231 NonIncrementalChange();
232}
233
235 NonIncrementalChange();
236}
237
239 const MPVariable* const variable,
240 double new_value, double old_value) {
241 NonIncrementalChange();
242}
243
245 NonIncrementalChange();
246}
247
249 double coefficient) {
250 NonIncrementalChange();
251}
252
253void SatInterface::SetObjectiveOffset(double value) { NonIncrementalChange(); }
254
255void SatInterface::ClearObjective() { NonIncrementalChange(); }
256
258 return 0; // FIXME
259}
260
261int64_t SatInterface::nodes() const { return 0; }
262
264 return MPSolver::BasisStatus::FREE; // FIXME
265}
266
268 return MPSolver::BasisStatus::FREE; // FIXME
269}
270
271bool SatInterface::IsContinuous() const { return false; }
272bool SatInterface::IsLP() const { return false; }
273bool SatInterface::IsMIP() const { return true; }
274
275std::string SatInterface::SolverVersion() const {
276 return "SAT Based MIP Solver";
277}
278
279void* SatInterface::underlying_solver() { return nullptr; }
280
281void SatInterface::ExtractNewVariables() { NonIncrementalChange(); }
282
283void SatInterface::ExtractNewConstraints() { NonIncrementalChange(); }
284
285void SatInterface::ExtractObjective() { NonIncrementalChange(); }
286
288 parameters_.set_num_search_workers(num_threads_);
289 parameters_.set_linearization_level(2);
290 parameters_.set_log_search_progress(!quiet_);
291 SetCommonParameters(param);
292}
293
294absl::Status SatInterface::SetNumThreads(int num_threads) {
295 num_threads_ = num_threads;
296 return absl::OkStatus();
297}
298
299// All these have no effect.
305
306// TODO(user): Implement me.
308
310 const std::string& parameters) {
311 return ProtobufTextFormatMergeFromString(parameters, &parameters_);
312}
313
314void SatInterface::NonIncrementalChange() {
315 // The current implementation is not incremental.
317}
318
319// Register Sat in the global linear solver factory.
321 return new SatInterface(solver);
322}
323
324} // namespace operations_research
#define LOG(severity)
Definition: base/logging.h:416
#define VLOG(verboselevel)
Definition: base/logging.h:979
The class for constraints of a Mathematical Programming (MP) model.
::operations_research::MPModelProto * mutable_model()
void set_solver_specific_parameters(ArgT0 &&arg0, ArgT... args)
void set_enable_internal_solver_output(bool value)
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
absl::optional< MPSolutionResponse > DirectlySolveProto(const MPModelRequest &request, std::atomic< bool > *interrupt) 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
void set_linearization_level(::PROTOBUF_NAMESPACE_ID::int32 value)
void set_num_search_workers(::PROTOBUF_NAMESPACE_ID::int32 value)
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...
const int INFO
Definition: log_severity.h:31
Collection of objects used to extend the Constraint Solver library.
bool ProtobufTextFormatMergeFromString(const std::string &proto_text_string, ProtoType *proto)
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)
std::string EncodeSatParametersAsString(const sat::SatParameters &parameters)
MPSolverInterface * BuildSatInterface(MPSolver *const solver)
int index
Definition: pack.cc:509
int64_t coefficient