27 #include "absl/container/flat_hash_map.h"
28 #include "absl/container/flat_hash_set.h"
29 #include "absl/memory/memory.h"
30 #include "absl/status/status.h"
31 #include "absl/status/statusor.h"
32 #include "absl/strings/str_cat.h"
33 #include "absl/strings/str_format.h"
34 #include "absl/strings/string_view.h"
35 #include "absl/types/span.h"
38 #include "ortools/gscip/gscip.pb.h"
44 #include "scip/cons_linear.h"
45 #include "scip/cons_quadratic.h"
46 #include "scip/scip.h"
47 #include "scip/scip_general.h"
48 #include "scip/scip_param.h"
49 #include "scip/scip_prob.h"
50 #include "scip/scip_solvingstats.h"
51 #include "scip/scipdefplugins.h"
52 #include "scip/type_cons.h"
53 #include "scip/type_scip.h"
54 #include "scip/type_var.h"
58 #define RETURN_ERROR_UNLESS(x) \
60 return util::StatusBuilder(absl::InvalidArgumentError(absl::StrFormat( \
61 "Condition violated at %s:%d: %s", __FILE__, __LINE__, #x)))
65 constexpr absl::string_view kLinearConstraintHandlerName =
"linear";
67 SCIP_VARTYPE ConvertVarType(
const GScipVarType var_type) {
70 return SCIP_VARTYPE_CONTINUOUS;
72 return SCIP_VARTYPE_BINARY;
74 return SCIP_VARTYPE_IMPLINT;
76 return SCIP_VARTYPE_INTEGER;
80 GScipVarType ConvertVarType(
const SCIP_VARTYPE var_type) {
82 case SCIP_VARTYPE_CONTINUOUS:
84 case SCIP_VARTYPE_IMPLINT:
86 case SCIP_VARTYPE_INTEGER:
88 case SCIP_VARTYPE_BINARY:
93 GScipOutput::Status ConvertStatus(
const SCIP_STATUS scip_status) {
94 switch (scip_status) {
95 case SCIP_STATUS_UNKNOWN:
96 return GScipOutput::UNKNOWN;
97 case SCIP_STATUS_USERINTERRUPT:
98 return GScipOutput::USER_INTERRUPT;
99 case SCIP_STATUS_BESTSOLLIMIT:
100 return GScipOutput::BEST_SOL_LIMIT;
101 case SCIP_STATUS_MEMLIMIT:
102 return GScipOutput::MEM_LIMIT;
103 case SCIP_STATUS_NODELIMIT:
104 return GScipOutput::NODE_LIMIT;
105 case SCIP_STATUS_RESTARTLIMIT:
106 return GScipOutput::RESTART_LIMIT;
107 case SCIP_STATUS_SOLLIMIT:
108 return GScipOutput::SOL_LIMIT;
109 case SCIP_STATUS_STALLNODELIMIT:
110 return GScipOutput::STALL_NODE_LIMIT;
111 case SCIP_STATUS_TIMELIMIT:
112 return GScipOutput::TIME_LIMIT;
113 case SCIP_STATUS_TOTALNODELIMIT:
114 return GScipOutput::TOTAL_NODE_LIMIT;
115 case SCIP_STATUS_OPTIMAL:
117 case SCIP_STATUS_GAPLIMIT:
118 return GScipOutput::GAP_LIMIT;
119 case SCIP_STATUS_INFEASIBLE:
121 case SCIP_STATUS_UNBOUNDED:
123 case SCIP_STATUS_INFORUNBD:
124 return GScipOutput::INF_OR_UNBD;
125 case SCIP_STATUS_TERMINATE:
126 return GScipOutput::TERMINATE;
128 LOG(FATAL) <<
"Unrecognized scip status: " << scip_status;
132 SCIP_PARAMEMPHASIS ConvertEmphasis(
134 switch (gscip_emphasis) {
135 case GScipParameters::DEFAULT_EMPHASIS:
136 return SCIP_PARAMEMPHASIS_DEFAULT;
137 case GScipParameters::CP_SOLVER:
138 return SCIP_PARAMEMPHASIS_CPSOLVER;
139 case GScipParameters::EASY_CIP:
140 return SCIP_PARAMEMPHASIS_EASYCIP;
141 case GScipParameters::FEASIBILITY:
142 return SCIP_PARAMEMPHASIS_FEASIBILITY;
143 case GScipParameters::HARD_LP:
144 return SCIP_PARAMEMPHASIS_HARDLP;
145 case GScipParameters::OPTIMALITY:
146 return SCIP_PARAMEMPHASIS_OPTIMALITY;
147 case GScipParameters::COUNTER:
148 return SCIP_PARAMEMPHASIS_COUNTER;
149 case GScipParameters::PHASE_FEAS:
150 return SCIP_PARAMEMPHASIS_PHASEFEAS;
151 case GScipParameters::PHASE_IMPROVE:
152 return SCIP_PARAMEMPHASIS_PHASEIMPROVE;
153 case GScipParameters::PHASE_PROOF:
154 return SCIP_PARAMEMPHASIS_PHASEPROOF;
156 LOG(FATAL) <<
"Unrecognized gscip_emphasis: "
161 SCIP_PARAMSETTING ConvertMetaParamValue(
162 const GScipParameters::MetaParamValue gscip_meta_param_value) {
163 switch (gscip_meta_param_value) {
164 case GScipParameters::DEFAULT_META_PARAM_VALUE:
165 return SCIP_PARAMSETTING_DEFAULT;
166 case GScipParameters::AGGRESSIVE:
167 return SCIP_PARAMSETTING_AGGRESSIVE;
168 case GScipParameters::FAST:
169 return SCIP_PARAMSETTING_FAST;
170 case GScipParameters::OFF:
171 return SCIP_PARAMSETTING_OFF;
173 LOG(FATAL) <<
"Unrecognized gscip_meta_param_value: "
178 absl::Status CheckSolutionsInOrder(
const GScipResult& result,
179 const bool is_maximize) {
180 auto objective_as_good_as = [is_maximize](
double left,
double right) {
182 return left >= right;
184 return left <= right;
186 for (
int i = 1; i < result.objective_values.size(); ++i) {
187 const double previous = result.objective_values[i - 1];
188 const double current = result.objective_values[i];
189 if (!objective_as_good_as(previous, current)) {
191 <<
"Expected SCIP solutions to be in best objective order "
193 << (is_maximize ?
"maximization" :
"minimization")
194 <<
" problem, the " << i - 1 <<
" objective is " << previous
195 <<
" and the " << i <<
" objective is " << current;
198 return absl::OkStatus();
210 return constraint_options;
213 absl::Status GScip::SetParams(
const GScipParameters& params,
214 const std::string& legacy_params) {
215 if (params.has_silence_output()) {
216 SCIPsetMessagehdlrQuiet(scip_, params.silence_output());
218 if (!params.search_logs_filename().empty()) {
219 SCIPsetMessagehdlrLogfile(scip_, params.search_logs_filename().c_str());
222 const SCIP_Bool set_param_quiet =
223 static_cast<SCIP_Bool
>(!params.silence_output());
226 scip_, ConvertEmphasis(params.emphasis()), set_param_quiet));
227 if (params.has_heuristics()) {
229 scip_, ConvertMetaParamValue(params.heuristics()), set_param_quiet));
231 if (params.has_presolve()) {
233 scip_, ConvertMetaParamValue(params.presolve()), set_param_quiet));
235 if (params.has_separating()) {
237 scip_, ConvertMetaParamValue(params.separating()), set_param_quiet));
239 for (
const auto& bool_param : params.bool_params()) {
241 (SCIPsetBoolParam(scip_, bool_param.first.c_str(), bool_param.second)));
243 for (
const auto& int_param : params.int_params()) {
245 (SCIPsetIntParam(scip_, int_param.first.c_str(), int_param.second)));
247 for (
const auto& long_param : params.long_params()) {
249 long_param.second)));
251 for (
const auto& char_param : params.char_params()) {
252 if (char_param.second.size() != 1) {
253 return absl::InvalidArgumentError(
254 absl::StrCat(
"Character parameters must be single character strings, "
256 char_param.first,
" was: ", char_param.second));
259 char_param.second[0])));
261 for (
const auto& string_param : params.string_params()) {
263 string_param.second.c_str())));
265 for (
const auto& real_param : params.real_params()) {
267 (SCIPsetRealParam(scip_, real_param.first.c_str(), real_param.second)));
269 if (!legacy_params.empty()) {
273 return absl::OkStatus();
277 const std::string& problem_name) {
278 SCIP*
scip =
nullptr;
283 return absl::WrapUnique(
new GScip(
scip));
286 GScip::GScip(SCIP* scip) : scip_(scip) {}
290 absl::Status GScip::FreeTransform() {
295 return absl::StrFormat(
"SCIP %d.%d.%d [LP solver: %s]", SCIPmajorVersion(),
296 SCIPminorVersion(), SCIPtechVersion(),
297 SCIPlpiGetSolverName());
301 if (scip_ ==
nullptr) {
304 return SCIPinterruptSolve(scip_) == SCIP_OKAY;
307 absl::Status GScip::CleanUp() {
308 if (scip_ !=
nullptr) {
309 for (SCIP_VAR* variable : variables_) {
310 if (variable !=
nullptr) {
314 for (SCIP_CONS* constraint : constraints_) {
315 if (constraint !=
nullptr) {
321 return absl::OkStatus();
325 const absl::Status clean_up_status = CleanUp();
326 LOG_IF(DFATAL, !clean_up_status.ok()) << clean_up_status;
330 double lb,
double ub,
double obj_coef,
GScipVarType var_type,
332 SCIP_VAR*
var =
nullptr;
334 _ <<
"invalid lower bound for variable: " << var_name);
336 _ <<
"invalid upper bound for variable: " << var_name);
338 <<
"invalid objective coefficient for variable: " << var_name;
343 ConvertVarType(var_type)));
348 variables_.insert(
var);
355 absl::Status GScip::MaybeKeepConstraintAlive(
358 constraints_.insert(constraint);
362 return absl::OkStatus();
368 SCIP_CONS* constraint =
nullptr;
370 <<
"Error adding constraint: " <<
name <<
".";
372 _ <<
"invalid lower bound for constraint: " <<
name);
374 _ <<
"invalid upper bound for constraint: " <<
name);
375 for (
int i = 0; i <
range.coefficients.size(); ++i) {
377 <<
"invalid coefficient at index " << i <<
" of constraint: " <<
name;
380 scip_, &constraint,
name.c_str(),
range.variables.size(),
381 const_cast<SCIP_VAR**
>(
range.variables.data()),
382 const_cast<double*
>(
range.coefficients.data()),
402 SCIP_CONS* constraint =
nullptr;
403 const int num_lin_vars =
range.linear_variables.size();
405 <<
"Error adding quadratic constraint: " <<
name <<
" in linear term.";
406 const int num_quad_vars =
range.quadratic_variables1.size();
408 <<
"Error adding quadratic constraint: " <<
name <<
" in quadratic term.";
410 <<
"Error adding quadratic constraint: " <<
name <<
" in quadratic term.";
412 _ <<
"invalid lower bound for constraint: " <<
name);
414 _ <<
"invalid upper bound for constraint: " <<
name);
415 for (
int i = 0; i <
range.linear_coefficients.size(); ++i) {
417 <<
"invalid linear coefficient at index " << i
418 <<
" of constraint: " <<
name;
420 for (
int i = 0; i <
range.quadratic_coefficients.size(); ++i) {
422 <<
"invalid quadratic coefficient at index " << i
423 <<
" of constraint: " <<
name;
426 scip_, &constraint,
name.c_str(), num_lin_vars,
427 const_cast<SCIP_Var**
>(
range.linear_variables.data()),
428 const_cast<double*
>(
range.linear_coefficients.data()), num_quad_vars,
429 const_cast<SCIP_Var**
>(
range.quadratic_variables1.data()),
430 const_cast<SCIP_Var**
>(
range.quadratic_variables2.data()),
431 const_cast<double*
>(
range.quadratic_coefficients.data()),
452 <<
"Error adding indicator constraint: " <<
name <<
".";
457 SCIP_CONS* constraint =
nullptr;
460 <<
"Error adding indicator constraint: " <<
name <<
".";
463 _ <<
"invalid upper bound for constraint: " <<
name);
464 for (
int i = 0; i < indicator_constraint.
coefficients.size(); ++i) {
466 <<
"invalid coefficient at index " << i <<
" of constraint: " <<
name;
469 scip_, &constraint,
name.c_str(), indicator,
471 const_cast<SCIP_Var**
>(indicator_constraint.
variables.data()),
472 const_cast<double*
>(indicator_constraint.
coefficients.data()),
492 <<
"Error adding and constraint: " <<
name <<
".";
493 SCIP_CONS* constraint =
nullptr;
495 SCIPcreateConsAnd(scip_, &constraint,
name.c_str(),
497 const_cast<SCIP_VAR**
>(logical_data.
operators.data()),
517 <<
"Error adding or constraint: " <<
name <<
".";
518 SCIP_CONS* constraint =
nullptr;
520 SCIPcreateConsOr(scip_, &constraint,
name.c_str(), logical_data.
resultant,
522 const_cast<SCIP_Var**
>(logical_data.
operators.data()),
540 absl::Status ValidateSOSData(
const GScipSOSData& sos_data,
541 absl::string_view
name) {
543 <<
"Error adding SOS constraint: " <<
name <<
".";
544 if (!sos_data.
weights.empty()) {
546 <<
" Error adding SOS constraint: " <<
name <<
".";
548 absl::flat_hash_set<double> distinct_weights;
549 for (
const double w : sos_data.
weights) {
551 <<
"Error adding SOS constraint: " <<
name
552 <<
", weights must be distinct, but found value " << w <<
" twice.";
553 distinct_weights.insert(w);
555 return absl::OkStatus();
564 SCIP_CONS* constraint =
nullptr;
565 double* weights =
nullptr;
566 if (!sos_data.
weights.empty()) {
567 weights =
const_cast<double*
>(sos_data.
weights.data());
572 const_cast<SCIP_Var**
>(sos_data.
variables.data()), weights,
591 SCIP_CONS* constraint =
nullptr;
592 double* weights =
nullptr;
593 if (!sos_data.
weights.empty()) {
594 weights =
const_cast<double*
>(sos_data.
weights.data());
598 const_cast<SCIP_Var**
>(sos_data.
variables.data()), weights,
615 scip_, is_maximize ? SCIP_OBJSENSE_MAXIMIZE : SCIP_OBJSENSE_MINIMIZE));
616 return absl::OkStatus();
620 RETURN_IF_ERROR(CheckScipFinite(offset)) <<
"invalid objective offset";
621 double old_offset = SCIPgetOrigObjoffset(scip_);
622 double delta_offset = offset - old_offset;
624 return absl::OkStatus();
628 return SCIPgetObjsense(scip_) == SCIP_OBJSENSE_MAXIMIZE;
635 return absl::OkStatus();
641 return absl::OkStatus();
647 return absl::OkStatus();
651 RETURN_IF_ERROR(CheckScipFinite(obj_coef)) <<
"invalid objective coefficient";
653 return absl::OkStatus();
657 SCIP_Bool infeasible;
659 SCIPchgVarType(scip_,
var, ConvertVarType(var_type), &infeasible));
660 return absl::OkStatus();
664 SCIP_Bool did_delete;
667 <<
"Failed to delete variable named: " <<
Name(
var);
668 variables_.erase(
var);
670 return absl::OkStatus();
674 const absl::flat_hash_set<SCIP_VAR*>& vars) {
676 return absl::OkStatus();
678 for (SCIP_CONS* constraint : constraints_) {
680 return absl::InvalidArgumentError(absl::StrCat(
681 "Model contains nonlinear constraint: ",
Name(constraint)));
684 return absl::OkStatus();
690 return absl::OkStatus();
693 for (SCIP_CONS* constraint : constraints_) {
694 const absl::Span<SCIP_VAR* const> nonzeros =
696 const std::vector<SCIP_VAR*> nonzeros_copy(nonzeros.begin(),
698 for (SCIP_VAR*
var : nonzeros_copy) {
699 if (vars.contains(
var)) {
704 for (SCIP_VAR*
const var : vars) {
707 return absl::OkStatus();
711 return ScipInfUnclamp(SCIPvarGetLbOriginal(
var));
715 return ScipInfUnclamp(SCIPvarGetUbOriginal(
var));
721 return ConvertVarType(SCIPvarGetType(
var));
727 return absl::string_view(SCIPconshdlrGetName(SCIPconsGetHdlr(constraint)));
731 return ConstraintType(constraint) == kLinearConstraintHandlerName;
735 SCIP_CONS* constraint) {
736 int num_vars = SCIPgetNVarsLinear(scip_, constraint);
737 return absl::MakeConstSpan(SCIPgetValsLinear(scip_, constraint), num_vars);
741 SCIP_CONS* constraint) {
742 int num_vars = SCIPgetNVarsLinear(scip_, constraint);
743 return absl::MakeConstSpan(SCIPgetVarsLinear(scip_, constraint), num_vars);
747 return ScipInfUnclamp(SCIPgetLhsLinear(scip_, constraint));
751 return ScipInfUnclamp(SCIPgetRhsLinear(scip_, constraint));
755 return SCIPconsGetName(constraint);
761 return absl::OkStatus();
767 return absl::OkStatus();
772 constraints_.erase(constraint);
774 return absl::OkStatus();
784 return absl::OkStatus();
789 const double value) {
792 return absl::OkStatus();
798 const int scip_num_vars = SCIPgetNOrigVars(scip_);
799 const bool is_solution_partial = partial_solution.size() < scip_num_vars;
800 if (is_solution_partial) {
805 <<
"Error suggesting hint.";
808 for (
const auto& var_value_pair : partial_solution) {
810 var_value_pair.second));
812 if (!is_solution_partial) {
813 SCIP_Bool is_feasible;
815 scip_, solution,
false,
true,
818 if (!
static_cast<bool>(is_feasible)) {
825 if (
static_cast<bool>(is_stored)) {
833 const GScipParameters& params,
const std::string& legacy_params,
844 const absl::Status param_status = SetParams(params, legacy_params);
845 if (!param_status.ok()) {
849 std::string(param_status.message()));
852 if (params.print_scip_model()) {
855 if (!params.scip_model_filename().empty()) {
857 scip_, params.scip_model_filename().c_str(),
"cip", FALSE));
859 if (params.has_objective_limit()) {
861 ScipInfClamp(params.objective_limit()),
862 _ <<
"invalid objective_limit");
874 if (message_handler !=
nullptr) {
878 SCIPsetMessagehdlr(scip_, new_handler.get());
893 const SCIP_STAGE stage = SCIPgetStage(scip_);
894 if (stage != SCIP_STAGE_PRESOLVING && stage != SCIP_STAGE_SOLVING &&
895 stage != SCIP_STAGE_SOLVED) {
898 absl::StrCat(
"Unpexpected SCIP final stage= ", stage,
899 " was expected to be either SCIP_STAGE_PRESOLVING, "
900 "SCIP_STAGE_SOLVING, or SCIP_STAGE_SOLVED"));
903 if (params.print_detailed_solving_stats()) {
906 if (!params.detailed_solving_stats_filename().empty()) {
907 FILE*
file = fopen(params.detailed_solving_stats_filename().c_str(),
"w");
908 if (
file ==
nullptr) {
909 return absl::InvalidArgumentError(absl::StrCat(
910 "Could not open file: ", params.detailed_solving_stats_filename(),
911 " to write SCIP solve stats."));
914 int close_result = fclose(
file);
915 if (close_result != 0) {
916 return absl::InvalidArgumentError(absl::StrCat(
917 "Error: ", close_result,
918 " closing file: ", params.detailed_solving_stats_filename(),
919 " when writing solve stats."));
925 GScipSolvingStats* stats = result.
gscip_output.mutable_stats();
926 const int num_scip_solutions = SCIPgetNSols(scip_);
927 const int num_returned_solutions =
929 SCIP_SOL** all_solutions = SCIPgetSols(scip_);
930 stats->set_best_objective(ScipInfUnclamp(SCIPgetPrimalbound(scip_)));
931 for (
int i = 0; i < num_returned_solutions; ++i) {
932 SCIP_SOL* scip_sol = all_solutions[i];
933 const double obj_value = ScipInfUnclamp(SCIPgetSolOrigObj(scip_, scip_sol));
935 for (SCIP_VAR* v : variables_) {
936 solution[v] = SCIPgetSolVal(scip_, scip_sol, v);
943 if (stage != SCIP_STAGE_PRESOLVING && SCIPhasPrimalRay(scip_)) {
944 for (SCIP_VAR* v : variables_) {
945 result.
primal_ray[v] = SCIPgetPrimalRayVal(scip_, v);
949 stats->set_best_bound(ScipInfUnclamp(SCIPgetDualbound(scip_)));
950 stats->set_node_count(SCIPgetNTotalNodes(scip_));
951 stats->set_first_lp_relaxation_bound(SCIPgetFirstLPDualboundRoot(scip_));
952 stats->set_root_node_bound(SCIPgetDualboundRoot(scip_));
953 if (stage != SCIP_STAGE_PRESOLVING) {
954 stats->set_total_lp_iterations(SCIPgetNLPIterations(scip_));
955 stats->set_primal_simplex_iterations(SCIPgetNPrimalLPIterations(scip_));
956 stats->set_dual_simplex_iterations(SCIPgetNDualLPIterations(scip_));
957 stats->set_deterministic_time(SCIPgetDeterministicTime(scip_));
959 result.
gscip_output.set_status(ConvertStatus(SCIPgetStatus(scip_)));
967 if (message_handler !=
nullptr) {
976 if (params.has_objective_limit()) {
984 SCIPsetMessagehdlrQuiet(scip_,
false);
985 SCIPsetMessagehdlrLogfile(scip_,
nullptr);
991 const std::string& parameter_name) {
992 SCIP_Bool default_value;
994 SCIPgetBoolParam(scip_, parameter_name.c_str(), &default_value));
995 return static_cast<bool>(default_value);
999 const std::string& parameter_name) {
1002 SCIPgetIntParam(scip_, parameter_name.c_str(), &default_value));
1003 return default_value;
1007 const std::string& parameter_name) {
1008 SCIP_Longint result;
1010 SCIPgetLongintParam(scip_, parameter_name.c_str(), &result));
1011 return static_cast<int64_t
>(result);
1015 const std::string& parameter_name) {
1018 SCIPgetRealParam(scip_, parameter_name.c_str(), &result));
1023 const std::string& parameter_name) {
1026 SCIPgetCharParam(scip_, parameter_name.c_str(), &result));
1031 const std::string& parameter_name) {
1034 SCIPgetStringParam(scip_, parameter_name.c_str(), &result));
1035 return std::string(result);
1038 absl::StatusOr<double> GScip::ScipInfClamp(
const double d) {
1039 const double kScipInf =
ScipInf();
1040 if (d == std::numeric_limits<double>::infinity()) {
1043 if (d == -std::numeric_limits<double>::infinity()) {
1047 if (d >= kScipInf || d <= -kScipInf) {
1049 << d <<
" is not in SCIP's finite range: (" << -kScipInf <<
", "
1055 double GScip::ScipInfUnclamp(
double d) {
1056 const double kScipInf =
ScipInf();
1057 if (d >= kScipInf)
return std::numeric_limits<double>::infinity();
1058 if (d <= -kScipInf)
return -std::numeric_limits<double>::infinity();
1062 absl::Status GScip::CheckScipFinite(
double d) {
1063 const double kScipInf =
ScipInf();
1065 if (d >= kScipInf || d <= -kScipInf) {
1067 << d <<
" is not in SCIP's finite range: (" << -kScipInf <<
", "
1070 return absl::OkStatus();
1073 #undef RETURN_ERROR_UNLESS
#define ASSIGN_OR_RETURN(lhs, rexpr)
#define RETURN_IF_ERROR(expr)
double LinearConstraintUb(SCIP_CONS *constraint)
absl::Status SetObjectiveOffset(double offset)
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::Status DeleteVariable(SCIP_VAR *var)
absl::StatusOr< SCIP_CONS * > AddOrConstraint(const GScipLogicalConstraintData &logical_data, const std::string &name="", const GScipConstraintOptions &options=DefaultGScipConstraintOptions())
absl::StatusOr< double > DefaultRealParamValue(const std::string ¶meter_name)
absl::Status CanSafeBulkDelete(const absl::flat_hash_set< SCIP_VAR * > &vars)
absl::StatusOr< SCIP_CONS * > AddAndConstraint(const GScipLogicalConstraintData &logical_data, const std::string &name="", const GScipConstraintOptions &options=DefaultGScipConstraintOptions())
absl::StatusOr< SCIP_CONS * > AddLinearConstraint(const GScipLinearRange &range, const std::string &name="", const GScipConstraintOptions &options=DefaultGScipConstraintOptions())
bool IsConstraintLinear(SCIP_CONS *constraint)
absl::string_view ConstraintType(SCIP_CONS *constraint)
absl::StatusOr< int64_t > DefaultLongParamValue(const std::string ¶meter_name)
absl::StatusOr< int > DefaultIntParamValue(const std::string ¶meter_name)
absl::Status DeleteConstraint(SCIP_CONS *constraint)
absl::Status SetLinearConstraintUb(SCIP_CONS *constraint, double ub)
absl::Status SafeBulkDelete(const absl::flat_hash_set< SCIP_VAR * > &vars)
static absl::StatusOr< std::unique_ptr< GScip > > Create(const std::string &problem_name)
double ObjCoef(SCIP_VAR *var)
absl::Status SetMaximize(bool is_maximize)
absl::Span< SCIP_VAR *const > LinearConstraintVariables(SCIP_CONS *constraint)
absl::StatusOr< std::string > DefaultStringParamValue(const std::string ¶meter_name)
absl::StatusOr< bool > DefaultBoolParamValue(const std::string ¶meter_name)
absl::StatusOr< SCIP_CONS * > AddIndicatorConstraint(const GScipIndicatorConstraint &indicator_constraint, const std::string &name="", const GScipConstraintOptions &options=DefaultGScipConstraintOptions())
absl::Status SetLb(SCIP_VAR *var, double lb)
double LinearConstraintLb(SCIP_CONS *constraint)
absl::Status SetLinearConstraintCoef(SCIP_CONS *constraint, SCIP_VAR *var, double value)
absl::Status SetLinearConstraintLb(SCIP_CONS *constraint, double lb)
absl::StatusOr< GScipHintResult > SuggestHint(const GScipSolution &partial_solution)
absl::StatusOr< GScipResult > Solve(const GScipParameters ¶ms=GScipParameters(), const std::string &legacy_params="", GScipMessageHandler message_handler=nullptr)
GScipVarType VarType(SCIP_VAR *var)
absl::Status SetVarType(SCIP_VAR *var, GScipVarType var_type)
absl::Status SetBranchingPriority(SCIP_VAR *var, int priority)
absl::StatusOr< char > DefaultCharParamValue(const std::string ¶meter_name)
absl::Span< const double > LinearConstraintCoefficients(SCIP_CONS *constraint)
absl::Status SetUb(SCIP_VAR *var, double ub)
absl::Status SetObjCoef(SCIP_VAR *var, double obj_coef)
absl::StatusOr< SCIP_CONS * > AddSOS2Constraint(const GScipSOSData &sos_data, const std::string &name="", const GScipConstraintOptions &options=DefaultGScipConstraintOptions())
static std::string ScipVersion()
absl::StatusOr< SCIP_CONS * > AddQuadraticConstraint(const GScipQuadraticRange &range, const std::string &name="", const GScipConstraintOptions &options=DefaultGScipConstraintOptions())
absl::string_view Name(SCIP_VAR *var)
absl::Status AddLinearConstraintCoef(SCIP_CONS *constraint, SCIP_VAR *var, double value)
absl::StatusOr< SCIP_CONS * > AddSOS1Constraint(const GScipSOSData &sos_data, const std::string &name="", const GScipConstraintOptions &options=DefaultGScipConstraintOptions())
bool ObjectiveIsMaximize()
#define RETURN_ERROR_UNLESS(x)
absl::StatusOr< MessageHandlerPtr > MakeSCIPMessageHandler(const GScipMessageHandler gscip_message_handler)
std::unique_ptr< SCIP_MESSAGEHDLR, ReleaseSCIPMessageHandler > MessageHandlerPtr
MessageHandlerPtr CaptureMessageHandlerPtr(SCIP_MESSAGEHDLR *const handler)
Collection of objects used to extend the Constraint Solver library.
const GScipConstraintOptions & DefaultGScipConstraintOptions()
std::function< void(GScipMessageType type, absl::string_view message)> GScipMessageHandler
int GScipMaxNumThreads(const GScipParameters ¶meters)
std::string ProtoEnumToString(ProtoEnumType enum_value)
absl::Status LegacyScipSetSolverSpecificParameters(absl::string_view parameters, SCIP *scip)
@ INVALID_SOLVER_PARAMETERS
const GScipVariableOptions & DefaultGScipVariableOptions()
absl::flat_hash_map< SCIP_VAR *, double > GScipSolution
StatusBuilder InternalErrorBuilder()
StatusBuilder InvalidArgumentErrorBuilder()
#define SCIP_TO_STATUS(x)
#define RETURN_IF_SCIP_ERROR(x)
const std::optional< Range > & range
std::vector< double > coefficients
std::vector< SCIP_Var * > variables
SCIP_VAR * indicator_variable
std::vector< SCIP_VAR * > operators
absl::flat_hash_map< SCIP_VAR *, double > primal_ray
std::vector< double > objective_values
std::vector< GScipSolution > solutions
std::vector< SCIP_VAR * > variables
std::vector< double > weights
#define OR_ASSIGN_OR_RETURN3(lhs, rexpr, error_expression)