29#include "absl/base/attributes.h"
30#include "absl/cleanup/cleanup.h"
31#include "absl/container/btree_set.h"
32#include "absl/flags/flag.h"
33#include "absl/log/check.h"
34#include "absl/log/log.h"
35#include "absl/status/status.h"
36#include "absl/status/statusor.h"
37#include "absl/strings/str_cat.h"
38#include "absl/strings/str_format.h"
39#include "absl/strings/string_view.h"
40#include "absl/time/clock.h"
41#include "absl/time/time.h"
49#include "scip/cons_and.h"
50#include "scip/cons_disjunction.h"
51#include "scip/cons_indicator.h"
52#include "scip/cons_linear.h"
53#include "scip/cons_or.h"
54#include "scip/cons_quadratic.h"
55#include "scip/cons_sos1.h"
56#include "scip/cons_sos2.h"
58#include "scip/pub_event.h"
59#include "scip/pub_var.h"
60#include "scip/scip_cons.h"
61#include "scip/scip_event.h"
62#include "scip/scip_general.h"
63#include "scip/scip_message.h"
64#include "scip/scip_numerics.h"
65#include "scip/scip_param.h"
66#include "scip/scip_prob.h"
67#include "scip/scip_sol.h"
68#include "scip/scip_solve.h"
69#include "scip/scip_solvingstats.h"
70#include "scip/scip_var.h"
71#include "scip/scipdefplugins.h"
72#include "scip/type_clock.h"
73#include "scip/type_cons.h"
74#include "scip/type_prob.h"
75#include "scip/type_retcode.h"
76#include "scip/type_scip.h"
77#include "scip/type_sol.h"
78#include "scip/type_stat.h"
79#include "scip/type_var.h"
81ABSL_FLAG(std::string, scip_proto_solver_output_cip_file,
"",
82 "If given, saves the generated CIP file here. Useful for "
83 "reporting bugs to SCIP.");
88absl::StatusOr<double> ScipInfClamp(
SCIP* scip,
const double d) {
90 return absl::InvalidArgumentError(
"Cannot clamp a NaN.");
92 const double kScipInf = SCIPinfinity(scip);
93 const double clamped = std::clamp(d, -kScipInf, kScipInf);
95 VLOG_EVERY_N_SEC(1, 5)
96 <<
"A bound was clamped to SCIP's 'infinite' value for safety; this "
97 "may affect results. Was: "
98 << d <<
", is now: " << clamped;
106 SCIP* scip, SCIP_CONS** scip_cst,
107 std::vector<SCIP_VAR*>* scip_variables,
108 std::vector<SCIP_CONS*>* scip_constraints,
109 std::vector<SCIP_VAR*>* tmp_variables,
110 std::vector<double>* tmp_coefficients) {
111 CHECK(scip !=
nullptr);
112 CHECK(scip_cst !=
nullptr);
113 CHECK(scip_variables !=
nullptr);
114 CHECK(scip_constraints !=
nullptr);
115 CHECK(tmp_variables !=
nullptr);
116 CHECK(tmp_coefficients !=
nullptr);
117 CHECK(gen_cst.has_indicator_constraint());
118 constexpr double kInfinity = std::numeric_limits<double>::infinity();
120 const auto& ind = gen_cst.indicator_constraint();
121 if (!ind.has_constraint())
return absl::OkStatus();
125 tmp_variables->resize(size,
nullptr);
126 tmp_coefficients->resize(size, 0);
127 for (
int i = 0;
i < size; ++
i) {
128 (*tmp_variables)[
i] = (*scip_variables)[constraint.var_index(i)];
129 (*tmp_coefficients)[
i] = constraint.coefficient(i);
132 SCIP_VAR* ind_var = (*scip_variables)[ind.var_index()];
133 if (ind.var_value() == 0) {
135 SCIPgetNegatedVar(scip, (*scip_variables)[ind.var_index()], &ind_var));
138 if (ind.constraint().upper_bound() <
kInfinity) {
140 ScipInfClamp(scip, ind.constraint().upper_bound()));
142 scip, scip_cst, gen_cst.name().c_str(), ind_var, size,
143 tmp_variables->data(), tmp_coefficients->data(), upper_bound,
144 !ind.constraint().is_lazy(),
151 ind.constraint().is_lazy(),
154 scip_constraints->push_back(
nullptr);
155 scip_cst = &scip_constraints->back();
157 if (ind.constraint().lower_bound() > -
kInfinity) {
159 ScipInfClamp(scip, ind.constraint().lower_bound()));
160 for (
int i = 0;
i < size; ++
i) {
161 (*tmp_coefficients)[
i] *= -1;
164 scip, scip_cst, gen_cst.name().c_str(), ind_var, size,
165 tmp_variables->data(), tmp_coefficients->data(), -lower_bound,
166 !ind.constraint().is_lazy(),
173 ind.constraint().is_lazy(),
178 return absl::OkStatus();
182 const std::vector<SCIP_VAR*>& scip_variables,
183 SCIP* scip, SCIP_CONS** scip_cst,
184 std::vector<SCIP_VAR*>* tmp_variables,
185 std::vector<double>* tmp_weights) {
186 CHECK(scip !=
nullptr);
187 CHECK(scip_cst !=
nullptr);
188 CHECK(tmp_variables !=
nullptr);
189 CHECK(tmp_weights !=
nullptr);
191 CHECK(gen_cst.has_sos_constraint());
197 if (sos_cst.var_index_size() <= 1)
return absl::OkStatus();
199 sos_cst.var_index_size() <= 2) {
200 return absl::OkStatus();
203 tmp_variables->resize(sos_cst.var_index_size(),
nullptr);
204 for (
int v = 0; v < sos_cst.var_index_size(); ++v) {
205 (*tmp_variables)[v] = scip_variables[sos_cst.var_index(v)];
207 tmp_weights->resize(sos_cst.var_index_size(), 0);
208 if (sos_cst.weight_size() == sos_cst.var_index_size()) {
209 for (
int w = 0;
w < sos_cst.weight_size(); ++
w) {
210 (*tmp_weights)[
w] = sos_cst.weight(
w);
215 std::iota(tmp_weights->begin(), tmp_weights->end(), 1);
217 switch (sos_cst.type()) {
220 SCIPcreateConsBasicSOS1(scip,
222 gen_cst.name().c_str(),
223 sos_cst.var_index_size(),
224 tmp_variables->data(),
225 tmp_weights->data()));
229 SCIPcreateConsBasicSOS2(scip,
231 gen_cst.name().c_str(),
232 sos_cst.var_index_size(),
233 tmp_variables->data(),
234 tmp_weights->data()));
238 return absl::OkStatus();
241absl::Status AddQuadraticConstraint(
243 const std::vector<SCIP_VAR*>& scip_variables,
SCIP* scip,
244 SCIP_CONS** scip_cst, std::vector<SCIP_VAR*>* tmp_variables,
245 std::vector<double>* tmp_coefficients,
246 std::vector<SCIP_VAR*>* tmp_qvariables1,
247 std::vector<SCIP_VAR*>* tmp_qvariables2,
248 std::vector<double>* tmp_qcoefficients) {
249 CHECK(scip !=
nullptr);
250 CHECK(scip_cst !=
nullptr);
251 CHECK(tmp_variables !=
nullptr);
252 CHECK(tmp_coefficients !=
nullptr);
253 CHECK(tmp_qvariables1 !=
nullptr);
254 CHECK(tmp_qvariables2 !=
nullptr);
255 CHECK(tmp_qcoefficients !=
nullptr);
257 CHECK(gen_cst.has_quadratic_constraint());
262 CHECK_EQ(quad_cst.coefficient_size(), lsize);
263 tmp_variables->resize(lsize,
nullptr);
264 tmp_coefficients->resize(lsize, 0.0);
265 for (
int i = 0;
i < lsize; ++
i) {
266 (*tmp_variables)[
i] = scip_variables[quad_cst.var_index(i)];
267 (*tmp_coefficients)[
i] = quad_cst.coefficient(i);
271 const int qsize = quad_cst.qvar1_index_size();
272 CHECK_EQ(quad_cst.qvar2_index_size(), qsize);
273 CHECK_EQ(quad_cst.qcoefficient_size(), qsize);
274 tmp_qvariables1->resize(qsize,
nullptr);
275 tmp_qvariables2->resize(qsize,
nullptr);
276 tmp_qcoefficients->resize(qsize, 0.0);
277 for (
int i = 0;
i < qsize; ++
i) {
278 (*tmp_qvariables1)[
i] = scip_variables[quad_cst.qvar1_index(i)];
279 (*tmp_qvariables2)[
i] = scip_variables[quad_cst.qvar2_index(i)];
280 (*tmp_qcoefficients)[
i] = quad_cst.qcoefficient(i);
284 ScipInfClamp(scip, quad_cst.lower_bound()));
286 ScipInfClamp(scip, quad_cst.upper_bound()));
288 SCIPcreateConsBasicQuadratic(scip,
290 gen_cst.name().c_str(),
292 tmp_variables->data(),
293 tmp_coefficients->data(),
295 tmp_qvariables1->data(),
296 tmp_qvariables2->data(),
297 tmp_qcoefficients->data(),
301 return absl::OkStatus();
307 const std::vector<SCIP_VAR*>& scip_variables,
308 SCIP* scip, SCIP_CONS** scip_cst) {
309 CHECK(scip !=
nullptr);
310 CHECK(scip_cst !=
nullptr);
311 CHECK(gen_cst.has_abs_constraint());
312 const auto& abs = gen_cst.abs_constraint();
313 SCIP_VAR* scip_var = scip_variables[abs.var_index()];
314 SCIP_VAR* scip_resultant_var = scip_variables[abs.resultant_var_index()];
317 if (SCIPvarGetLbLocal(scip_resultant_var) < 0.0) {
321 std::vector<SCIP_VAR*> vars;
322 std::vector<double> vals;
324 std::vector<SCIP_CONS*> cons;
326 absl::Cleanup cons_cleanup = [&]() {
327 for (SCIP_CONS* c : cons) {
328 const absl::Status status =
SCIP_TO_STATUS(SCIPreleaseCons(scip, &c));
329 LOG_IF(ERROR, !status.ok()) << status;
333 auto add_abs_constraint = [&](absl::string_view name_prefix) -> absl::Status {
334 SCIP_CONS* scip_cons =
nullptr;
335 CHECK(vars.size() == vals.size());
336 const std::string name =
337 gen_cst.has_name() ? absl::StrCat(gen_cst.name(), name_prefix) :
"";
340 name.c_str(), vars.size(), vars.data(),
341 vals.data(), 0.0, 0.0));
344 cons.push_back(scip_cons);
345 return absl::OkStatus();
349 vars = {scip_resultant_var, scip_var};
358 const std::string name =
359 gen_cst.has_name() ? absl::StrCat(gen_cst.name(),
"_disj") :
"";
361 scip, scip_cst, name.c_str(),
362 cons.size(), cons.data(),
nullptr));
365 return absl::OkStatus();
369 const std::vector<SCIP_VAR*>& scip_variables,
370 SCIP* scip, SCIP_CONS** scip_cst,
371 std::vector<SCIP_VAR*>* tmp_variables) {
372 CHECK(scip !=
nullptr);
373 CHECK(scip_cst !=
nullptr);
374 CHECK(tmp_variables !=
nullptr);
375 CHECK(gen_cst.has_and_constraint());
376 const auto& andcst = gen_cst.and_constraint();
378 tmp_variables->resize(andcst.var_index_size(),
nullptr);
379 for (
int i = 0;
i < andcst.var_index_size(); ++
i) {
380 (*tmp_variables)[
i] = scip_variables[andcst.var_index(i)];
384 gen_cst.name().c_str(),
385 scip_variables[andcst.resultant_var_index()],
386 andcst.var_index_size(),
387 tmp_variables->data()));
389 return absl::OkStatus();
393 const std::vector<SCIP_VAR*>& scip_variables,
394 SCIP* scip, SCIP_CONS** scip_cst,
395 std::vector<SCIP_VAR*>* tmp_variables) {
396 CHECK(scip !=
nullptr);
397 CHECK(scip_cst !=
nullptr);
398 CHECK(tmp_variables !=
nullptr);
399 CHECK(gen_cst.has_or_constraint());
400 const auto& orcst = gen_cst.or_constraint();
402 tmp_variables->resize(orcst.var_index_size(),
nullptr);
403 for (
int i = 0;
i < orcst.var_index_size(); ++
i) {
404 (*tmp_variables)[
i] = scip_variables[orcst.var_index(i)];
408 gen_cst.name().c_str(),
409 scip_variables[orcst.resultant_var_index()],
410 orcst.var_index_size(),
411 tmp_variables->data()));
413 return absl::OkStatus();
422 const std::vector<SCIP_VAR*>& scip_variables,
423 SCIP* scip, SCIP_CONS** scip_cst,
424 std::vector<SCIP_CONS*>* scip_constraints,
425 std::vector<SCIP_VAR*>* tmp_variables) {
426 CHECK(scip !=
nullptr);
427 CHECK(scip_cst !=
nullptr);
428 CHECK(tmp_variables !=
nullptr);
429 CHECK(gen_cst.has_min_constraint() || gen_cst.has_max_constraint());
430 constexpr double kInfinity = std::numeric_limits<double>::infinity();
432 const auto& minmax = gen_cst.has_min_constraint() ? gen_cst.min_constraint()
433 : gen_cst.max_constraint();
434 const absl::btree_set<int> unique_var_indices(minmax.var_index().begin(),
435 minmax.var_index().end());
436 SCIP_VAR* scip_resultant_var = scip_variables[minmax.resultant_var_index()];
438 std::vector<SCIP_VAR*> vars;
439 std::vector<double> vals;
440 std::vector<SCIP_CONS*> cons;
441 auto add_lin_constraint = [&](absl::string_view name_prefix,
442 double lower_bound = 0.0,
443 double upper_bound = 0.0) -> absl::Status {
444 SCIP_CONS* scip_cons =
nullptr;
445 CHECK(vars.size() == vals.size());
446 const std::string name =
447 gen_cst.has_name() ? absl::StrCat(gen_cst.name(), name_prefix) :
"";
449 ScipInfClamp(scip, lower_bound));
451 ScipInfClamp(scip, upper_bound));
454 name.c_str(), vars.size(), vars.data(),
455 vals.data(), scip_lower_bound,
459 cons.push_back(scip_cons);
460 return absl::OkStatus();
464 for (
const int var_index : unique_var_indices) {
465 vars = {scip_resultant_var, scip_variables[var_index]};
471 if (minmax.has_constant()) {
472 vars = {scip_resultant_var};
475 add_lin_constraint(
"_constant", minmax.constant(), minmax.constant()));
479 const std::string name =
480 gen_cst.has_name() ? absl::StrCat(gen_cst.name(),
"_disj") :
"";
482 scip, scip_cst, name.c_str(),
483 cons.size(), cons.data(),
nullptr));
488 for (
const int var_index : unique_var_indices) {
489 vars = {scip_resultant_var, scip_variables[var_index]};
491 if (gen_cst.has_min_constraint()) {
495 RETURN_IF_ERROR(add_lin_constraint(absl::StrCat(
"_ineq_", var_index), 0.0,
499 if (minmax.has_constant()) {
500 vars = {scip_resultant_var};
502 if (gen_cst.has_min_constraint()) {
504 add_lin_constraint(
"_ineq_constant", -
kInfinity, minmax.constant()));
507 add_lin_constraint(
"_ineq_constant", minmax.constant(),
kInfinity));
510 for (SCIP_CONS* scip_cons : cons) {
511 scip_constraints->push_back(scip_cons);
514 return absl::OkStatus();
519 std::vector<SCIP_VAR*>* scip_variables,
520 std::vector<SCIP_CONS*>* scip_constraints) {
521 CHECK(scip !=
nullptr);
522 CHECK(scip_variables !=
nullptr);
523 CHECK(scip_constraints !=
nullptr);
525 constexpr double kInfinity = std::numeric_limits<double>::infinity();
527 const int size = quadobj.coefficient_size();
528 if (size == 0)
return absl::OkStatus();
532 scip_variables->push_back(
nullptr);
537 SCIP_VARTYPE_CONTINUOUS));
540 scip_constraints->push_back(
nullptr);
541 SCIP_VAR* linvars[1] = {scip_variables->back()};
542 double lincoefs[1] = {-1};
543 std::vector<SCIP_VAR*> quadvars1(size,
nullptr);
544 std::vector<SCIP_VAR*> quadvars2(size,
nullptr);
545 std::vector<double> quadcoefs(size, 0);
546 for (
int i = 0;
i < size; ++
i) {
547 quadvars1[
i] = scip_variables->at(quadobj.qvar1_index(i));
548 quadvars2[
i] = scip_variables->at(quadobj.qvar2_index(i));
549 quadcoefs[
i] = quadobj.coefficient(i);
552 scip, &scip_constraints->back(),
"quadobj",
553 1, linvars, lincoefs,
554 size, quadvars1.data(),
555 quadvars2.data(), quadcoefs.data(),
559 return absl::OkStatus();
563 const std::vector<SCIP_VAR*>& scip_variables) {
564 CHECK(scip !=
nullptr);
565 if (!model.has_solution_hint())
return absl::OkStatus();
569 bool is_solution_partial =
570 solution_hint.var_index_size() != model.variable_size();
571 if (is_solution_partial) {
573 SCIPcreatePartialSol(scip, &
solution,
nullptr));
576 SCIPcreateSol(scip, &
solution,
nullptr));
579 for (
int i = 0;
i < solution_hint.var_index_size(); ++
i) {
581 scip,
solution, scip_variables[solution_hint.var_index(i)],
582 solution_hint.var_value(i)));
588 return absl::OkStatus();
595 CHECK(scip !=
nullptr);
596 const double infinity = SCIPinfinity(scip);
601 return absl::StrFormat(
602 "Variable %i's lower bound is considered +infinity", v);
605 return absl::StrFormat(
606 "Variable %i's upper bound is considered -infinity", v);
609 if (coeff >= infinity || coeff <= -infinity) {
610 return absl::StrFormat(
611 "Variable %i's objective coefficient is considered infinite", v);
618 return absl::StrFormat(
619 "Constraint %d's lower_bound is considered +infinity", c);
622 return absl::StrFormat(
623 "Constraint %d's upper_bound is considered -infinity", c);
627 return absl::StrFormat(
628 "Constraint %d's coefficient #%d is considered infinite", c, i);
638 return absl::StrFormat(
639 "Quadratic constraint %d's lower_bound is considered +infinity",
643 return absl::StrFormat(
644 "Quadratic constraint %d's upper_bound is considered -infinity",
650 if (coefficient >= infinity || coefficient <= -infinity) {
651 return absl::StrFormat(
652 "Quadratic constraint %d's linear coefficient #%d considered "
659 const double qcoefficient =
661 if (qcoefficient >= infinity || qcoefficient <= -infinity) {
662 return absl::StrFormat(
663 "Quadratic constraint %d's quadratic coefficient #%d "
664 "considered infinite",
672 return absl::StrFormat(
673 "Min constraint %d's coefficient constant considered infinite",
680 return absl::StrFormat(
681 "Max constraint %d's coefficient constant considered infinite",
692 if (std::abs(quad_obj.
coefficient(i)) >= infinity) {
693 return absl::StrFormat(
694 "Quadratic objective term #%d's coefficient is considered infinite",
700 for (
int i = 0; i < model.
solution_hint().var_value_size(); ++i) {
702 if (value >= infinity || value <= -infinity) {
703 return absl::StrFormat(
704 "Variable %i's solution hint is considered infinite",
712 return "Model's objective offset is considered infinite.";
721 const std::optional<LazyMutableCopy<MPModelProto>> optional_model =
723 if (!optional_model)
return response;
726 SCIP* scip =
nullptr;
727 std::vector<SCIP_VAR*> scip_variables(model.
variable_size(),
nullptr);
728 std::vector<SCIP_CONS*> scip_constraints(
731 auto delete_scip_objects = [&]() -> absl::Status {
733 if (scip ==
nullptr)
return absl::OkStatus();
734 for (SCIP_VAR* variable : scip_variables) {
735 if (variable !=
nullptr) {
739 for (SCIP_CONS* constraint : scip_constraints) {
740 if (constraint !=
nullptr) {
745 return absl::OkStatus();
748 auto scip_deleter = absl::MakeCleanup([delete_scip_objects]() {
749 const absl::Status deleter_status = delete_scip_objects();
750 LOG_IF(DFATAL, !deleter_status.ok()) << deleter_status;
755 const std::string scip_model_invalid_error =
757 if (!scip_model_invalid_error.empty()) {
764 request->solver_specific_parameters(), scip);
765 if (!parameters_status.ok()) {
768 std::string(parameters_status.message()));
778 SCIPsetIntParam(scip,
"timing/clocktype", SCIP_CLOCKTYPE_WALL));
779 if (request->solver_time_limit_seconds() > 0 &&
780 request->solver_time_limit_seconds() < 1e20) {
782 scip,
"limits/time", request->solver_time_limit_seconds()));
784 SCIPsetMessagehdlrQuiet(scip, !request->enable_internal_solver_output());
798 scip, &scip_variables[v], variable.
name().c_str(),
799 lower_bound, upper_bound,
802 : SCIP_VARTYPE_CONTINUOUS));
807 std::vector<SCIP_VAR*> ct_variables;
808 std::vector<double> ct_coefficients;
812 ct_variables.resize(size,
nullptr);
813 ct_coefficients.resize(size, 0);
814 for (
int i = 0; i < size; ++i) {
815 ct_variables[i] = scip_variables[constraint.
var_index(i)];
823 scip, &scip_constraints[c],
824 constraint.
name().c_str(),
826 ct_coefficients.data(),
827 lower_bound, upper_bound,
842 std::vector<SCIP_VAR*> ct_qvariables1;
843 std::vector<SCIP_VAR*> ct_qvariables2;
844 std::vector<double> ct_qcoefficients;
851 gen_cst, scip, &scip_constraints[lincst_size + c],
852 &scip_variables, &scip_constraints, &ct_variables,
858 &scip_constraints[lincst_size + c],
859 &ct_variables, &ct_coefficients));
864 gen_cst, scip_variables, scip, &scip_constraints[lincst_size + c],
865 &ct_variables, &ct_coefficients, &ct_qvariables1, &ct_qvariables2,
871 &scip_constraints[lincst_size + c]));
876 &scip_constraints[lincst_size + c],
882 &scip_constraints[lincst_size + c],
889 gen_cst, scip_variables, scip, &scip_constraints[lincst_size + c],
890 &scip_constraints, &ct_variables));
894 return absl::UnimplementedError(
895 absl::StrFormat(
"General constraints of type %i not supported.",
903 &scip_variables, &scip_constraints));
908 if (!absl::GetFlag(FLAGS_scip_proto_solver_output_cip_file).empty()) {
909 SCIPwriteOrigProblem(
910 scip, absl::GetFlag(FLAGS_scip_proto_solver_output_cip_file).c_str(),
913 const absl::Time time_before = absl::Now();
919 const absl::Duration solving_duration = absl::Now() - time_before;
921 VLOG(1) <<
"Finished solving in ScipSolveProto(), walltime = "
922 << solving_duration <<
", usertime = " << user_timer.
GetDuration();
925 absl::ToDoubleSeconds(solving_duration));
929 const int solution_count =
930 std::min(SCIPgetNSols(scip),
931 std::min(request->populate_additional_solutions_up_to(),
932 std::numeric_limits<int32_t>::max() - 1) +
934 if (solution_count > 0) {
937 auto scip_solution_to_repeated_field = [&](SCIP_SOL* scip_solution) {
938 google::protobuf::RepeatedField<double> variable_value;
941 double value = SCIPgetSolVal(scip, scip_solution, scip_variables[v]);
943 value = std::round(value);
945 variable_value.AddAlreadyReserved(value);
947 return variable_value;
953 SCIP_SOL**
const scip_solutions = SCIPgetSols(scip);
957 scip_solution_to_repeated_field(scip_solutions[0]);
958 for (
int i = 1; i < solution_count; ++i) {
960 solution->set_objective_value(SCIPgetSolOrigObj(scip, scip_solutions[i]));
961 *
solution->mutable_variable_value() =
962 scip_solution_to_repeated_field(scip_solutions[i]);
966 const SCIP_STATUS scip_status = SCIPgetStatus(scip);
967 switch (scip_status) {
968 case SCIP_STATUS_OPTIMAL:
971 case SCIP_STATUS_GAPLIMIT:
975 case SCIP_STATUS_INFORUNBD:
982 DLOG(INFO) <<
"SCIP solve returned SCIP_STATUS_INFORUNBD, which we treat "
983 "as INFEASIBLE even though it may mean UNBOUNDED.";
985 "The model may actually be unbounded: SCIP returned "
986 "SCIP_STATUS_INFORUNBD");
987 ABSL_FALLTHROUGH_INTENDED;
988 case SCIP_STATUS_INFEASIBLE:
991 case SCIP_STATUS_UNBOUNDED:
995 if (solution_count > 0) {
1000 static_cast<int>(scip_status)));
1005 VLOG(1) <<
"ScipSolveProto() status="
#define ASSIGN_OR_RETURN(lhs, rexpr)
#define RETURN_IF_ERROR(expr)
absl::Duration GetDuration() const
void Start()
When Start() is called multiple times, only the most recent is used.
double lower_bound() const
const ::std::string & name() const
int var_index_size() const
repeated int32 var_index = 6 [packed = true];
int coefficient_size() const
repeated double coefficient = 7 [packed = true];
double coefficient(int index) const
::int32_t var_index(int index) const
double upper_bound() const
GeneralConstraintCase general_constraint_case() const
const ::operations_research::MPArrayWithConstantConstraint & max_constraint() const
const ::operations_research::MPArrayWithConstantConstraint & min_constraint() const
const ::operations_research::MPQuadraticConstraint & quadratic_constraint() const
const ::operations_research::MPVariableProto & variable(int index) const
int variable_size() const
repeated .operations_research.MPVariableProto variable = 3;
const ::operations_research::MPGeneralConstraintProto & general_constraint(int index) const
const ::operations_research::MPQuadraticObjective & quadratic_objective() const
const ::operations_research::MPConstraintProto & constraint(int index) const
int general_constraint_size() const
repeated .operations_research.MPGeneralConstraintProto general_constraint = 7;
const ::operations_research::PartialVariableAssignment & solution_hint() const
bool has_quadratic_objective() const
optional .operations_research.MPQuadraticObjective quadratic_objective = 8;
bool has_solution_hint() const
optional .operations_research.PartialVariableAssignment solution_hint = 6;
const ::std::string & name() const
int constraint_size() const
repeated .operations_research.MPConstraintProto constraint = 4;
double objective_offset() const
double qcoefficient(int index) const
double coefficient(int index) const
double lower_bound() const
int var_index_size() const
repeated int32 var_index = 1;
double upper_bound() const
double coefficient(int index) const
int coefficient_size() const
repeated double coefficient = 3;
::operations_research::MPSolveInfo *PROTOBUF_NONNULL mutable_solve_info()
::operations_research::MPSolverResponseStatus status() const
void set_objective_value(double value)
void set_best_objective_bound(double value)
void set_status_str(Arg_ &&arg, Args_... args)
::google::protobuf::RepeatedField< double > *PROTOBUF_NONNULL mutable_variable_value()
::operations_research::MPSolution *PROTOBUF_NONNULL add_additional_solutions()
void set_status(::operations_research::MPSolverResponseStatus value)
void set_solve_wall_time_seconds(double value)
void set_solve_user_time_seconds(double value)
static constexpr Type SOS1_DEFAULT
static constexpr Type SOS2
double lower_bound() const
double upper_bound() const
const ::std::string & name() const
double objective_coefficient() const
::int32_t var_index(int index) const
double var_value(int index) const
In SWIG mode, we don't want anything besides these top-level includes.
static constexpr double kInfinity
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
absl::StatusOr< MPSolutionResponse > ScipSolveProto(LazyMutableCopy< MPModelRequest > request)
std::string FindErrorInMPModelForScip(const MPModelProto &model, SCIP *scip)
const ::std::string & MPSolverResponseStatus_Name(T value)
@ MPSOLVER_MODEL_INVALID_SOLVER_PARAMETERS
std::optional< LazyMutableCopy< MPModelProto > > GetMPModelOrPopulateResponse(LazyMutableCopy< MPModelRequest > &request, MPSolutionResponse *response)
absl::Status LegacyScipSetSolverSpecificParameters(absl::string_view parameters, SCIP *scip)
trees with all degrees equal w the current value of w
#define SCIP_TO_STATUS(x)
#define RETURN_IF_SCIP_ERROR(x)
ABSL_FLAG(std::string, scip_proto_solver_output_cip_file, "", "If given, saves the generated CIP file here. Useful for " "reporting bugs to SCIP.")