OR-Tools  9.2
gscip.cc
Go to the documentation of this file.
1// Copyright 2010-2021 Google LLC
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14#include "ortools/gscip/gscip.h"
15
16#include <stdio.h>
17
18#include <algorithm>
19#include <cstdint>
20#include <functional>
21#include <limits>
22#include <memory>
23#include <string>
24#include <utility>
25#include <vector>
26
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"
43#include "scip/cons_linear.h"
44#include "scip/cons_quadratic.h"
45#include "scip/scip.h"
46#include "scip/scip_general.h"
47#include "scip/scip_param.h"
48#include "scip/scip_prob.h"
49#include "scip/scip_solvingstats.h"
50#include "scip/scipdefplugins.h"
51#include "scip/type_cons.h"
52#include "scip/type_scip.h"
53#include "scip/type_var.h"
54
55namespace operations_research {
56
57#define RETURN_ERROR_UNLESS(x) \
58 if (!(x)) \
59 return util::StatusBuilder(absl::InvalidArgumentError(absl::StrFormat( \
60 "Condition violated at %s:%d: %s", __FILE__, __LINE__, #x)))
61
62namespace {
63
64constexpr absl::string_view kLinearConstraintHandlerName = "linear";
65
66SCIP_VARTYPE ConvertVarType(const GScipVarType var_type) {
67 switch (var_type) {
69 return SCIP_VARTYPE_CONTINUOUS;
71 return SCIP_VARTYPE_IMPLINT;
73 return SCIP_VARTYPE_INTEGER;
74 }
75}
76
77GScipVarType ConvertVarType(const SCIP_VARTYPE var_type) {
78 switch (var_type) {
79 case SCIP_VARTYPE_CONTINUOUS:
81 case SCIP_VARTYPE_IMPLINT:
83 case SCIP_VARTYPE_INTEGER:
84 case SCIP_VARTYPE_BINARY:
86 }
87}
88
89GScipOutput::Status ConvertStatus(const SCIP_STATUS scip_status) {
90 switch (scip_status) {
91 case SCIP_STATUS_UNKNOWN:
93 case SCIP_STATUS_USERINTERRUPT:
95 case SCIP_STATUS_BESTSOLLIMIT:
97 case SCIP_STATUS_MEMLIMIT:
99 case SCIP_STATUS_NODELIMIT:
101 case SCIP_STATUS_RESTARTLIMIT:
103 case SCIP_STATUS_SOLLIMIT:
105 case SCIP_STATUS_STALLNODELIMIT:
107 case SCIP_STATUS_TIMELIMIT:
109 case SCIP_STATUS_TOTALNODELIMIT:
111 case SCIP_STATUS_OPTIMAL:
113 case SCIP_STATUS_GAPLIMIT:
115 case SCIP_STATUS_INFEASIBLE:
117 case SCIP_STATUS_UNBOUNDED:
119 case SCIP_STATUS_INFORUNBD:
121 case SCIP_STATUS_TERMINATE:
123 default:
124 LOG(FATAL) << "Unrecognized scip status: " << scip_status;
125 }
126}
127
128SCIP_PARAMEMPHASIS ConvertEmphasis(
129 const GScipParameters::Emphasis gscip_emphasis) {
130 switch (gscip_emphasis) {
132 return SCIP_PARAMEMPHASIS_DEFAULT;
134 return SCIP_PARAMEMPHASIS_CPSOLVER;
136 return SCIP_PARAMEMPHASIS_EASYCIP;
138 return SCIP_PARAMEMPHASIS_FEASIBILITY;
140 return SCIP_PARAMEMPHASIS_HARDLP;
142 return SCIP_PARAMEMPHASIS_OPTIMALITY;
144 return SCIP_PARAMEMPHASIS_COUNTER;
146 return SCIP_PARAMEMPHASIS_PHASEFEAS;
148 return SCIP_PARAMEMPHASIS_PHASEIMPROVE;
150 return SCIP_PARAMEMPHASIS_PHASEPROOF;
151 default:
152 LOG(FATAL) << "Unrecognized gscip_emphasis: "
153 << ProtoEnumToString(gscip_emphasis);
154 }
155}
156
157SCIP_PARAMSETTING ConvertMetaParamValue(
158 const GScipParameters::MetaParamValue gscip_meta_param_value) {
159 switch (gscip_meta_param_value) {
161 return SCIP_PARAMSETTING_DEFAULT;
163 return SCIP_PARAMSETTING_AGGRESSIVE;
165 return SCIP_PARAMSETTING_FAST;
167 return SCIP_PARAMSETTING_OFF;
168 default:
169 LOG(FATAL) << "Unrecognized gscip_meta_param_value: "
170 << ProtoEnumToString(gscip_meta_param_value);
171 }
172}
173
174absl::Status CheckSolutionsInOrder(const GScipResult& result,
175 const bool is_maximize) {
176 auto objective_as_good_as = [is_maximize](double left, double right) {
177 if (is_maximize) {
178 return left >= right;
179 }
180 return left <= right;
181 };
182 for (int i = 1; i < result.objective_values.size(); ++i) {
183 const double previous = result.objective_values[i - 1];
184 const double current = result.objective_values[i];
185 if (!objective_as_good_as(previous, current)) {
187 << "Expected SCIP solutions to be in best objective order "
188 "first, but for "
189 << (is_maximize ? "maximization" : "minimization")
190 << " problem, the " << i - 1 << " objective is " << previous
191 << " and the " << i << " objective is " << current;
192 }
193 }
194 return absl::OkStatus();
195}
196
197} // namespace
198
200 static GScipVariableOptions var_options;
201 return var_options;
202}
203
205 static GScipConstraintOptions constraint_options;
206 return constraint_options;
207}
208
209absl::Status GScip::SetParams(const GScipParameters& params,
210 const std::string& legacy_params) {
211 if (params.has_silence_output()) {
212 SCIPsetMessagehdlrQuiet(scip_, params.silence_output());
213 }
214 if (!params.search_logs_filename().empty()) {
215 SCIPsetMessagehdlrLogfile(scip_, params.search_logs_filename().c_str());
216 }
217
218 const SCIP_Bool set_param_quiet =
219 static_cast<SCIP_Bool>(!params.silence_output());
220
221 RETURN_IF_SCIP_ERROR(SCIPsetEmphasis(
222 scip_, ConvertEmphasis(params.emphasis()), set_param_quiet));
223 if (params.has_heuristics()) {
224 RETURN_IF_SCIP_ERROR(SCIPsetHeuristics(
225 scip_, ConvertMetaParamValue(params.heuristics()), set_param_quiet));
226 }
227 if (params.has_presolve()) {
228 RETURN_IF_SCIP_ERROR(SCIPsetPresolving(
229 scip_, ConvertMetaParamValue(params.presolve()), set_param_quiet));
230 }
231 if (params.has_separating()) {
232 RETURN_IF_SCIP_ERROR(SCIPsetSeparating(
233 scip_, ConvertMetaParamValue(params.separating()), set_param_quiet));
234 }
235 for (const auto& bool_param : params.bool_params()) {
237 (SCIPsetBoolParam(scip_, bool_param.first.c_str(), bool_param.second)));
238 }
239 for (const auto& int_param : params.int_params()) {
241 (SCIPsetIntParam(scip_, int_param.first.c_str(), int_param.second)));
242 }
243 for (const auto& long_param : params.long_params()) {
244 RETURN_IF_SCIP_ERROR((SCIPsetLongintParam(scip_, long_param.first.c_str(),
245 long_param.second)));
246 }
247 for (const auto& char_param : params.char_params()) {
248 if (char_param.second.size() != 1) {
249 return absl::InvalidArgumentError(
250 absl::StrCat("Character parameters must be single character strings, "
251 "but parameter: ",
252 char_param.first, " was: ", char_param.second));
253 }
254 RETURN_IF_SCIP_ERROR((SCIPsetCharParam(scip_, char_param.first.c_str(),
255 char_param.second[0])));
256 }
257 for (const auto& string_param : params.string_params()) {
258 RETURN_IF_SCIP_ERROR((SCIPsetStringParam(scip_, string_param.first.c_str(),
259 string_param.second.c_str())));
260 }
261 for (const auto& real_param : params.real_params()) {
263 (SCIPsetRealParam(scip_, real_param.first.c_str(), real_param.second)));
264 }
265 if (!legacy_params.empty()) {
267 LegacyScipSetSolverSpecificParameters(legacy_params, scip_));
268 }
269 return absl::OkStatus();
270}
271
272absl::StatusOr<std::unique_ptr<GScip>> GScip::Create(
273 const std::string& problem_name) {
274 SCIP* scip = nullptr;
275 RETURN_IF_SCIP_ERROR(SCIPcreate(&scip));
276 RETURN_IF_SCIP_ERROR(SCIPincludeDefaultPlugins(scip));
277 RETURN_IF_SCIP_ERROR(SCIPcreateProbBasic(scip, problem_name.c_str()));
278 // NOTE(user): the constructor is private, so we cannot call make_unique.
279 return absl::WrapUnique(new GScip(scip));
280}
281
282GScip::GScip(SCIP* scip) : scip_(scip) {}
283
284double GScip::ScipInf() { return SCIPinfinity(scip_); }
285
286absl::Status GScip::FreeTransform() {
287 return SCIP_TO_STATUS(SCIPfreeTransform(scip_));
288}
289
290std::string GScip::ScipVersion() {
291 return absl::StrFormat("SCIP %d.%d.%d [LP solver: %s]", SCIPmajorVersion(),
292 SCIPminorVersion(), SCIPtechVersion(),
294}
295
297 if (scip_ == nullptr) {
298 return true;
299 }
300 return SCIPinterruptSolve(scip_) == SCIP_OKAY;
301}
302
303absl::Status GScip::CleanUp() {
304 if (scip_ != nullptr) {
305 for (SCIP_VAR* variable : variables_) {
306 if (variable != nullptr) {
307 RETURN_IF_SCIP_ERROR(SCIPreleaseVar(scip_, &variable));
308 }
309 }
310 for (SCIP_CONS* constraint : constraints_) {
311 if (constraint != nullptr) {
312 RETURN_IF_SCIP_ERROR(SCIPreleaseCons(scip_, &constraint));
313 }
314 }
315 RETURN_IF_SCIP_ERROR(SCIPfree(&scip_));
316 }
317 return absl::OkStatus();
318}
319
321 const absl::Status clean_up_status = CleanUp();
322 LOG_IF(DFATAL, !clean_up_status.ok()) << clean_up_status;
323}
324
325absl::StatusOr<SCIP_VAR*> GScip::AddVariable(
326 double lb, double ub, double obj_coef, GScipVarType var_type,
327 const std::string& var_name, const GScipVariableOptions& options) {
328 SCIP_VAR* var = nullptr;
329 lb = ScipInfClamp(lb);
330 ub = ScipInfClamp(ub);
331 RETURN_IF_SCIP_ERROR(SCIPcreateVarBasic(scip_, /*var=*/&var,
332 /*name=*/var_name.c_str(),
333 /*lb=*/lb, /*ub=*/ub,
334 /*obj=*/obj_coef,
335 ConvertVarType(var_type)));
336 RETURN_IF_SCIP_ERROR(SCIPvarSetInitial(var, options.initial));
337 RETURN_IF_SCIP_ERROR(SCIPvarSetRemovable(var, options.removable));
338 RETURN_IF_SCIP_ERROR(SCIPaddVar(scip_, var));
339 if (options.keep_alive) {
340 variables_.insert(var);
341 } else {
342 RETURN_IF_SCIP_ERROR(SCIPreleaseVar(scip_, &var));
343 }
344 return var;
345}
346
347absl::Status GScip::MaybeKeepConstraintAlive(
348 SCIP_CONS* constraint, const GScipConstraintOptions& options) {
349 if (options.keep_alive) {
350 constraints_.insert(constraint);
351 } else {
352 RETURN_IF_SCIP_ERROR(SCIPreleaseCons(scip_, &constraint));
353 }
354 return absl::OkStatus();
355}
356
357absl::StatusOr<SCIP_CONS*> GScip::AddLinearConstraint(
358 const GScipLinearRange& range, const std::string& name,
359 const GScipConstraintOptions& options) {
360 SCIP_CONS* constraint = nullptr;
361 RETURN_ERROR_UNLESS(range.variables.size() == range.coefficients.size())
362 << "Error adding constraint: " << name << ".";
363 RETURN_IF_SCIP_ERROR(SCIPcreateConsLinear(
364 scip_, &constraint, name.c_str(), range.variables.size(),
365 const_cast<SCIP_VAR**>(range.variables.data()),
366 const_cast<double*>(range.coefficients.data()),
367 ScipInfClamp(range.lower_bound), ScipInfClamp(range.upper_bound),
368 /*initial=*/options.initial,
369 /*separate=*/options.separate,
370 /*enforce=*/options.enforce,
371 /*check=*/options.check,
372 /*propagate=*/options.propagate,
373 /*local=*/options.local,
374 /*modifiable=*/options.modifiable,
375 /*dynamic=*/options.dynamic,
376 /*removable=*/options.removable,
377 /*stickingatnode=*/options.sticking_at_node));
378 RETURN_IF_SCIP_ERROR(SCIPaddCons(scip_, constraint));
379 RETURN_IF_ERROR(MaybeKeepConstraintAlive(constraint, options));
380 return constraint;
381}
382
383absl::StatusOr<SCIP_CONS*> GScip::AddQuadraticConstraint(
384 const GScipQuadraticRange& range, const std::string& name,
385 const GScipConstraintOptions& options) {
386 SCIP_CONS* constraint = nullptr;
387 const int num_lin_vars = range.linear_variables.size();
388 RETURN_ERROR_UNLESS(num_lin_vars == range.linear_coefficients.size())
389 << "Error adding quadratic constraint: " << name << " in linear term.";
390 const int num_quad_vars = range.quadratic_variables1.size();
391 RETURN_ERROR_UNLESS(num_quad_vars == range.quadratic_variables2.size())
392 << "Error adding quadratic constraint: " << name << " in quadratic term.";
393 RETURN_ERROR_UNLESS(num_quad_vars == range.quadratic_coefficients.size())
394 << "Error adding quadratic constraint: " << name << " in quadratic term.";
395 RETURN_IF_SCIP_ERROR(SCIPcreateConsQuadratic(
396 scip_, &constraint, name.c_str(), num_lin_vars,
397 const_cast<SCIP_Var**>(range.linear_variables.data()),
398 const_cast<double*>(range.linear_coefficients.data()), num_quad_vars,
399 const_cast<SCIP_Var**>(range.quadratic_variables1.data()),
400 const_cast<SCIP_Var**>(range.quadratic_variables2.data()),
401 const_cast<double*>(range.quadratic_coefficients.data()),
402 ScipInfClamp(range.lower_bound), ScipInfClamp(range.upper_bound),
403 /*initial=*/options.initial,
404 /*separate=*/options.separate,
405 /*enforce=*/options.enforce,
406 /*check=*/options.check,
407 /*propagate=*/options.propagate,
408 /*local=*/options.local,
409 /*modifiable=*/options.modifiable,
410 /*dynamic=*/options.dynamic,
411 /*removable=*/options.removable));
412 RETURN_IF_SCIP_ERROR(SCIPaddCons(scip_, constraint));
413 RETURN_IF_ERROR(MaybeKeepConstraintAlive(constraint, options));
414 return constraint;
415}
416
417absl::StatusOr<SCIP_CONS*> GScip::AddIndicatorConstraint(
418 const GScipIndicatorConstraint& indicator_constraint,
419 const std::string& name, const GScipConstraintOptions& options) {
420 SCIP_VAR* indicator = indicator_constraint.indicator_variable;
421 RETURN_ERROR_UNLESS(indicator != nullptr)
422 << "Error adding indicator constraint: " << name << ".";
423 if (indicator_constraint.negate_indicator) {
424 RETURN_IF_SCIP_ERROR(SCIPgetNegatedVar(scip_, indicator, &indicator));
425 }
426
427 SCIP_CONS* constraint = nullptr;
428 RETURN_ERROR_UNLESS(indicator_constraint.variables.size() ==
429 indicator_constraint.coefficients.size())
430 << "Error adding indicator constraint: " << name << ".";
431 RETURN_IF_SCIP_ERROR(SCIPcreateConsIndicator(
432 scip_, &constraint, name.c_str(), indicator,
433 indicator_constraint.variables.size(),
434 const_cast<SCIP_Var**>(indicator_constraint.variables.data()),
435 const_cast<double*>(indicator_constraint.coefficients.data()),
436 ScipInfClamp(indicator_constraint.upper_bound),
437 /*initial=*/options.initial,
438 /*separate=*/options.separate,
439 /*enforce=*/options.enforce,
440 /*check=*/options.check,
441 /*propagate=*/options.propagate,
442 /*local=*/options.local,
443 /*dynamic=*/options.dynamic,
444 /*removable=*/options.removable,
445 /*stickingatnode=*/options.sticking_at_node));
446 RETURN_IF_SCIP_ERROR(SCIPaddCons(scip_, constraint));
447 RETURN_IF_ERROR(MaybeKeepConstraintAlive(constraint, options));
448 return constraint;
449}
450
451absl::StatusOr<SCIP_CONS*> GScip::AddAndConstraint(
452 const GScipLogicalConstraintData& logical_data, const std::string& name,
453 const GScipConstraintOptions& options) {
454 RETURN_ERROR_UNLESS(logical_data.resultant != nullptr)
455 << "Error adding and constraint: " << name << ".";
456 SCIP_CONS* constraint = nullptr;
458 SCIPcreateConsAnd(scip_, &constraint, name.c_str(),
459 logical_data.resultant, logical_data.operators.size(),
460 const_cast<SCIP_VAR**>(logical_data.operators.data()),
461 /*initial=*/options.initial,
462 /*separate=*/options.separate,
463 /*enforce=*/options.enforce,
464 /*check=*/options.check,
465 /*propagate=*/options.propagate,
466 /*local=*/options.local,
467 /*modifiable=*/options.modifiable,
468 /*dynamic=*/options.dynamic,
469 /*removable=*/options.removable,
470 /*stickingatnode=*/options.sticking_at_node));
471 RETURN_IF_SCIP_ERROR(SCIPaddCons(scip_, constraint));
472 RETURN_IF_ERROR(MaybeKeepConstraintAlive(constraint, options));
473 return constraint;
474}
475
476absl::StatusOr<SCIP_CONS*> GScip::AddOrConstraint(
477 const GScipLogicalConstraintData& logical_data, const std::string& name,
478 const GScipConstraintOptions& options) {
479 RETURN_ERROR_UNLESS(logical_data.resultant != nullptr)
480 << "Error adding or constraint: " << name << ".";
481 SCIP_CONS* constraint = nullptr;
483 SCIPcreateConsOr(scip_, &constraint, name.c_str(), logical_data.resultant,
484 logical_data.operators.size(),
485 const_cast<SCIP_Var**>(logical_data.operators.data()),
486 /*initial=*/options.initial,
487 /*separate=*/options.separate,
488 /*enforce=*/options.enforce,
489 /*check=*/options.check,
490 /*propagate=*/options.propagate,
491 /*local=*/options.local,
492 /*modifiable=*/options.modifiable,
493 /*dynamic=*/options.dynamic,
494 /*removable=*/options.removable,
495 /*stickingatnode=*/options.sticking_at_node));
496 RETURN_IF_SCIP_ERROR(SCIPaddCons(scip_, constraint));
497 RETURN_IF_ERROR(MaybeKeepConstraintAlive(constraint, options));
498 return constraint;
499}
500
501namespace {
502
503absl::Status ValidateSOSData(const GScipSOSData& sos_data,
504 const std::string& name) {
505 RETURN_ERROR_UNLESS(!sos_data.variables.empty())
506 << "Error adding SOS constraint: " << name << ".";
507 if (!sos_data.weights.empty()) {
508 RETURN_ERROR_UNLESS(sos_data.variables.size() == sos_data.weights.size())
509 << " Error adding SOS constraint: " << name << ".";
510 }
511 absl::flat_hash_set<double> distinct_weights;
512 for (const double w : sos_data.weights) {
513 RETURN_ERROR_UNLESS(!distinct_weights.contains(w))
514 << "Error adding SOS constraint: " << name
515 << ", weights must be distinct, but found value " << w << " twice.";
516 distinct_weights.insert(w);
517 }
518 return absl::OkStatus();
519}
520
521} // namespace
522
523absl::StatusOr<SCIP_CONS*> GScip::AddSOS1Constraint(
524 const GScipSOSData& sos_data, const std::string& name,
525 const GScipConstraintOptions& options) {
526 RETURN_IF_ERROR(ValidateSOSData(sos_data, name));
527 SCIP_CONS* constraint = nullptr;
528 double* weights = nullptr;
529 if (!sos_data.weights.empty()) {
530 weights = const_cast<double*>(sos_data.weights.data());
531 }
532
533 RETURN_IF_SCIP_ERROR(SCIPcreateConsSOS1(
534 scip_, &constraint, name.c_str(), sos_data.variables.size(),
535 const_cast<SCIP_Var**>(sos_data.variables.data()), weights,
536 /*initial=*/options.initial,
537 /*separate=*/options.separate,
538 /*enforce=*/options.enforce,
539 /*check=*/options.check,
540 /*propagate=*/options.propagate,
541 /*local=*/options.local,
542 /*dynamic=*/options.dynamic,
543 /*removable=*/options.removable,
544 /*stickingatnode=*/options.sticking_at_node));
545 RETURN_IF_SCIP_ERROR(SCIPaddCons(scip_, constraint));
546 RETURN_IF_ERROR(MaybeKeepConstraintAlive(constraint, options));
547 return constraint;
548}
549
550absl::StatusOr<SCIP_CONS*> GScip::AddSOS2Constraint(
551 const GScipSOSData& sos_data, const std::string& name,
552 const GScipConstraintOptions& options) {
553 RETURN_IF_ERROR(ValidateSOSData(sos_data, name));
554 SCIP_CONS* constraint = nullptr;
555 double* weights = nullptr;
556 if (!sos_data.weights.empty()) {
557 weights = const_cast<double*>(sos_data.weights.data());
558 }
559 RETURN_IF_SCIP_ERROR(SCIPcreateConsSOS2(
560 scip_, &constraint, name.c_str(), sos_data.variables.size(),
561 const_cast<SCIP_Var**>(sos_data.variables.data()), weights,
562 /*initial=*/options.initial,
563 /*separate=*/options.separate,
564 /*enforce=*/options.enforce,
565 /*check=*/options.check,
566 /*propagate=*/options.propagate,
567 /*local=*/options.local,
568 /*dynamic=*/options.dynamic,
569 /*removable=*/options.removable,
570 /*stickingatnode=*/options.sticking_at_node));
571 RETURN_IF_SCIP_ERROR(SCIPaddCons(scip_, constraint));
572 RETURN_IF_ERROR(MaybeKeepConstraintAlive(constraint, options));
573 return constraint;
574}
575
576absl::Status GScip::SetMaximize(bool is_maximize) {
577 RETURN_IF_SCIP_ERROR(SCIPsetObjsense(
578 scip_, is_maximize ? SCIP_OBJSENSE_MAXIMIZE : SCIP_OBJSENSE_MINIMIZE));
579 return absl::OkStatus();
580}
581
582absl::Status GScip::SetObjectiveOffset(double offset) {
583 double old_offset = SCIPgetOrigObjoffset(scip_);
584 double delta_offset = offset - old_offset;
585 RETURN_IF_SCIP_ERROR(SCIPaddOrigObjoffset(scip_, delta_offset));
586 return absl::OkStatus();
587}
588
590 return SCIPgetObjsense(scip_) == SCIP_OBJSENSE_MAXIMIZE;
591}
592
593double GScip::ObjectiveOffset() { return SCIPgetOrigObjoffset(scip_); }
594
595absl::Status GScip::SetBranchingPriority(SCIP_VAR* var, int priority) {
596 RETURN_IF_SCIP_ERROR(SCIPchgVarBranchPriority(scip_, var, priority));
597 return absl::OkStatus();
598}
599
600absl::Status GScip::SetLb(SCIP_VAR* var, double lb) {
601 lb = ScipInfClamp(lb);
602 RETURN_IF_SCIP_ERROR(SCIPchgVarLb(scip_, var, lb));
603 return absl::OkStatus();
604}
605
606absl::Status GScip::SetUb(SCIP_VAR* var, double ub) {
607 ub = ScipInfClamp(ub);
608 RETURN_IF_SCIP_ERROR(SCIPchgVarUb(scip_, var, ub));
609 return absl::OkStatus();
610}
611
612absl::Status GScip::SetObjCoef(SCIP_VAR* var, double obj_coef) {
613 RETURN_IF_SCIP_ERROR(SCIPchgVarObj(scip_, var, obj_coef));
614 return absl::OkStatus();
615}
616
617absl::Status GScip::SetVarType(SCIP_VAR* var, GScipVarType var_type) {
618 SCIP_Bool infeasible;
620 SCIPchgVarType(scip_, var, ConvertVarType(var_type), &infeasible));
621 return absl::OkStatus();
622}
623
624absl::Status GScip::DeleteVariable(SCIP_VAR* var) {
625 SCIP_Bool did_delete;
626 RETURN_IF_SCIP_ERROR(SCIPdelVar(scip_, var, &did_delete));
627 RETURN_ERROR_UNLESS(static_cast<bool>(did_delete))
628 << "Failed to delete variable named: " << Name(var);
629 variables_.erase(var);
630 RETURN_IF_SCIP_ERROR(SCIPreleaseVar(scip_, &var));
631 return absl::OkStatus();
632}
633
635 const absl::flat_hash_set<SCIP_VAR*>& vars) {
636 for (SCIP_CONS* constraint : constraints_) {
637 if (!IsConstraintLinear(constraint)) {
638 return absl::InvalidArgumentError(absl::StrCat(
639 "Model contains nonlinear constraint: ", Name(constraint)));
640 }
641 }
642 return absl::OkStatus();
643}
644
645absl::Status GScip::SafeBulkDelete(const absl::flat_hash_set<SCIP_VAR*>& vars) {
647 // Now, we can assume that all constraints are linear.
648 for (SCIP_CONS* constraint : constraints_) {
649 const absl::Span<SCIP_VAR* const> nonzeros =
650 LinearConstraintVariables(constraint);
651 const std::vector<SCIP_VAR*> nonzeros_copy(nonzeros.begin(),
652 nonzeros.end());
653 for (SCIP_VAR* var : nonzeros_copy) {
654 if (vars.contains(var)) {
656 }
657 }
658 }
659 for (SCIP_VAR* const var : vars) {
661 }
662 return absl::OkStatus();
663}
664
665double GScip::Lb(SCIP_VAR* var) {
666 return ScipInfUnclamp(SCIPvarGetLbOriginal(var));
667}
668
669double GScip::Ub(SCIP_VAR* var) {
670 return ScipInfUnclamp(SCIPvarGetUbOriginal(var));
671}
672
673double GScip::ObjCoef(SCIP_VAR* var) { return SCIPvarGetObj(var); }
674
676 return ConvertVarType(SCIPvarGetType(var));
677}
678
679absl::string_view GScip::Name(SCIP_VAR* var) { return SCIPvarGetName(var); }
680
681absl::string_view GScip::ConstraintType(SCIP_CONS* constraint) {
682 return absl::string_view(SCIPconshdlrGetName(SCIPconsGetHdlr(constraint)));
683}
684
685bool GScip::IsConstraintLinear(SCIP_CONS* constraint) {
686 return ConstraintType(constraint) == kLinearConstraintHandlerName;
687}
688
689absl::Span<const double> GScip::LinearConstraintCoefficients(
690 SCIP_CONS* constraint) {
691 int num_vars = SCIPgetNVarsLinear(scip_, constraint);
692 return absl::MakeConstSpan(SCIPgetValsLinear(scip_, constraint), num_vars);
693}
694
695absl::Span<SCIP_VAR* const> GScip::LinearConstraintVariables(
696 SCIP_CONS* constraint) {
697 int num_vars = SCIPgetNVarsLinear(scip_, constraint);
698 return absl::MakeConstSpan(SCIPgetVarsLinear(scip_, constraint), num_vars);
699}
700
701double GScip::LinearConstraintLb(SCIP_CONS* constraint) {
702 return ScipInfUnclamp(SCIPgetLhsLinear(scip_, constraint));
703}
704
705double GScip::LinearConstraintUb(SCIP_CONS* constraint) {
706 return ScipInfUnclamp(SCIPgetRhsLinear(scip_, constraint));
707}
708
709absl::string_view GScip::Name(SCIP_CONS* constraint) {
710 return SCIPconsGetName(constraint);
711}
712
713absl::Status GScip::SetLinearConstraintLb(SCIP_CONS* constraint, double lb) {
714 lb = ScipInfClamp(lb);
715 RETURN_IF_SCIP_ERROR(SCIPchgLhsLinear(scip_, constraint, lb));
716 return absl::OkStatus();
717}
718
719absl::Status GScip::SetLinearConstraintUb(SCIP_CONS* constraint, double ub) {
720 ub = ScipInfClamp(ub);
721 RETURN_IF_SCIP_ERROR(SCIPchgRhsLinear(scip_, constraint, ub));
722 return absl::OkStatus();
723}
724
725absl::Status GScip::DeleteConstraint(SCIP_CONS* constraint) {
726 RETURN_IF_SCIP_ERROR(SCIPdelCons(scip_, constraint));
727 constraints_.erase(constraint);
728 RETURN_IF_SCIP_ERROR(SCIPreleaseCons(scip_, &constraint));
729 return absl::OkStatus();
730}
731
732absl::Status GScip::SetLinearConstraintCoef(SCIP_CONS* constraint,
733 SCIP_VAR* var, double value) {
734 // TODO(user): this operation is slow (linear in the nnz in the constraint).
735 // It would be better to just use a bulk operation, but there doesn't appear
736 // to be any?
737 RETURN_IF_SCIP_ERROR(SCIPchgCoefLinear(scip_, constraint, var, value));
738 return absl::OkStatus();
739}
740
741absl::StatusOr<GScipHintResult> GScip::SuggestHint(
742 const GScipSolution& partial_solution) {
743 SCIP_SOL* solution;
744 const int scip_num_vars = SCIPgetNOrigVars(scip_);
745 const bool is_solution_partial = partial_solution.size() < scip_num_vars;
746 if (is_solution_partial) {
747 RETURN_IF_SCIP_ERROR(SCIPcreatePartialSol(scip_, &solution, nullptr));
748 } else {
749 // This is actually a full solution
750 RETURN_ERROR_UNLESS(partial_solution.size() == scip_num_vars)
751 << "Error suggesting hint.";
752 RETURN_IF_SCIP_ERROR(SCIPcreateSol(scip_, &solution, nullptr));
753 }
754 for (const auto& var_value_pair : partial_solution) {
755 RETURN_IF_SCIP_ERROR(SCIPsetSolVal(scip_, solution, var_value_pair.first,
756 var_value_pair.second));
757 }
758 if (!is_solution_partial) {
759 SCIP_Bool is_feasible;
760 RETURN_IF_SCIP_ERROR(SCIPcheckSol(
761 scip_, solution, /*printreason=*/false, /*completely=*/true,
762 /*checkbounds=*/true, /*checkintegrality=*/true, /*checklprows=*/true,
763 &is_feasible));
764 if (!static_cast<bool>(is_feasible)) {
765 RETURN_IF_SCIP_ERROR(SCIPfreeSol(scip_, &solution));
767 }
768 }
769 SCIP_Bool is_stored;
770 RETURN_IF_SCIP_ERROR(SCIPaddSolFree(scip_, &solution, &is_stored));
771 if (static_cast<bool>(is_stored)) {
773 } else {
775 }
776}
777
778absl::StatusOr<GScipResult> GScip::Solve(
779 const GScipParameters& params, const std::string& legacy_params,
780 const GScipMessageHandler message_handler) {
781 // A four step process:
782 // 1. Apply parameters.
783 // 2. Solve the problem.
784 // 3. Extract solution and solve statistics.
785 // 4. Prepare the solver for further modification/solves (reset parameters,
786 // free the solutions found).
787 GScipResult result;
788
789 // Step 1: apply parameters.
790 const absl::Status param_status = SetParams(params, legacy_params);
791 if (!param_status.ok()) {
793 // Conversion to std::string for open source build.
795 std::string(param_status.message())); // NOLINT
796 return result;
797 }
798 if (params.print_scip_model()) {
799 RETURN_IF_SCIP_ERROR(SCIPwriteOrigProblem(scip_, nullptr, "cip", FALSE));
800 }
801 if (!params.scip_model_filename().empty()) {
802 RETURN_IF_SCIP_ERROR(SCIPwriteOrigProblem(
803 scip_, params.scip_model_filename().c_str(), "cip", FALSE));
804 }
805 if (params.has_objective_limit()) {
807 SCIPsetObjlimit(scip_, ScipInfClamp(params.objective_limit())));
808 }
809
810 // Install the message handler if necessary. We do this after setting the
811 // parameters so that parameters that applies to the default message handler
812 // like `quiet` are indeed applied to it and not to our temporary
813 // handler.
816 MessageHandlerPtr previous_handler;
817 MessageHandlerPtr new_handler;
818 if (message_handler != nullptr) {
819 previous_handler = CaptureMessageHandlerPtr(SCIPgetMessagehdlr(scip_));
820 ASSIGN_OR_RETURN(new_handler,
821 internal::MakeSCIPMessageHandler(message_handler));
822 SCIPsetMessagehdlr(scip_, new_handler.get());
823 }
824 // Make sure we prevent any call of message_handler after this function has
825 // returned, until the new_handler is reset (see below).
826 const internal::ScopedSCIPMessageHandlerDisabler new_handler_disabler(
827 new_handler);
828
829 // Step 2: Solve.
830 // NOTE(user): after solve, SCIP will either be in stage PRESOLVING,
831 // SOLVING, OR SOLVED.
832 if (GScipMaxNumThreads(params) > 1) {
833 RETURN_IF_SCIP_ERROR(SCIPsolveConcurrent(scip_));
834 } else {
835 RETURN_IF_SCIP_ERROR(SCIPsolve(scip_));
836 }
837 const SCIP_STAGE stage = SCIPgetStage(scip_);
838 if (stage != SCIP_STAGE_PRESOLVING && stage != SCIP_STAGE_SOLVING &&
839 stage != SCIP_STAGE_SOLVED) {
842 absl::StrCat("Unpexpected SCIP final stage= ", stage,
843 " was expected to be either SCIP_STAGE_PRESOLVING, "
844 "SCIP_STAGE_SOLVING, or SCIP_STAGE_SOLVED"));
845 return result;
846 }
847 if (params.print_detailed_solving_stats()) {
848 RETURN_IF_SCIP_ERROR(SCIPprintStatistics(scip_, nullptr));
849 }
850 if (!params.detailed_solving_stats_filename().empty()) {
851 FILE* file = fopen(params.detailed_solving_stats_filename().c_str(), "w");
852 if (file == nullptr) {
853 return absl::InvalidArgumentError(absl::StrCat(
854 "Could not open file: ", params.detailed_solving_stats_filename(),
855 " to write SCIP solve stats."));
856 }
857 RETURN_IF_SCIP_ERROR(SCIPprintStatistics(scip_, file));
858 int close_result = fclose(file);
859 if (close_result != 0) {
860 return absl::InvalidArgumentError(absl::StrCat(
861 "Error: ", close_result,
862 " closing file: ", params.detailed_solving_stats_filename(),
863 " when writing solve stats."));
864 }
865 }
866 // Step 3: Extract solution information.
867 // Some outputs are available unconditionally, and some are only ready if at
868 // least presolve succeeded.
870 const int num_scip_solutions = SCIPgetNSols(scip_);
871 const int num_returned_solutions =
872 std::min(num_scip_solutions, std::max(1, params.num_solutions()));
873 SCIP_SOL** all_solutions = SCIPgetSols(scip_);
874 stats->set_best_objective(ScipInfUnclamp(SCIPgetPrimalbound(scip_)));
875 for (int i = 0; i < num_returned_solutions; ++i) {
876 SCIP_SOL* scip_sol = all_solutions[i];
877 const double obj_value = ScipInfUnclamp(SCIPgetSolOrigObj(scip_, scip_sol));
878 GScipSolution solution;
879 for (SCIP_VAR* v : variables_) {
880 solution[v] = SCIPgetSolVal(scip_, scip_sol, v);
881 }
882 result.solutions.push_back(solution);
883 result.objective_values.push_back(obj_value);
884 }
885 RETURN_IF_ERROR(CheckSolutionsInOrder(result, ObjectiveIsMaximize()));
886 // Can only check for primal ray if we made it past presolve.
887 if (stage != SCIP_STAGE_PRESOLVING && SCIPhasPrimalRay(scip_)) {
888 for (SCIP_VAR* v : variables_) {
889 result.primal_ray[v] = SCIPgetPrimalRayVal(scip_, v);
890 }
891 }
892 // TODO(user): refactor this into a new method.
893 stats->set_best_bound(ScipInfUnclamp(SCIPgetDualbound(scip_)));
894 stats->set_node_count(SCIPgetNTotalNodes(scip_));
895 stats->set_first_lp_relaxation_bound(SCIPgetFirstLPDualboundRoot(scip_));
896 stats->set_root_node_bound(SCIPgetDualboundRoot(scip_));
897 if (stage != SCIP_STAGE_PRESOLVING) {
898 stats->set_total_lp_iterations(SCIPgetNLPIterations(scip_));
899 stats->set_primal_simplex_iterations(SCIPgetNPrimalLPIterations(scip_));
900 stats->set_dual_simplex_iterations(SCIPgetNDualLPIterations(scip_));
901 stats->set_deterministic_time(SCIPgetDeterministicTime(scip_));
902 }
903 result.gscip_output.set_status(ConvertStatus(SCIPgetStatus(scip_)));
904
905 // Step 4: clean up.
906 RETURN_IF_ERROR(FreeTransform());
907
908 // Restore the previous message handler. We must do so AFTER we reset the
909 // stage of the problem with FreeTransform(). Doing so before will fail since
910 // changing the message handler is only possible in INIT and PROBLEM stages.
911 if (message_handler != nullptr) {
912 RETURN_IF_SCIP_ERROR(SCIPsetMessagehdlr(scip_, previous_handler.get()));
913
914 // Resetting the unique_ptr will free the associated handler which will
915 // flush the buffer if the last log line was unfinished. If we were not
916 // resetting it, the last new_handler_disabler would disable the handler and
917 // the remainder of the buffer content would be lost.
918 new_handler.reset();
919 }
920 if (params.has_objective_limit()) {
921 RETURN_IF_SCIP_ERROR(SCIPsetObjlimit(scip_, SCIP_INVALID));
922 }
923
924 RETURN_IF_SCIP_ERROR(SCIPresetParams(scip_));
925 // The `silence_output` and `search_logs_filename` parameters are special
926 // since those are not parameters but properties of the SCIP message
927 // handler. Hence we reset them explicitly.
928 SCIPsetMessagehdlrQuiet(scip_, false);
929 SCIPsetMessagehdlrLogfile(scip_, nullptr);
930
931 return result;
932}
933
934absl::StatusOr<bool> GScip::DefaultBoolParamValue(
935 const std::string& parameter_name) {
936 SCIP_Bool default_value;
938 SCIPgetBoolParam(scip_, parameter_name.c_str(), &default_value));
939 return static_cast<bool>(default_value);
940}
941
942absl::StatusOr<int> GScip::DefaultIntParamValue(
943 const std::string& parameter_name) {
944 int default_value;
946 SCIPgetIntParam(scip_, parameter_name.c_str(), &default_value));
947 return default_value;
948}
949
950absl::StatusOr<int64_t> GScip::DefaultLongParamValue(
951 const std::string& parameter_name) {
952 SCIP_Longint result;
954 SCIPgetLongintParam(scip_, parameter_name.c_str(), &result));
955 return static_cast<int64_t>(result);
956}
957
958absl::StatusOr<double> GScip::DefaultRealParamValue(
959 const std::string& parameter_name) {
960 double result;
962 SCIPgetRealParam(scip_, parameter_name.c_str(), &result));
963 return result;
964}
965
966absl::StatusOr<char> GScip::DefaultCharParamValue(
967 const std::string& parameter_name) {
968 char result;
970 SCIPgetCharParam(scip_, parameter_name.c_str(), &result));
971 return result;
972}
973
974absl::StatusOr<std::string> GScip::DefaultStringParamValue(
975 const std::string& parameter_name) {
976 char* result;
978 SCIPgetStringParam(scip_, parameter_name.c_str(), &result));
979 return std::string(result);
980}
981
982double GScip::ScipInfClamp(double d) {
983 const double kScipInf = ScipInf();
984 if (d > kScipInf) return kScipInf;
985 if (d < -kScipInf) return -kScipInf;
986 return d;
987}
988
989double GScip::ScipInfUnclamp(double d) {
990 const double kScipInf = ScipInf();
991 if (d >= kScipInf) return std::numeric_limits<double>::infinity();
992 if (d <= -kScipInf) return -std::numeric_limits<double>::infinity();
993 return d;
994}
995
996#undef RETURN_ERROR_UNLESS
997
998} // namespace operations_research
int64_t max
Definition: alldiff_cst.cc:140
int64_t min
Definition: alldiff_cst.cc:139
#define LOG_IF(severity, condition)
Definition: base/logging.h:479
#define LOG(severity)
Definition: base/logging.h:420
double LinearConstraintUb(SCIP_CONS *constraint)
Definition: gscip.cc:705
absl::Status SetObjectiveOffset(double offset)
Definition: gscip.cc:582
absl::StatusOr< SCIP_VAR * > AddVariable(double lb, double ub, double obj_coef, GScipVarType var_type, const std::string &var_name="", const GScipVariableOptions &options=DefaultGScipVariableOptions())
Definition: gscip.cc:325
absl::Status DeleteVariable(SCIP_VAR *var)
Definition: gscip.cc:624
absl::StatusOr< SCIP_CONS * > AddOrConstraint(const GScipLogicalConstraintData &logical_data, const std::string &name="", const GScipConstraintOptions &options=DefaultGScipConstraintOptions())
Definition: gscip.cc:476
absl::StatusOr< double > DefaultRealParamValue(const std::string &parameter_name)
Definition: gscip.cc:958
absl::Status CanSafeBulkDelete(const absl::flat_hash_set< SCIP_VAR * > &vars)
Definition: gscip.cc:634
absl::StatusOr< SCIP_CONS * > AddAndConstraint(const GScipLogicalConstraintData &logical_data, const std::string &name="", const GScipConstraintOptions &options=DefaultGScipConstraintOptions())
Definition: gscip.cc:451
absl::StatusOr< SCIP_CONS * > AddLinearConstraint(const GScipLinearRange &range, const std::string &name="", const GScipConstraintOptions &options=DefaultGScipConstraintOptions())
Definition: gscip.cc:357
bool IsConstraintLinear(SCIP_CONS *constraint)
Definition: gscip.cc:685
absl::string_view ConstraintType(SCIP_CONS *constraint)
Definition: gscip.cc:681
absl::StatusOr< int64_t > DefaultLongParamValue(const std::string &parameter_name)
Definition: gscip.cc:950
absl::StatusOr< int > DefaultIntParamValue(const std::string &parameter_name)
Definition: gscip.cc:942
absl::Status DeleteConstraint(SCIP_CONS *constraint)
Definition: gscip.cc:725
absl::Status SetLinearConstraintUb(SCIP_CONS *constraint, double ub)
Definition: gscip.cc:719
absl::Status SafeBulkDelete(const absl::flat_hash_set< SCIP_VAR * > &vars)
Definition: gscip.cc:645
static absl::StatusOr< std::unique_ptr< GScip > > Create(const std::string &problem_name)
Definition: gscip.cc:272
double Ub(SCIP_VAR *var)
Definition: gscip.cc:669
double ObjCoef(SCIP_VAR *var)
Definition: gscip.cc:673
absl::Status SetMaximize(bool is_maximize)
Definition: gscip.cc:576
absl::StatusOr< std::string > DefaultStringParamValue(const std::string &parameter_name)
Definition: gscip.cc:974
absl::StatusOr< bool > DefaultBoolParamValue(const std::string &parameter_name)
Definition: gscip.cc:934
absl::StatusOr< SCIP_CONS * > AddIndicatorConstraint(const GScipIndicatorConstraint &indicator_constraint, const std::string &name="", const GScipConstraintOptions &options=DefaultGScipConstraintOptions())
Definition: gscip.cc:417
double Lb(SCIP_VAR *var)
Definition: gscip.cc:665
absl::Status SetLb(SCIP_VAR *var, double lb)
Definition: gscip.cc:600
absl::Span< SCIP_VAR *const > LinearConstraintVariables(SCIP_CONS *constraint)
Definition: gscip.cc:695
double LinearConstraintLb(SCIP_CONS *constraint)
Definition: gscip.cc:701
absl::Status SetLinearConstraintCoef(SCIP_CONS *constraint, SCIP_VAR *var, double value)
Definition: gscip.cc:732
absl::Status SetLinearConstraintLb(SCIP_CONS *constraint, double lb)
Definition: gscip.cc:713
absl::StatusOr< GScipHintResult > SuggestHint(const GScipSolution &partial_solution)
Definition: gscip.cc:741
absl::StatusOr< GScipResult > Solve(const GScipParameters &params=GScipParameters(), const std::string &legacy_params="", GScipMessageHandler message_handler=nullptr)
Definition: gscip.cc:778
GScipVarType VarType(SCIP_VAR *var)
Definition: gscip.cc:675
absl::Status SetVarType(SCIP_VAR *var, GScipVarType var_type)
Definition: gscip.cc:617
absl::Status SetBranchingPriority(SCIP_VAR *var, int priority)
Definition: gscip.cc:595
absl::StatusOr< char > DefaultCharParamValue(const std::string &parameter_name)
Definition: gscip.cc:966
absl::Span< const double > LinearConstraintCoefficients(SCIP_CONS *constraint)
Definition: gscip.cc:689
absl::Status SetUb(SCIP_VAR *var, double ub)
Definition: gscip.cc:606
absl::Status SetObjCoef(SCIP_VAR *var, double obj_coef)
Definition: gscip.cc:612
absl::StatusOr< SCIP_CONS * > AddSOS2Constraint(const GScipSOSData &sos_data, const std::string &name="", const GScipConstraintOptions &options=DefaultGScipConstraintOptions())
Definition: gscip.cc:550
static std::string ScipVersion()
Definition: gscip.cc:290
absl::StatusOr< SCIP_CONS * > AddQuadraticConstraint(const GScipQuadraticRange &range, const std::string &name="", const GScipConstraintOptions &options=DefaultGScipConstraintOptions())
Definition: gscip.cc:383
absl::string_view Name(SCIP_VAR *var)
Definition: gscip.cc:679
absl::StatusOr< SCIP_CONS * > AddSOS1Constraint(const GScipSOSData &sos_data, const std::string &name="", const GScipConstraintOptions &options=DefaultGScipConstraintOptions())
Definition: gscip.cc:523
static constexpr Status TOTAL_NODE_LIMIT
Definition: gscip.pb.h:1244
static constexpr Status BEST_SOL_LIMIT
Definition: gscip.pb.h:1256
static constexpr Status UNBOUNDED
Definition: gscip.pb.h:1264
static constexpr Status INF_OR_UNBD
Definition: gscip.pb.h:1266
static constexpr Status SOL_LIMIT
Definition: gscip.pb.h:1254
static constexpr Status STALL_NODE_LIMIT
Definition: gscip.pb.h:1246
static constexpr Status TERMINATE
Definition: gscip.pb.h:1268
void set_status(::operations_research::GScipOutput_Status value)
Definition: gscip.pb.h:2139
static constexpr Status GAP_LIMIT
Definition: gscip.pb.h:1252
static constexpr Status RESTART_LIMIT
Definition: gscip.pb.h:1258
static constexpr Status USER_INTERRUPT
Definition: gscip.pb.h:1240
static constexpr Status TIME_LIMIT
Definition: gscip.pb.h:1248
static constexpr Status INVALID_SOLVER_PARAMETERS
Definition: gscip.pb.h:1270
static constexpr Status NODE_LIMIT
Definition: gscip.pb.h:1242
static constexpr Status INFEASIBLE
Definition: gscip.pb.h:1262
static constexpr Status MEM_LIMIT
Definition: gscip.pb.h:1250
GScipOutput_Status Status
Definition: gscip.pb.h:1237
void set_status_detail(ArgT0 &&arg0, ArgT... args)
static constexpr Status OPTIMAL
Definition: gscip.pb.h:1260
::operations_research::GScipSolvingStats * mutable_stats()
Definition: gscip.pb.h:2260
static constexpr Status UNKNOWN
Definition: gscip.pb.h:1238
static constexpr Emphasis PHASE_IMPROVE
Definition: gscip.pb.h:495
static constexpr Emphasis FEASIBILITY
Definition: gscip.pb.h:487
static constexpr MetaParamValue FAST
Definition: gscip.pb.h:529
static constexpr Emphasis HARD_LP
Definition: gscip.pb.h:489
static constexpr Emphasis CP_SOLVER
Definition: gscip.pb.h:483
const std::string & scip_model_filename() const
Definition: gscip.pb.h:1833
static constexpr MetaParamValue AGGRESSIVE
Definition: gscip.pb.h:527
static constexpr Emphasis PHASE_FEAS
Definition: gscip.pb.h:493
static constexpr Emphasis PHASE_PROOF
Definition: gscip.pb.h:497
static constexpr MetaParamValue DEFAULT_META_PARAM_VALUE
Definition: gscip.pb.h:525
static constexpr Emphasis COUNTER
Definition: gscip.pb.h:481
static constexpr Emphasis OPTIMALITY
Definition: gscip.pb.h:491
static constexpr Emphasis EASY_CIP
Definition: gscip.pb.h:485
GScipParameters_MetaParamValue MetaParamValue
Definition: gscip.pb.h:524
static constexpr Emphasis DEFAULT_EMPHASIS
Definition: gscip.pb.h:479
const std::string & detailed_solving_stats_filename() const
Definition: gscip.pb.h:1782
static constexpr MetaParamValue OFF
Definition: gscip.pb.h:531
GScipParameters_Emphasis Emphasis
Definition: gscip.pb.h:478
void set_root_node_bound(double value)
Definition: gscip.pb.h:2095
void set_total_lp_iterations(int64_t value)
Definition: gscip.pb.h:2035
void set_primal_simplex_iterations(int64_t value)
Definition: gscip.pb.h:1995
void set_best_objective(double value)
Definition: gscip.pb.h:1955
void set_node_count(int64_t value)
Definition: gscip.pb.h:2055
void set_first_lp_relaxation_bound(double value)
Definition: gscip.pb.h:2075
void set_deterministic_time(double value)
Definition: gscip.pb.h:2115
void set_dual_simplex_iterations(int64_t value)
Definition: gscip.pb.h:2015
const std::string name
int64_t value
IntVar * var
Definition: expr_array.cc:1874
#define RETURN_ERROR_UNLESS(x)
Definition: gscip.cc:57
const int FATAL
Definition: log_severity.h:32
const char * SCIPlpiGetSolverName(void)
gets name and version of LP solver
Definition: lpi_glop.cc:137
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()
Definition: gscip.cc:204
std::function< void(GScipMessageType type, absl::string_view message)> GScipMessageHandler
int GScipMaxNumThreads(const GScipParameters &parameters)
absl::Status LegacyScipSetSolverSpecificParameters(const std::string &parameters, SCIP *scip)
std::string ProtoEnumToString(ProtoEnumType enum_value)
const GScipVariableOptions & DefaultGScipVariableOptions()
Definition: gscip.cc:199
absl::flat_hash_map< SCIP_VAR *, double > GScipSolution
Definition: gscip.h:74
StatusBuilder InternalErrorBuilder()
#define SCIP_TO_STATUS(x)
#define RETURN_IF_SCIP_ERROR(x)
#define ASSIGN_OR_RETURN(lhs, rexpr)
Definition: status_macros.h:48
#define RETURN_IF_ERROR(expr)
Definition: status_macros.h:29
std::vector< SCIP_Var * > variables
Definition: gscip.h:436
std::vector< SCIP_VAR * > variables
Definition: gscip.h:100
std::vector< double > coefficients
Definition: gscip.h:101
std::vector< SCIP_VAR * > operators
Definition: gscip.h:449
std::vector< SCIP_Var * > quadratic_variables1
Definition: gscip.h:396
std::vector< SCIP_Var * > quadratic_variables2
Definition: gscip.h:397
std::vector< SCIP_Var * > linear_variables
Definition: gscip.h:383
std::vector< double > linear_coefficients
Definition: gscip.h:384
std::vector< double > quadratic_coefficients
Definition: gscip.h:398
absl::flat_hash_map< SCIP_VAR *, double > primal_ray
Definition: gscip.h:90
std::vector< double > objective_values
Definition: gscip.h:85
std::vector< GScipSolution > solutions
Definition: gscip.h:83
std::vector< SCIP_VAR * > variables
Definition: gscip.h:417
std::vector< double > weights
Definition: gscip.h:426