25#include "absl/base/optimization.h"
26#include "absl/cleanup/cleanup.h"
27#include "absl/container/flat_hash_map.h"
28#include "absl/container/flat_hash_set.h"
29#include "absl/log/check.h"
30#include "absl/log/log.h"
31#include "absl/memory/memory.h"
32#include "absl/status/status.h"
33#include "absl/status/statusor.h"
34#include "absl/strings/str_cat.h"
35#include "absl/strings/str_format.h"
36#include "absl/strings/string_view.h"
37#include "absl/synchronization/mutex.h"
38#include "absl/types/span.h"
40#include "scip/cons_and.h"
41#include "scip/cons_indicator.h"
42#include "scip/cons_linear.h"
43#include "scip/cons_or.h"
44#if SCIP_VERSION_MAJOR >= 10
45#include "scip/cons_nonlinear.h"
46#define SCIPcreateConsQuadratic SCIPcreateConsQuadraticNonlinear
48#include "scip/cons_quadratic.h"
57#include "scip/cons_sos1.h"
58#include "scip/cons_sos2.h"
60#include "scip/pub_cons.h"
61#include "scip/pub_var.h"
62#include "scip/scip_cons.h"
63#include "scip/scip_general.h"
64#include "scip/scip_message.h"
65#include "scip/scip_numerics.h"
66#include "scip/scip_param.h"
67#include "scip/scip_prob.h"
68#include "scip/scip_sol.h"
69#include "scip/scip_solve.h"
70#include "scip/scip_solvingstats.h"
71#include "scip/scip_var.h"
72#include "scip/scipdefplugins.h"
73#include "scip/type_cons.h"
74#include "scip/type_event.h"
75#include "scip/type_paramset.h"
76#include "scip/type_prob.h"
77#include "scip/type_retcode.h"
78#include "scip/type_scip.h"
79#include "scip/type_set.h"
80#include "scip/type_sol.h"
81#include "scip/type_stat.h"
82#include "scip/type_var.h"
86#define RETURN_ERROR_UNLESS(x) \
88 return util::StatusBuilder(absl::InvalidArgumentError(absl::StrFormat( \
89 "Condition violated at %s:%d: %s", __FILE__, __LINE__, #x)))
93constexpr absl::string_view kLinearConstraintHandlerName =
"linear";
95SCIP_VARTYPE ConvertVarType(
const GScipVarType var_type) {
98 return SCIP_VARTYPE_CONTINUOUS;
100 return SCIP_VARTYPE_BINARY;
102 return SCIP_VARTYPE_IMPLINT;
104 return SCIP_VARTYPE_INTEGER;
109GScipVarType ConvertVarType(
const SCIP_VARTYPE var_type) {
111 case SCIP_VARTYPE_CONTINUOUS:
113 case SCIP_VARTYPE_IMPLINT:
115 case SCIP_VARTYPE_INTEGER:
117 case SCIP_VARTYPE_BINARY:
120 LOG(FATAL) <<
"Unrecognized SCIP_VARTYPE: " << var_type;
124 switch (scip_status) {
125 case SCIP_STATUS_UNKNOWN:
127 case SCIP_STATUS_USERINTERRUPT:
129 case SCIP_STATUS_BESTSOLLIMIT:
131 case SCIP_STATUS_MEMLIMIT:
133 case SCIP_STATUS_NODELIMIT:
135 case SCIP_STATUS_RESTARTLIMIT:
137 case SCIP_STATUS_SOLLIMIT:
139 case SCIP_STATUS_STALLNODELIMIT:
141 case SCIP_STATUS_TIMELIMIT:
143 case SCIP_STATUS_TOTALNODELIMIT:
145 case SCIP_STATUS_OPTIMAL:
147 case SCIP_STATUS_GAPLIMIT:
149 case SCIP_STATUS_INFEASIBLE:
151 case SCIP_STATUS_UNBOUNDED:
153 case SCIP_STATUS_INFORUNBD:
155 case SCIP_STATUS_TERMINATE:
158 LOG(FATAL) <<
"Unrecognized scip status: " << scip_status;
162SCIP_PARAMEMPHASIS ConvertEmphasis(
164 switch (gscip_emphasis) {
166 return SCIP_PARAMEMPHASIS_DEFAULT;
168 return SCIP_PARAMEMPHASIS_CPSOLVER;
170 return SCIP_PARAMEMPHASIS_EASYCIP;
172 return SCIP_PARAMEMPHASIS_FEASIBILITY;
174 return SCIP_PARAMEMPHASIS_HARDLP;
176 return SCIP_PARAMEMPHASIS_OPTIMALITY;
178 return SCIP_PARAMEMPHASIS_COUNTER;
180 return SCIP_PARAMEMPHASIS_PHASEFEAS;
182 return SCIP_PARAMEMPHASIS_PHASEIMPROVE;
184 return SCIP_PARAMEMPHASIS_PHASEPROOF;
186 LOG(FATAL) <<
"Unrecognized gscip_emphasis: "
191SCIP_PARAMSETTING ConvertMetaParamValue(
193 switch (gscip_meta_param_value) {
195 return SCIP_PARAMSETTING_DEFAULT;
197 return SCIP_PARAMSETTING_AGGRESSIVE;
199 return SCIP_PARAMSETTING_FAST;
201 return SCIP_PARAMSETTING_OFF;
203 LOG(FATAL) <<
"Unrecognized gscip_meta_param_value: "
208absl::Status CheckSolutionsInOrder(
const GScipResult& result,
209 const bool is_maximize) {
210 auto objective_as_good_as = [is_maximize](
double left,
double right) {
212 return left >= right;
214 return left <= right;
216 for (
int i = 1; i < result.objective_values.size(); ++i) {
217 const double previous = result.objective_values[i - 1];
218 const double current = result.objective_values[i];
219 if (!objective_as_good_as(previous, current)) {
221 <<
"Expected SCIP solutions to be in best objective order "
223 << (is_maximize ?
"maximization" :
"minimization")
224 <<
" problem, the " << i - 1 <<
" objective is " << previous
225 <<
" and the " << i <<
" objective is " << current;
228 return absl::OkStatus();
233void GScip::InterruptEventHandler::set_interrupter(
235 interrupter_ = interrupter;
238GScip::InterruptEventHandler::InterruptEventHandler()
240 {.name =
"interrupt event handler",
241 .description =
"Event handler to call SCIPinterruptSolve() when a "
242 "user SolveInterrupter is triggered."}) {}
244SCIP_RETCODE GScip::InterruptEventHandler::Init(GScip*
const gscip) {
246 if (interrupter_ ==
nullptr) {
252 CatchEvent(SCIP_EVENTTYPE_PRESOLVEROUND);
253 CatchEvent(SCIP_EVENTTYPE_NODEEVENT);
254 CatchEvent(SCIP_EVENTTYPE_ROWEVENT);
256 return TryCallInterruptIfNeeded(gscip);
259SCIP_RETCODE GScip::InterruptEventHandler::Execute(
260 const GScipEventHandlerContext context) {
261 return TryCallInterruptIfNeeded(context.gscip());
264SCIP_RETCODE GScip::InterruptEventHandler::TryCallInterruptIfNeeded(
265 GScip*
const gscip) {
266 if (interrupter_ ==
nullptr) {
267 LOG(WARNING) <<
"TryCallInterruptIfNeeded() called after interrupter has "
272 if (!interrupter_->is_interrupted()) {
276 const SCIP_STAGE stage = SCIPgetStage(gscip->scip());
278 case SCIP_STAGE_INIT:
279 case SCIP_STAGE_FREE:
282 LOG(DFATAL) <<
"TryCallInterruptIfNeeded() called in stage "
283 << (stage == SCIP_STAGE_INIT ?
"INIT" :
"FREE");
285 case SCIP_STAGE_INITSOLVE:
286 LOG(WARNING) <<
"TryCallInterruptIfNeeded() called in INITSOLVE stage; "
287 "we can't call SCIPinterruptSolve() in this stage.";
290 return SCIPinterruptSolve(gscip->scip());
301 return constraint_options;
304absl::Status GScip::SetParams(
const GScipParameters& params) {
305 if (params.has_silence_output()) {
306 SCIPsetMessagehdlrQuiet(scip_, params.silence_output());
308 if (!params.search_logs_filename().empty()) {
309 SCIPsetMessagehdlrLogfile(scip_, params.search_logs_filename().c_str());
312 const SCIP_Bool set_param_quiet =
313 static_cast<SCIP_Bool
>(!params.silence_output());
316 scip_, ConvertEmphasis(params.emphasis()), set_param_quiet));
317 if (params.has_heuristics()) {
319 scip_, ConvertMetaParamValue(params.heuristics()), set_param_quiet));
321 if (params.has_presolve()) {
323 scip_, ConvertMetaParamValue(params.presolve()), set_param_quiet));
325 if (params.has_separating()) {
327 scip_, ConvertMetaParamValue(params.separating()), set_param_quiet));
329 for (
const auto& bool_param : params.bool_params()) {
331 SCIPsetBoolParam(scip_, bool_param.first.c_str(), bool_param.second));
333 for (
const auto& int_param : params.int_params()) {
335 SCIPsetIntParam(scip_, int_param.first.c_str(), int_param.second));
337 for (
const auto& long_param : params.long_params()) {
341 for (
const auto& char_param : params.char_params()) {
342 if (char_param.second.size() != 1) {
343 return absl::InvalidArgumentError(
344 absl::StrCat(
"Character parameters must be single character strings, "
346 char_param.first,
" was: ", char_param.second));
349 char_param.second[0]));
351 for (
const auto& string_param : params.string_params()) {
353 string_param.second.c_str()));
355 for (
const auto& real_param : params.real_params()) {
357 SCIPsetRealParam(scip_, real_param.first.c_str(), real_param.second));
359 return absl::OkStatus();
363 const std::string& problem_name) {
366 absl::Cleanup scip_cleanup = [&]() { SCIPfree(&
scip); };
369 auto result = absl::WrapUnique(
new GScip(
scip));
371 std::move(scip_cleanup).Cancel();
372 RETURN_IF_ERROR(result->interrupt_event_handler_.Register(result.get()));
376GScip::GScip(SCIP* scip) : scip_(scip) {}
380absl::Status GScip::FreeTransform() {
385 return absl::StrFormat(
"SCIP %d.%d.%d [LP solver: %s]", SCIPmajorVersion(),
386 SCIPminorVersion(), SCIPtechVersion(),
387 SCIPlpiGetSolverName());
391 absl::Status error_status) {
392 CHECK(!error_status.ok());
394 const absl::MutexLock lock(callback_status_mutex_);
395 if (!callback_status_.ok()) {
398 callback_status_ = std::move(error_status);
401 const absl::Status status =
SCIP_TO_STATUS(SCIPinterruptSolve(scip_));
403 LOG(WARNING) <<
"Error trying to interrupt solve after error in callback: "
408absl::Status GScip::CleanUp() {
409 if (scip_ !=
nullptr) {
410 for (SCIP_VAR* variable : variables_) {
411 if (variable !=
nullptr) {
415 for (SCIP_CONS* constraint : constraints_) {
416 if (constraint !=
nullptr) {
422 return absl::OkStatus();
426 const absl::Status clean_up_status = CleanUp();
427 LOG_IF(DFATAL, !clean_up_status.ok()) << clean_up_status;
431 double lb,
double ub,
double obj_coef,
GScipVarType var_type,
433 SCIP_VAR* var =
nullptr;
435 _ <<
"invalid lower bound for variable: " << var_name);
437 _ <<
"invalid upper bound for variable: " << var_name);
439 <<
"invalid objective coefficient for variable: " << var_name;
444 ConvertVarType(var_type)));
449 variables_.insert(var);
456absl::Status GScip::MaybeKeepConstraintAlive(
459 constraints_.insert(constraint);
463 return absl::OkStatus();
469 SCIP_CONS* constraint =
nullptr;
471 <<
"Error adding constraint: " << name <<
".";
473 _ <<
"invalid lower bound for constraint: " << name);
475 _ <<
"invalid upper bound for constraint: " << name);
478 <<
"invalid coefficient at index " << i <<
" of constraint: " << name;
481 scip_, &constraint, name.c_str(), range.
variables.size(),
482 const_cast<SCIP_VAR**
>(range.
variables.data()),
503 SCIP_CONS* constraint =
nullptr;
506 <<
"Error adding quadratic constraint: " << name <<
" in linear term.";
509 <<
"Error adding quadratic constraint: " << name <<
" in quadratic term.";
511 <<
"Error adding quadratic constraint: " << name <<
" in quadratic term.";
513 _ <<
"invalid lower bound for constraint: " << name);
515 _ <<
"invalid upper bound for constraint: " << name);
518 <<
"invalid linear coefficient at index " << i
519 <<
" of constraint: " << name;
523 <<
"invalid quadratic coefficient at index " << i
524 <<
" of constraint: " << name;
527 scip_, &constraint, name.c_str(), num_lin_vars,
553 <<
"Error adding indicator constraint: " << name <<
".";
558 SCIP_CONS* constraint =
nullptr;
561 <<
"Error adding indicator constraint: " << name <<
".";
564 _ <<
"invalid upper bound for constraint: " << name);
565 for (
int i = 0; i < indicator_constraint.
coefficients.size(); ++i) {
567 <<
"invalid coefficient at index " << i <<
" of constraint: " << name;
570 scip_, &constraint, name.c_str(), indicator,
572 const_cast<SCIP_Var**
>(indicator_constraint.
variables.data()),
573 const_cast<double*
>(indicator_constraint.
coefficients.data()),
593 <<
"Error adding and constraint: " << name <<
".";
594 SCIP_CONS* constraint =
nullptr;
596 SCIPcreateConsAnd(scip_, &constraint, name.c_str(),
598 const_cast<SCIP_VAR**
>(logical_data.
operators.data()),
618 <<
"Error adding or constraint: " << name <<
".";
619 SCIP_CONS* constraint =
nullptr;
621 SCIPcreateConsOr(scip_, &constraint, name.c_str(), logical_data.
resultant,
623 const_cast<SCIP_Var**
>(logical_data.
operators.data()),
641absl::Status ValidateSOSData(
const GScipSOSData& sos_data,
642 absl::string_view name) {
644 <<
"Error adding SOS constraint: " << name <<
".";
645 if (!sos_data.
weights.empty()) {
647 <<
" Error adding SOS constraint: " << name <<
".";
649 absl::flat_hash_set<double> distinct_weights;
650 for (
const double w : sos_data.
weights) {
652 <<
"Error adding SOS constraint: " << name
653 <<
", weights must be distinct, but found value " <<
w <<
" twice.";
654 distinct_weights.insert(
w);
656 return absl::OkStatus();
665 SCIP_CONS* constraint =
nullptr;
666 double* weights =
nullptr;
667 if (!sos_data.
weights.empty()) {
668 weights =
const_cast<double*
>(sos_data.
weights.data());
672 scip_, &constraint, name.c_str(), sos_data.
variables.size(),
673 const_cast<SCIP_Var**
>(sos_data.
variables.data()), weights,
692 SCIP_CONS* constraint =
nullptr;
693 double* weights =
nullptr;
694 if (!sos_data.
weights.empty()) {
695 weights =
const_cast<double*
>(sos_data.
weights.data());
698 scip_, &constraint, name.c_str(), sos_data.
variables.size(),
699 const_cast<SCIP_Var**
>(sos_data.
variables.data()), weights,
716 scip_, is_maximize ? SCIP_OBJSENSE_MAXIMIZE : SCIP_OBJSENSE_MINIMIZE));
717 return absl::OkStatus();
721 RETURN_IF_ERROR(CheckScipFinite(offset)) <<
"invalid objective offset";
722 double old_offset = SCIPgetOrigObjoffset(scip_);
723 double delta_offset = offset - old_offset;
725 return absl::OkStatus();
729 return SCIPgetObjsense(scip_) == SCIP_OBJSENSE_MAXIMIZE;
736 return absl::OkStatus();
742 return absl::OkStatus();
748 return absl::OkStatus();
752 RETURN_IF_ERROR(CheckScipFinite(obj_coef)) <<
"invalid objective coefficient";
754 return absl::OkStatus();
758 SCIP_Bool infeasible;
760 SCIPchgVarType(scip_, var, ConvertVarType(var_type), &infeasible));
761 return absl::OkStatus();
765 SCIP_Bool did_delete;
768 <<
"Failed to delete variable named: " <<
Name(var);
769 variables_.erase(var);
771 return absl::OkStatus();
775 const absl::flat_hash_set<SCIP_VAR*>& vars) {
777 return absl::OkStatus();
779 for (SCIP_CONS* constraint : constraints_) {
781 return absl::InvalidArgumentError(absl::StrCat(
782 "Model contains nonlinear constraint: ",
Name(constraint)));
785 return absl::OkStatus();
791 return absl::OkStatus();
794 for (SCIP_CONS* constraint : constraints_) {
795 const absl::Span<SCIP_VAR* const> nonzeros =
797 const std::vector<SCIP_VAR*> nonzeros_copy(nonzeros.begin(),
799 for (SCIP_VAR* var : nonzeros_copy) {
800 if (vars.contains(var)) {
805 for (SCIP_VAR*
const var : vars) {
808 return absl::OkStatus();
822 return ConvertVarType(SCIPvarGetType(var));
825absl::string_view
GScip::Name(SCIP_VAR* var) {
return SCIPvarGetName(var); }
828 return absl::string_view(SCIPconshdlrGetName(SCIPconsGetHdlr(constraint)));
832 return ConstraintType(constraint) == kLinearConstraintHandlerName;
836 SCIP_CONS* constraint) {
837 int num_vars = SCIPgetNVarsLinear(scip_, constraint);
838 return absl::MakeConstSpan(SCIPgetValsLinear(scip_, constraint), num_vars);
842 SCIP_CONS* constraint) {
843 int num_vars = SCIPgetNVarsLinear(scip_, constraint);
844 return absl::MakeConstSpan(SCIPgetVarsLinear(scip_, constraint), num_vars);
856 return SCIPconsGetName(constraint);
862 return absl::OkStatus();
868 return absl::OkStatus();
873 constraints_.erase(constraint);
875 return absl::OkStatus();
879 SCIP_VAR* var,
double value) {
885 return absl::OkStatus();
890 const double value) {
893 return absl::OkStatus();
899 const int scip_num_vars = SCIPgetNOrigVars(scip_);
900 const bool is_solution_partial = partial_solution.size() < scip_num_vars;
901 if (is_solution_partial) {
906 <<
"Error suggesting hint.";
909 for (
const auto& var_value_pair : partial_solution) {
911 var_value_pair.second));
913 if (!is_solution_partial) {
914 SCIP_Bool is_feasible;
919 if (!
static_cast<bool>(is_feasible)) {
926 if (
static_cast<bool>(is_stored)) {
937 return absl::InvalidArgumentError(
938 "GScip is in an error state due to a previous GScip::Solve()");
940 interrupt_event_handler_.set_interrupter(interrupter);
941 const absl::Cleanup interrupt_cleanup = [
this]() {
942 interrupt_event_handler_.set_interrupter(
nullptr);
954 const absl::Status param_status = SetParams(params);
955 if (!param_status.ok()) {
959 std::string(param_status.message()));
972 _ <<
"invalid objective_limit");
982 MessageHandlerPtr previous_handler;
983 MessageHandlerPtr new_handler;
984 if (message_handler !=
nullptr) {
985 previous_handler = CaptureMessageHandlerPtr(SCIPgetMessagehdlr(scip_));
988 SCIPsetMessagehdlr(scip_, new_handler.get());
1003 const SCIP_STAGE stage = SCIPgetStage(scip_);
1004 if (stage != SCIP_STAGE_PRESOLVING && stage != SCIP_STAGE_PRESOLVED &&
1005 stage != SCIP_STAGE_SOLVING && stage != SCIP_STAGE_SOLVED) {
1008 absl::StrCat(
"Unexpected SCIP final stage= ", stage,
1009 " was expected to be either "
1010 "SCIP_STAGE_PRESOLVING, SCIP_STAGE_PRESOLVED, "
1011 "SCIP_STAGE_SOLVING, or SCIP_STAGE_SOLVED"));
1019 if (
file ==
nullptr) {
1020 return absl::InvalidArgumentError(absl::StrCat(
1022 " to write SCIP solve stats."));
1025 int close_result = fclose(
file);
1026 if (close_result != 0) {
1027 return absl::InvalidArgumentError(absl::StrCat(
1028 "Error: ", close_result,
1030 " when writing solve stats."));
1033 absl::Status callback_status;
1035 const absl::MutexLock callback_status_lock(callback_status_mutex_);
1037 <<
"error in a callback that interrupted the solve";
1039 if (!callback_status.ok()) {
1040 const absl::Status status = FreeTransform();
1042 return callback_status;
1044 LOG(ERROR) <<
"GScip::FreeTransform() failed after interrupting "
1045 "the solve due to an error in a callback: "
1053 const int num_scip_solutions = SCIPgetNSols(scip_);
1054 const int num_returned_solutions =
1055 std::min(num_scip_solutions, std::max(1, params.
num_solutions()));
1056 SCIP_SOL** all_solutions = SCIPgetSols(scip_);
1058 for (
int i = 0; i < num_returned_solutions; ++i) {
1059 SCIP_SOL* scip_sol = all_solutions[i];
1060 const double obj_value =
ScipInfUnclamp(SCIPgetSolOrigObj(scip_, scip_sol));
1062 for (SCIP_VAR* v : variables_) {
1063 solution[v] = SCIPgetSolVal(scip_, scip_sol, v);
1070 if (stage != SCIP_STAGE_PRESOLVING && SCIPhasPrimalRay(scip_)) {
1071 for (SCIP_VAR* v : variables_) {
1072 result.
primal_ray[v] = SCIPgetPrimalRayVal(scip_, v);
1080 if (stage != SCIP_STAGE_PRESOLVING) {
1095 if (message_handler !=
nullptr) {
1102 new_handler.reset();
1112 SCIPsetMessagehdlrQuiet(scip_,
false);
1113 SCIPsetMessagehdlrLogfile(scip_,
nullptr);
1119 const std::string& parameter_name) {
1120 SCIP_Bool default_value;
1122 SCIPgetBoolParam(scip_, parameter_name.c_str(), &default_value));
1123 return static_cast<bool>(default_value);
1127 const std::string& parameter_name) {
1130 SCIPgetIntParam(scip_, parameter_name.c_str(), &default_value));
1131 return default_value;
1135 const std::string& parameter_name) {
1136 SCIP_Longint result;
1138 SCIPgetLongintParam(scip_, parameter_name.c_str(), &result));
1139 return static_cast<int64_t
>(result);
1143 const std::string& parameter_name) {
1146 SCIPgetRealParam(scip_, parameter_name.c_str(), &result));
1151 const std::string& parameter_name) {
1154 SCIPgetCharParam(scip_, parameter_name.c_str(), &result));
1159 const std::string& parameter_name) {
1162 SCIPgetStringParam(scip_, parameter_name.c_str(), &result));
1163 return std::string(result);
1167 const double kScipInf =
ScipInf();
1168 if (d == std::numeric_limits<double>::infinity()) {
1171 if (d == -std::numeric_limits<double>::infinity()) {
1175 if (d >= kScipInf || d <= -kScipInf) {
1177 << d <<
" is not in SCIP's finite range: (" << -kScipInf <<
", "
1184 const double kScipInf =
ScipInf();
1185 if (d >= kScipInf)
return std::numeric_limits<double>::infinity();
1186 if (d <= -kScipInf)
return -std::numeric_limits<double>::infinity();
1190absl::Status GScip::CheckScipFinite(
double d) {
1191 const double kScipInf =
ScipInf();
1193 if (d >= kScipInf || d <= -kScipInf) {
1195 << d <<
" is not in SCIP's finite range: (" << -kScipInf <<
", "
1198 return absl::OkStatus();
1202 const absl::MutexLock lock(callback_status_mutex_);
1203 return !callback_status_.ok();
1206#undef RETURN_ERROR_UNLESS
#define ASSIGN_OR_RETURN(lhs, rexpr)
#define RETURN_IF_ERROR(expr)
static constexpr Status STALL_NODE_LIMIT
static constexpr Status OPTIMAL
static constexpr Status INVALID_SOLVER_PARAMETERS
::operations_research::GScipSolvingStats *PROTOBUF_NONNULL mutable_stats()
static constexpr Status INFEASIBLE
static constexpr Status UNKNOWN
static constexpr Status TOTAL_NODE_LIMIT
static constexpr Status TIME_LIMIT
static constexpr Status TERMINATE
static constexpr Status BEST_SOL_LIMIT
static constexpr Status INF_OR_UNBD
static constexpr Status GAP_LIMIT
void set_status(::operations_research::GScipOutput_Status value)
static constexpr Status UNBOUNDED
static constexpr Status USER_INTERRUPT
void set_status_detail(Arg_ &&arg, Args_... args)
static constexpr Status NODE_LIMIT
static constexpr Status SOL_LIMIT
static constexpr Status RESTART_LIMIT
static constexpr Status MEM_LIMIT
GScipOutput_Status Status
GScipParameters_Emphasis Emphasis
bool print_detailed_solving_stats() const
static constexpr Emphasis OPTIMALITY
static constexpr Emphasis PHASE_IMPROVE
static constexpr MetaParamValue AGGRESSIVE
static constexpr MetaParamValue FAST
static constexpr MetaParamValue DEFAULT_META_PARAM_VALUE
static constexpr Emphasis PHASE_PROOF
bool print_scip_model() const
static constexpr Emphasis HARD_LP
static constexpr Emphasis PHASE_FEAS
static constexpr Emphasis EASY_CIP
::int32_t num_solutions() const
static constexpr MetaParamValue OFF
static constexpr Emphasis DEFAULT_EMPHASIS
static constexpr Emphasis CP_SOLVER
const ::std::string & scip_model_filename() const
static constexpr Emphasis FEASIBILITY
const ::std::string & detailed_solving_stats_filename() const
bool has_objective_limit() const
static constexpr Emphasis COUNTER
GScipParameters_MetaParamValue MetaParamValue
double objective_limit() const
void set_total_lp_iterations(::int64_t value)
void set_primal_simplex_iterations(::int64_t value)
void set_deterministic_time(double value)
void set_node_count(::int64_t value)
void set_root_node_bound(double value)
void set_first_lp_relaxation_bound(double value)
void set_best_bound(double value)
void set_best_objective(double value)
void set_barrier_iterations(::int64_t value)
void set_dual_simplex_iterations(::int64_t value)
absl::Status DeleteConstraint(SCIP_CONS *constraint)
double LinearConstraintLb(SCIP_CONS *constraint)
double LinearConstraintUb(SCIP_CONS *constraint)
absl::Span< SCIP_VAR *const > LinearConstraintVariables(SCIP_CONS *constraint)
absl::Status SafeBulkDelete(const absl::flat_hash_set< SCIP_VAR * > &vars)
bool ObjectiveIsMaximize()
absl::Status SetVarType(SCIP_VAR *var, GScipVarType var_type)
absl::StatusOr< char > DefaultCharParamValue(const std::string ¶meter_name)
absl::Status DeleteVariable(SCIP_VAR *var)
absl::StatusOr< SCIP_CONS * > AddQuadraticConstraint(const GScipQuadraticRange &range, const std::string &name="", const GScipConstraintOptions &options=DefaultGScipConstraintOptions())
absl::Status SetObjCoef(SCIP_VAR *var, double obj_coef)
absl::StatusOr< GScipResult > Solve(const GScipParameters ¶ms=GScipParameters(), GScipMessageHandler message_handler=nullptr, const Interrupter *interrupter=nullptr)
bool IsConstraintLinear(SCIP_CONS *constraint)
void InterruptSolveFromCallbackOnCallbackError(absl::Status error_status)
double ScipInfUnclamp(double d)
absl::StatusOr< double > DefaultRealParamValue(const std::string ¶meter_name)
absl::Status AddLinearConstraintCoef(SCIP_CONS *constraint, SCIP_VAR *var, double value)
absl::StatusOr< SCIP_CONS * > AddAndConstraint(const GScipLogicalConstraintData &logical_data, const std::string &name="", const GScipConstraintOptions &options=DefaultGScipConstraintOptions())
absl::StatusOr< double > ScipInfClamp(double d)
absl::Status CanSafeBulkDelete(const absl::flat_hash_set< SCIP_VAR * > &vars)
absl::StatusOr< int > DefaultIntParamValue(const std::string ¶meter_name)
double ObjCoef(SCIP_VAR *var)
absl::StatusOr< SCIP_VAR * > AddVariable(double lb, double ub, double obj_coef, GScipVarType var_type, const std::string &var_name="", const GScipVariableOptions &options=DefaultGScipVariableOptions())
absl::StatusOr< SCIP_CONS * > AddSOS2Constraint(const GScipSOSData &sos_data, const std::string &name="", const GScipConstraintOptions &options=DefaultGScipConstraintOptions())
absl::StatusOr< SCIP_CONS * > AddSOS1Constraint(const GScipSOSData &sos_data, const std::string &name="", const GScipConstraintOptions &options=DefaultGScipConstraintOptions())
absl::string_view ConstraintType(SCIP_CONS *constraint)
absl::Status SetObjectiveOffset(double offset)
absl::StatusOr< SCIP_CONS * > AddLinearConstraint(const GScipLinearRange &range, const std::string &name="", const GScipConstraintOptions &options=DefaultGScipConstraintOptions())
absl::Span< const double > LinearConstraintCoefficients(SCIP_CONS *constraint)
absl::Status SetLb(SCIP_VAR *var, double lb)
absl::StatusOr< SCIP_CONS * > AddOrConstraint(const GScipLogicalConstraintData &logical_data, const std::string &name="", const GScipConstraintOptions &options=DefaultGScipConstraintOptions())
absl::Status SetBranchingPriority(SCIP_VAR *var, int priority)
absl::string_view Name(SCIP_VAR *var)
absl::StatusOr< SCIP_CONS * > AddIndicatorConstraint(const GScipIndicatorConstraint &indicator_constraint, const std::string &name="", const GScipConstraintOptions &options=DefaultGScipConstraintOptions())
absl::StatusOr< bool > DefaultBoolParamValue(const std::string ¶meter_name)
absl::Status SetLinearConstraintUb(SCIP_CONS *constraint, double ub)
absl::StatusOr< GScipHintResult > SuggestHint(const GScipSolution &partial_solution)
absl::Status SetMaximize(bool is_maximize)
absl::Status SetUb(SCIP_VAR *var, double ub)
absl::Status SetLinearConstraintLb(SCIP_CONS *constraint, double lb)
GScipVarType VarType(SCIP_VAR *var)
absl::StatusOr< std::string > DefaultStringParamValue(const std::string ¶meter_name)
absl::StatusOr< int64_t > DefaultLongParamValue(const std::string ¶meter_name)
static absl::StatusOr< std::unique_ptr< GScip > > Create(const std::string &problem_name)
absl::Status SetLinearConstraintCoef(SCIP_CONS *constraint, SCIP_VAR *var, double value)
static std::string ScipVersion()
#define RETURN_ERROR_UNLESS(x)
absl::StatusOr< MessageHandlerPtr > MakeSCIPMessageHandler(const GScipMessageHandler gscip_message_handler)
MessageHandlerPtr CaptureMessageHandlerPtr(SCIP_MESSAGEHDLR *const handler)
std::unique_ptr< SCIP_MESSAGEHDLR, ReleaseSCIPMessageHandler > MessageHandlerPtr
const GScipConstraintOptions & DefaultGScipConstraintOptions()
Select next search node to expand Select next item_i to add this new search node to the search Generate a new search node where item_i is not in the knapsack Check validity of this new partial solution(using propagators) - If valid
std::string ProtoEnumToString(ProtoEnumType enum_value)
int GScipMaxNumThreads(const GScipParameters ¶meters)
absl::flat_hash_map< SCIP_VAR *, double > GScipSolution
std::function< void(GScipMessageType type, absl::string_view message)> GScipMessageHandler
const GScipVariableOptions & DefaultGScipVariableOptions()
StatusBuilder InternalErrorBuilder()
StatusBuilder InvalidArgumentErrorBuilder()
trees with all degrees equal w the current value of w
#define SCIP_TO_STATUS(x)
#define RETURN_IF_SCIP_ERROR(x)
SCIP_VAR * indicator_variable
std::vector< SCIP_Var * > variables
std::vector< double > coefficients
std::vector< SCIP_VAR * > variables
std::vector< double > coefficients
std::vector< SCIP_VAR * > operators
std::vector< double > linear_coefficients
std::vector< SCIP_Var * > quadratic_variables2
*quadratic_variables2[i] std::vector< SCIP_Var * > quadratic_variables1
std::vector< SCIP_Var * > linear_variables
std::vector< double > quadratic_coefficients
std::vector< GScipSolution > solutions
absl::flat_hash_map< SCIP_VAR *, double > primal_ray
std::vector< double > objective_values
std::vector< double > weights
std::vector< SCIP_VAR * > variables
#define OR_ASSIGN_OR_RETURN3(lhs, rexpr, error_expression)