19 #include "absl/status/statusor.h"
35 #if defined(PROTOBUF_INTERNAL_IMPL)
36 using google::protobuf::Message;
38 using google::protobuf::Message;
45 constexpr
bool kProtoLiteSatParameters =
69 MPModelRequest request, std::atomic<bool>* interrupt_solve) {
72 sat::SatParameters params;
73 params.set_num_search_workers(8);
74 params.set_log_search_progress(request.enable_internal_solver_output());
75 if (request.has_solver_specific_parameters()) {
77 if (kProtoLiteSatParameters) {
78 if (!params.MergeFromString(request.solver_specific_parameters())) {
79 return absl::InvalidArgumentError(
80 "solver_specific_parameters is not a valid binary stream of the "
81 "SatParameters proto");
85 request.solver_specific_parameters(), ¶ms)) {
86 return absl::InvalidArgumentError(
87 "solver_specific_parameters is not a valid textual representation "
88 "of the SatParameters proto");
92 if (request.has_solver_time_limit_seconds()) {
93 params.set_max_time_in_seconds(
94 static_cast<double>(request.solver_time_limit_seconds()) / 1000.0);
112 sat::CpSolverResponse cp_response;
121 const glop::GlopParameters glop_params;
122 MPModelProto*
const mp_model = request.mutable_model();
123 std::vector<std::unique_ptr<glop::Preprocessor>> for_postsolve;
127 if (params.log_search_progress()) {
129 sat::CpSolverResponse cp_response;
134 response.set_status_str(
"Problem proven infeasible during MIP presolve");
142 SOLVER_LOG(&logger,
"Scaling to pure integer problem.");
144 const int num_variables = mp_model->variable_size();
145 std::vector<double> var_scaling(num_variables, 1.0);
146 if (params.mip_automatically_scale_variables()) {
149 if (params.mip_var_scaling() != 1.0) {
151 params.mip_var_scaling(), params.mip_max_bound(), mp_model);
152 for (
int i = 0; i < var_scaling.size(); ++i) {
153 var_scaling[i] *= other_scaling[i];
157 sat::CpModelProto cp_model;
160 if (params.log_search_progress()) {
162 sat::CpSolverResponse cp_response;
167 response.set_status_str(
"Failed to convert model into CP-SAT model");
170 DCHECK_EQ(cp_model.variables().size(), var_scaling.size());
171 DCHECK_EQ(cp_model.variables().size(), mp_model->variable().size());
174 if (request.model().has_solution_hint()) {
175 auto* cp_model_hint = cp_model.mutable_solution_hint();
176 const int size = request.model().solution_hint().var_index().size();
177 for (
int i = 0; i < size; ++i) {
178 const int var = request.model().solution_hint().var_index(i);
179 if (
var >= var_scaling.size())
continue;
185 request.model().solution_hint().var_value(i) * var_scaling[
var];
186 if (std::abs(
value) > params.mip_max_bound()) {
187 value =
value > 0 ? params.mip_max_bound() : -params.mip_max_bound();
190 cp_model_hint->add_vars(
var);
191 cp_model_hint->add_values(
static_cast<int64_t
>(std::round(
value)));
196 const int old_num_variables = mp_model->variable().size();
197 const int old_num_constraints = mp_model->constraint().size();
204 if (interrupt_solve !=
nullptr) {
210 const sat::CpSolverResponse cp_response =
217 ToMPSolverResponseStatus(cp_response.status(), cp_model.has_objective()));
220 response.set_objective_value(cp_response.objective_value());
221 response.set_best_objective_bound(cp_response.best_objective_bound());
225 (glop::ColIndex(old_num_variables)));
228 static_cast<double>(cp_response.solution(v)) / var_scaling[v];
230 for (
int i = for_postsolve.size(); --i >= 0;) {
231 for_postsolve[i]->RecoverSolution(&solution);
242 if (kProtoLiteSatParameters) {
#define DCHECK_EQ(val1, val2)
void SetLogToStdOut(bool enable)
bool LoggingIsEnabled() const
void EnableLogging(bool enable)
A simple class to enforce both an elapsed time limit and a deterministic time limit in the same threa...
Class that owns everything related to a particular optimization model.
T Add(std::function< T(Model *)> f)
This makes it possible to have a nicer API on the client side, and it allows both of these forms:
void Register(T *non_owned_class)
Register a non-owned class that will be "singleton" in the model.
T * GetOrCreate()
Returns an object of type T that is unique to this model (like a "local" singleton).
SharedResponseManager * response
std::function< SatParameters(Model *)> NewSatParameters(const std::string ¶ms)
Creates parameters for the solver, which you can add to the model with.
std::string CpSolverResponseStats(const CpSolverResponse &response, bool has_objective)
Returns a string with some statistics on the solver response.
void RemoveNearZeroTerms(const SatParameters ¶ms, MPModelProto *mp_model, SolverLogger *logger)
bool ConvertMPModelProtoToCpModelProto(const SatParameters ¶ms, const MPModelProto &mp_model, CpModelProto *cp_model, SolverLogger *logger)
CpSolverResponse SolveCpModel(const CpModelProto &model_proto, Model *model)
Solves the given CpModelProto.
std::vector< double > ScaleContinuousVariables(double scaling, double max_bound, MPModelProto *mp_model)
std::vector< double > DetectImpliedIntegers(MPModelProto *mp_model, SolverLogger *logger)
Collection of objects used to extend the Constraint Solver library.
bool ExtractValidMPModelInPlaceOrPopulateResponseStatus(MPModelRequest *request, MPSolutionResponse *response)
Like ExtractValidMPModelOrPopulateResponseStatus(), but works in-place: if the MPModel needed extract...
bool ProtobufTextFormatMergeFromString(const std::string &proto_text_string, ProtoType *proto)
MPSolverResponseStatus ApplyMipPresolveSteps(const glop::GlopParameters &glop_params, MPModelProto *model, std::vector< std::unique_ptr< glop::Preprocessor >> *for_postsolve, SolverLogger *logger)
std::string EncodeSatParametersAsString(const sat::SatParameters ¶meters)
absl::StatusOr< MPSolutionResponse > SatSolveProto(MPModelRequest request, std::atomic< bool > *interrupt_solve)
#define SOLVER_LOG(logger,...)