19#include "absl/status/statusor.h"
35#if defined(PROTOBUF_INTERNAL_IMPL)
36using google::protobuf::Message;
38using google::protobuf::Message;
45constexpr bool kProtoLiteSatParameters =
81MPSolutionResponse InfeasibleResponse(SolverLogger& logger,
85 if (logger.LoggingIsEnabled()) {
86 sat::CpSolverResponse cp_response;
95MPSolutionResponse ModelInvalidResponse(SolverLogger& logger,
99 if (logger.LoggingIsEnabled()) {
100 sat::CpSolverResponse cp_response;
113 std::function<
void(
const std::string&)> logging_callback,
114 std::function<
void(
const MPSolution&)> solution_callback) {
120 if (kProtoLiteSatParameters) {
122 return absl::InvalidArgumentError(
123 "solver_specific_parameters is not a valid binary stream of the "
124 "SatParameters proto");
129 return absl::InvalidArgumentError(
130 "solver_specific_parameters is not a valid textual representation "
131 "of the SatParameters proto");
146 if (logging_callback !=
nullptr) {
175 return ModelInvalidResponse(logger,
"Extra CP-SAT validation failed.");
180 return InfeasibleResponse(logger,
181 "An integer variable has an empty domain");
187 std::vector<std::unique_ptr<glop::Preprocessor>> for_postsolve;
196 return InfeasibleResponse(
197 logger,
"Problem proven infeasible during MIP presolve");
199 return ModelInvalidResponse(
200 logger,
"Problem detected invalid during MIP presolve");
213 "Problem proven infeasible or unbounded during MIP presolve");
223 SOLVER_LOG(&logger,
"Scaling to pure integer problem.");
226 std::vector<double> var_scaling(num_variables, 1.0);
230 return InfeasibleResponse(
231 logger,
"A detected integer variable has an empty domain");
237 for (
int i = 0; i < var_scaling.size(); ++i) {
238 var_scaling[i] *= other_scaling[i];
252 response.set_status_str(
"Failed to convert model into CP-SAT model");
262 for (
int i = 0; i < size; ++i) {
264 if (
var >= var_scaling.size())
continue;
275 cp_model_hint->add_vars(
var);
276 cp_model_hint->add_values(
static_cast<int64_t
>(std::round(
value)));
281 const int old_num_variables = mp_model->
variable().size();
282 const int old_num_constraints = mp_model->
constraint().size();
289 if (interrupt_solve !=
nullptr) {
299 (glop::ColIndex(old_num_variables)));
302 static_cast<double>(cp_response.solution(v)) / var_scaling[v];
304 for (
int i = for_postsolve.size(); --i >= 0;) {
305 for_postsolve[i]->RecoverSolution(&glop_solution);
314 if (solution_callback !=
nullptr) {
317 solution_callback(post_solve(cp_response));
334 MPSolution post_solved_solution = post_solve(cp_response);
335 *
response.mutable_variable_value() =
345 MPSolution post_solved_solution = post_solve(temp);
346 *(
response.add_additional_solutions()->mutable_variable_value()) =
354 if (kProtoLiteSatParameters) {
#define DCHECK_EQ(val1, val2)
const ::operations_research::MPConstraintProto & constraint(int index) const
int variable_size() const
const ::operations_research::MPVariableProto & variable(int index) const
const ::operations_research::PartialVariableAssignment & solution_hint() const
bool has_solution_hint() const
double solver_time_limit_seconds() const
::operations_research::MPModelProto * mutable_model()
bool enable_internal_solver_output() const
const std::string & solver_specific_parameters() const
bool has_solver_specific_parameters() const
bool has_solver_time_limit_seconds() const
PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final
const ::operations_research::MPModelProto & model() const
void add_variable_value(double value)
::PROTOBUF_NAMESPACE_ID::RepeatedField< double > * mutable_variable_value()
void set_objective_value(double value)
double var_value(int index) const
int32_t var_index(int index) const
void SetLogToStdOut(bool enable)
bool LoggingIsEnabled() const
void AddInfoLoggingCallback(std::function< void(const std::string &message)> callback)
void EnableLogging(bool enable)
A simple class to enforce both an elapsed time limit and a deterministic time limit in the same threa...
const ::operations_research::sat::IntegerVariableProto & variables(int index) const
bool has_objective() const
::operations_research::sat::PartialVariableAssignment * mutable_solution_hint()
double best_objective_bound() const
const ::operations_research::sat::CpSolverSolution & additional_solutions(int index) const
void set_status(::operations_research::sat::CpSolverStatus value)
double objective_value() const
::operations_research::sat::CpSolverStatus status() const
::PROTOBUF_NAMESPACE_ID::RepeatedField< int64_t > * mutable_solution()
int64_t values(int index) const
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).
bool log_search_progress() const
bool enumerate_all_solutions() const
bool mip_automatically_scale_variables() const
double mip_var_scaling() const
void set_log_search_progress(bool value)
double mip_max_bound() const
void set_max_time_in_seconds(double value)
bool log_to_stdout() const
SharedResponseManager * response
@ INFEASIBLE_OR_UNBOUNDED
std::function< void(Model *)> NewFeasibleSolutionObserver(const std::function< void(const CpSolverResponse &response)> &observer)
Creates a solution observer with the model with model.Add(NewFeasibleSolutionObserver([](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)
bool MPModelProtoValidationBeforeConversion(const SatParameters ¶ms, const MPModelProto &mp_model, SolverLogger *logger)
CpSolverResponse SolveCpModel(const CpModelProto &model_proto, Model *model)
Solves the given CpModelProto.
bool MakeBoundsOfIntegerVariablesInteger(const SatParameters ¶ms, MPModelProto *mp_model, SolverLogger *logger)
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)
glop::ProblemStatus ApplyMipPresolveSteps(const glop::GlopParameters &glop_params, MPModelProto *model, std::vector< std::unique_ptr< glop::Preprocessor > > *for_postsolve, SolverLogger *logger)
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 ¶meters)
@ MPSOLVER_UNKNOWN_STATUS
#define SOLVER_LOG(logger,...)