25 #include "absl/memory/memory.h"
26 #include "absl/status/status.h"
27 #include "absl/status/statusor.h"
28 #include "absl/strings/str_cat.h"
29 #include "absl/strings/str_join.h"
30 #include "absl/time/time.h"
33 #include "ortools/math_opt/callback.pb.h"
35 #include "ortools/math_opt/model.pb.h"
36 #include "ortools/math_opt/model_parameters.pb.h"
37 #include "ortools/math_opt/model_update.pb.h"
38 #include "ortools/math_opt/parameters.pb.h"
40 #include "ortools/math_opt/result.pb.h"
41 #include "ortools/math_opt/solution.pb.h"
43 #include "ortools/math_opt/sparse_containers.pb.h"
54 constexpr
double kInf = std::numeric_limits<double>::infinity();
56 void SetTrivialBounds(
const bool maximize, SolveStatsProto& stats) {
57 stats.set_best_primal_bound(maximize ? -
kInf :
kInf);
58 stats.set_best_dual_bound(maximize ?
kInf : -
kInf);
63 std::vector<std::string> SetSolveParameters(
64 const SolveParametersProto&
parameters, MPModelRequest& request) {
65 std::vector<std::string> warnings;
66 const CommonSolveParametersProto& common_parameters =
68 if (common_parameters.has_time_limit()) {
69 request.set_solver_time_limit_seconds(absl::ToDoubleSeconds(
73 if (common_parameters.has_enable_output()) {
74 request.set_enable_internal_solver_output(
75 common_parameters.enable_output());
85 sat::SatParameters sat_parameters;
86 if (common_parameters.has_random_seed()) {
87 sat_parameters.set_random_seed(common_parameters.random_seed());
89 if (common_parameters.has_threads()) {
90 sat_parameters.set_num_search_workers(common_parameters.threads());
92 if (common_parameters.lp_algorithm() != LP_ALGORITHM_UNSPECIFIED) {
94 absl::StrCat(
"Setting the LP Algorithm (was set to ",
96 ") is not supported for CP_SAT solver"));
98 if (common_parameters.presolve() != EMPHASIS_UNSPECIFIED) {
99 switch (common_parameters.presolve()) {
101 sat_parameters.set_cp_model_presolve(
false);
104 case EMPHASIS_MEDIUM:
106 case EMPHASIS_VERY_HIGH:
107 sat_parameters.set_cp_model_presolve(
true);
112 <<
" unknown, error setting CP-SAT parameters";
115 if (common_parameters.scaling() != EMPHASIS_UNSPECIFIED) {
117 absl::StrCat(
"Setting the scaling (was set to ",
119 ") is not supported for CP_SAT solver"));
121 if (common_parameters.cuts() != EMPHASIS_UNSPECIFIED) {
122 switch (common_parameters.cuts()) {
126 sat_parameters.set_add_cg_cuts(
false);
127 sat_parameters.set_add_mir_cuts(
false);
128 sat_parameters.set_add_zero_half_cuts(
false);
129 sat_parameters.set_add_clique_cuts(
false);
130 sat_parameters.set_max_all_diff_cut_size(0);
131 sat_parameters.set_add_lin_max_cuts(
false);
134 case EMPHASIS_MEDIUM:
136 case EMPHASIS_VERY_HIGH:
141 <<
" unknown, error setting CP-SAT parameters";
144 if (common_parameters.heuristics() != EMPHASIS_UNSPECIFIED) {
146 absl::StrCat(
"Setting the heuristics (was set to ",
148 ") is not supported for CP_SAT solver"));
150 sat_parameters.MergeFrom(
parameters.cp_sat_parameters());
151 request.set_solver_specific_parameters(
159 const ModelProto&
model,
const SolverInitializerProto& initializer) {
163 model.variables().ids().end());
165 return absl::WrapUnique(
171 const ModelSolveParametersProto& model_parameters,
172 const CallbackRegistrationProto& callback_registration,
const Callback cb) {
173 SolveResultProto result;
177 *req.mutable_model() = cp_sat_model_;
178 req.set_solver_type(MPModelRequest::SAT_INTEGER_PROGRAMMING);
180 std::vector<std::string> param_warnings =
182 if (!param_warnings.empty()) {
183 if (
parameters.common_parameters().strictness().bad_parameter()) {
184 return absl::InvalidArgumentError(absl::StrJoin(param_warnings,
"; "));
186 for (std::string& warning : param_warnings) {
187 result.add_warnings(std::move(warning));
202 : SolveResultProto::OTHER_LIMIT);
203 result.set_termination_detail(
response.status_str());
204 result.mutable_solve_stats()->set_best_primal_bound(
206 result.mutable_solve_stats()->set_best_dual_bound(
208 *result.add_primal_solutions() =
209 ExtractSolution(
response, model_parameters);
214 result.set_termination_detail(
response.status_str());
215 SetTrivialBounds(cp_sat_model_.maximize(), *result.mutable_solve_stats());
218 result.set_termination_reason(SolveResultProto::OTHER_LIMIT);
219 result.set_termination_detail(
response.status_str());
220 SetTrivialBounds(cp_sat_model_.maximize(), *result.mutable_solve_stats());
223 return absl::InternalError(
224 absl::StrCat(
"cp-sat solver returned MODEL_INVALID, details: ",
227 return absl::InternalError(
228 absl::StrCat(
"unexpected solve status: ",
response.status()));
241 return absl::InternalError(
"CP-SAT solver does not support incrementalism");
244 CpSatSolver::CpSatSolver(MPModelProto cp_sat_model,
246 : cp_sat_model_(std::move(cp_sat_model)),
249 PrimalSolutionProto CpSatSolver::ExtractSolution(
251 const ModelSolveParametersProto& model_parameters)
const {
252 PrimalSolutionProto solution;
254 solution.set_objective_value(
response.objective_value());
260 SparseVectorFilterPredicate predicate(
261 model_parameters.primal_variables_filter());
262 auto*
const values = solution.mutable_variable_values();
263 for (
int i = 0; i < variable_ids_.size(); ++i) {
264 const int64_t
id = variable_ids_[i];
266 if (predicate.AcceptsAndUpdate(
id,
value)) {
268 values->add_values(
value);
#define CHECK_EQ(val1, val2)
bool CanUpdate(const ModelUpdateProto &model_update) override
absl::Status Update(const ModelUpdateProto &model_update) override
absl::StatusOr< SolveResultProto > Solve(const SolveParametersProto ¶meters, const ModelSolveParametersProto &model_parameters, const CallbackRegistrationProto &callback_registration, Callback cb) override
static absl::StatusOr< std::unique_ptr< SolverInterface > > New(const ModelProto &model, const SolverInitializerProto &initializer)
std::function< absl::StatusOr< CallbackResultProto >(const CallbackDataProto &)> Callback
SharedResponseManager * response
absl::Span< const int64_t > variable_ids
MATH_OPT_REGISTER_SOLVER(SOLVER_TYPE_CP_SAT, CpSatSolver::New)
absl::StatusOr<::operations_research::MPModelProto > MathOptModelToMPModelProto(const ::operations_research::math_opt::ModelProto &model)
Collection of objects used to extend the Constraint Solver library.
std::string ProtoEnumToString(ProtoEnumType enum_value)
std::string EncodeSatParametersAsString(const sat::SatParameters ¶meters)
absl::StatusOr< MPSolutionResponse > SatSolveProto(MPModelRequest request, std::atomic< bool > *interrupt_solve)
inline ::absl::StatusOr< absl::Duration > DecodeGoogleApiProto(const google::protobuf::Duration &proto)
#define ASSIGN_OR_RETURN(lhs, rexpr)