OR-Tools  9.1
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
174} // namespace
175
177 static GScipVariableOptions var_options;
178 return var_options;
179}
180
182 static GScipConstraintOptions constraint_options;
183 return constraint_options;
184}
185
186absl::Status GScip::SetParams(const GScipParameters& params,
187 const std::string& legacy_params) {
188 if (params.has_silence_output()) {
189 SCIPsetMessagehdlrQuiet(scip_, params.silence_output());
190 }
191 if (!params.search_logs_filename().empty()) {
192 SCIPsetMessagehdlrLogfile(scip_, params.search_logs_filename().c_str());
193 }
194
195 const SCIP_Bool set_param_quiet =
196 static_cast<SCIP_Bool>(!params.silence_output());
197
198 RETURN_IF_SCIP_ERROR(SCIPsetEmphasis(
199 scip_, ConvertEmphasis(params.emphasis()), set_param_quiet));
200 if (params.has_heuristics()) {
201 RETURN_IF_SCIP_ERROR(SCIPsetHeuristics(
202 scip_, ConvertMetaParamValue(params.heuristics()), set_param_quiet));
203 }
204 if (params.has_presolve()) {
205 RETURN_IF_SCIP_ERROR(SCIPsetPresolving(
206 scip_, ConvertMetaParamValue(params.presolve()), set_param_quiet));
207 }
208 if (params.has_separating()) {
209 RETURN_IF_SCIP_ERROR(SCIPsetSeparating(
210 scip_, ConvertMetaParamValue(params.separating()), set_param_quiet));
211 }
212 for (const auto& bool_param : params.bool_params()) {
214 (SCIPsetBoolParam(scip_, bool_param.first.c_str(), bool_param.second)));
215 }
216 for (const auto& int_param : params.int_params()) {
218 (SCIPsetIntParam(scip_, int_param.first.c_str(), int_param.second)));
219 }
220 for (const auto& long_param : params.long_params()) {
221 RETURN_IF_SCIP_ERROR((SCIPsetLongintParam(scip_, long_param.first.c_str(),
222 long_param.second)));
223 }
224 for (const auto& char_param : params.char_params()) {
225 if (char_param.second.size() != 1) {
226 return absl::InvalidArgumentError(
227 absl::StrCat("Character parameters must be single character strings, "
228 "but parameter: ",
229 char_param.first, " was: ", char_param.second));
230 }
231 RETURN_IF_SCIP_ERROR((SCIPsetCharParam(scip_, char_param.first.c_str(),
232 char_param.second[0])));
233 }
234 for (const auto& string_param : params.string_params()) {
235 RETURN_IF_SCIP_ERROR((SCIPsetStringParam(scip_, string_param.first.c_str(),
236 string_param.second.c_str())));
237 }
238 for (const auto& real_param : params.real_params()) {
240 (SCIPsetRealParam(scip_, real_param.first.c_str(), real_param.second)));
241 }
242 if (!legacy_params.empty()) {
244 LegacyScipSetSolverSpecificParameters(legacy_params, scip_));
245 }
246 return absl::OkStatus();
247}
248
249absl::StatusOr<std::unique_ptr<GScip>> GScip::Create(
250 const std::string& problem_name) {
251 SCIP* scip = nullptr;
252 RETURN_IF_SCIP_ERROR(SCIPcreate(&scip));
253 RETURN_IF_SCIP_ERROR(SCIPincludeDefaultPlugins(scip));
254 RETURN_IF_SCIP_ERROR(SCIPcreateProbBasic(scip, problem_name.c_str()));
255 // NOTE(user): the constructor is private, so we cannot call make_unique.
256 return absl::WrapUnique(new GScip(scip));
257}
258
259GScip::GScip(SCIP* scip) : scip_(scip) {}
260
261double GScip::ScipInf() { return SCIPinfinity(scip_); }
262
263absl::Status GScip::FreeTransform() {
264 return SCIP_TO_STATUS(SCIPfreeTransform(scip_));
265}
266
267std::string GScip::ScipVersion() {
268 return absl::StrFormat("SCIP %d.%d.%d [LP solver: %s]", SCIPmajorVersion(),
269 SCIPminorVersion(), SCIPtechVersion(),
271}
272
274 if (scip_ == nullptr) {
275 return true;
276 }
277 return SCIPinterruptSolve(scip_) == SCIP_OKAY;
278}
279
280absl::Status GScip::CleanUp() {
281 if (scip_ != nullptr) {
282 for (SCIP_VAR* variable : variables_) {
283 if (variable != nullptr) {
284 RETURN_IF_SCIP_ERROR(SCIPreleaseVar(scip_, &variable));
285 }
286 }
287 for (SCIP_CONS* constraint : constraints_) {
288 if (constraint != nullptr) {
289 RETURN_IF_SCIP_ERROR(SCIPreleaseCons(scip_, &constraint));
290 }
291 }
292 RETURN_IF_SCIP_ERROR(SCIPfree(&scip_));
293 }
294 return absl::OkStatus();
295}
296
298 const absl::Status clean_up_status = CleanUp();
299 LOG_IF(DFATAL, !clean_up_status.ok()) << clean_up_status;
300}
301
302absl::StatusOr<SCIP_VAR*> GScip::AddVariable(
303 double lb, double ub, double obj_coef, GScipVarType var_type,
304 const std::string& var_name, const GScipVariableOptions& options) {
305 SCIP_VAR* var = nullptr;
306 lb = ScipInfClamp(lb);
307 ub = ScipInfClamp(ub);
308 RETURN_IF_SCIP_ERROR(SCIPcreateVarBasic(scip_, /*var=*/&var,
309 /*name=*/var_name.c_str(),
310 /*lb=*/lb, /*ub=*/ub,
311 /*obj=*/obj_coef,
312 ConvertVarType(var_type)));
313 RETURN_IF_SCIP_ERROR(SCIPvarSetInitial(var, options.initial));
314 RETURN_IF_SCIP_ERROR(SCIPvarSetRemovable(var, options.removable));
315 RETURN_IF_SCIP_ERROR(SCIPaddVar(scip_, var));
316 if (options.keep_alive) {
317 variables_.insert(var);
318 } else {
319 RETURN_IF_SCIP_ERROR(SCIPreleaseVar(scip_, &var));
320 }
321 return var;
322}
323
324absl::Status GScip::MaybeKeepConstraintAlive(
325 SCIP_CONS* constraint, const GScipConstraintOptions& options) {
326 if (options.keep_alive) {
327 constraints_.insert(constraint);
328 } else {
329 RETURN_IF_SCIP_ERROR(SCIPreleaseCons(scip_, &constraint));
330 }
331 return absl::OkStatus();
332}
333
334absl::StatusOr<SCIP_CONS*> GScip::AddLinearConstraint(
335 const GScipLinearRange& range, const std::string& name,
336 const GScipConstraintOptions& options) {
337 SCIP_CONS* constraint = nullptr;
338 RETURN_ERROR_UNLESS(range.variables.size() == range.coefficients.size())
339 << "Error adding constraint: " << name << ".";
340 RETURN_IF_SCIP_ERROR(SCIPcreateConsLinear(
341 scip_, &constraint, name.c_str(), range.variables.size(),
342 const_cast<SCIP_VAR**>(range.variables.data()),
343 const_cast<double*>(range.coefficients.data()),
344 ScipInfClamp(range.lower_bound), ScipInfClamp(range.upper_bound),
345 /*initial=*/options.initial,
346 /*separate=*/options.separate,
347 /*enforce=*/options.enforce,
348 /*check=*/options.check,
349 /*propagate=*/options.propagate,
350 /*local=*/options.local,
351 /*modifiable=*/options.modifiable,
352 /*dynamic=*/options.dynamic,
353 /*removable=*/options.removable,
354 /*stickingatnode=*/options.sticking_at_node));
355 RETURN_IF_SCIP_ERROR(SCIPaddCons(scip_, constraint));
356 RETURN_IF_ERROR(MaybeKeepConstraintAlive(constraint, options));
357 return constraint;
358}
359
360absl::StatusOr<SCIP_CONS*> GScip::AddQuadraticConstraint(
361 const GScipQuadraticRange& range, const std::string& name,
362 const GScipConstraintOptions& options) {
363 SCIP_CONS* constraint = nullptr;
364 const int num_lin_vars = range.linear_variables.size();
365 RETURN_ERROR_UNLESS(num_lin_vars == range.linear_coefficients.size())
366 << "Error adding quadratic constraint: " << name << " in linear term.";
367 const int num_quad_vars = range.quadratic_variables1.size();
368 RETURN_ERROR_UNLESS(num_quad_vars == range.quadratic_variables2.size())
369 << "Error adding quadratic constraint: " << name << " in quadratic term.";
370 RETURN_ERROR_UNLESS(num_quad_vars == range.quadratic_coefficients.size())
371 << "Error adding quadratic constraint: " << name << " in quadratic term.";
372 RETURN_IF_SCIP_ERROR(SCIPcreateConsQuadratic(
373 scip_, &constraint, name.c_str(), num_lin_vars,
374 const_cast<SCIP_Var**>(range.linear_variables.data()),
375 const_cast<double*>(range.linear_coefficients.data()), num_quad_vars,
376 const_cast<SCIP_Var**>(range.quadratic_variables1.data()),
377 const_cast<SCIP_Var**>(range.quadratic_variables2.data()),
378 const_cast<double*>(range.quadratic_coefficients.data()),
379 ScipInfClamp(range.lower_bound), ScipInfClamp(range.upper_bound),
380 /*initial=*/options.initial,
381 /*separate=*/options.separate,
382 /*enforce=*/options.enforce,
383 /*check=*/options.check,
384 /*propagate=*/options.propagate,
385 /*local=*/options.local,
386 /*modifiable=*/options.modifiable,
387 /*dynamic=*/options.dynamic,
388 /*removable=*/options.removable));
389 RETURN_IF_SCIP_ERROR(SCIPaddCons(scip_, constraint));
390 RETURN_IF_ERROR(MaybeKeepConstraintAlive(constraint, options));
391 return constraint;
392}
393
394absl::StatusOr<SCIP_CONS*> GScip::AddIndicatorConstraint(
395 const GScipIndicatorConstraint& indicator_constraint,
396 const std::string& name, const GScipConstraintOptions& options) {
397 SCIP_VAR* indicator = indicator_constraint.indicator_variable;
398 RETURN_ERROR_UNLESS(indicator != nullptr)
399 << "Error adding indicator constraint: " << name << ".";
400 if (indicator_constraint.negate_indicator) {
401 RETURN_IF_SCIP_ERROR(SCIPgetNegatedVar(scip_, indicator, &indicator));
402 }
403
404 SCIP_CONS* constraint = nullptr;
405 RETURN_ERROR_UNLESS(indicator_constraint.variables.size() ==
406 indicator_constraint.coefficients.size())
407 << "Error adding indicator constraint: " << name << ".";
408 RETURN_IF_SCIP_ERROR(SCIPcreateConsIndicator(
409 scip_, &constraint, name.c_str(), indicator,
410 indicator_constraint.variables.size(),
411 const_cast<SCIP_Var**>(indicator_constraint.variables.data()),
412 const_cast<double*>(indicator_constraint.coefficients.data()),
413 ScipInfClamp(indicator_constraint.upper_bound),
414 /*initial=*/options.initial,
415 /*separate=*/options.separate,
416 /*enforce=*/options.enforce,
417 /*check=*/options.check,
418 /*propagate=*/options.propagate,
419 /*local=*/options.local,
420 /*dynamic=*/options.dynamic,
421 /*removable=*/options.removable,
422 /*stickingatnode=*/options.sticking_at_node));
423 RETURN_IF_SCIP_ERROR(SCIPaddCons(scip_, constraint));
424 RETURN_IF_ERROR(MaybeKeepConstraintAlive(constraint, options));
425 return constraint;
426}
427
428absl::StatusOr<SCIP_CONS*> GScip::AddAndConstraint(
429 const GScipLogicalConstraintData& logical_data, const std::string& name,
430 const GScipConstraintOptions& options) {
431 RETURN_ERROR_UNLESS(logical_data.resultant != nullptr)
432 << "Error adding and constraint: " << name << ".";
433 SCIP_CONS* constraint = nullptr;
435 SCIPcreateConsAnd(scip_, &constraint, name.c_str(),
436 logical_data.resultant, logical_data.operators.size(),
437 const_cast<SCIP_VAR**>(logical_data.operators.data()),
438 /*initial=*/options.initial,
439 /*separate=*/options.separate,
440 /*enforce=*/options.enforce,
441 /*check=*/options.check,
442 /*propagate=*/options.propagate,
443 /*local=*/options.local,
444 /*modifiable=*/options.modifiable,
445 /*dynamic=*/options.dynamic,
446 /*removable=*/options.removable,
447 /*stickingatnode=*/options.sticking_at_node));
448 RETURN_IF_SCIP_ERROR(SCIPaddCons(scip_, constraint));
449 RETURN_IF_ERROR(MaybeKeepConstraintAlive(constraint, options));
450 return constraint;
451}
452
453absl::StatusOr<SCIP_CONS*> GScip::AddOrConstraint(
454 const GScipLogicalConstraintData& logical_data, const std::string& name,
455 const GScipConstraintOptions& options) {
456 RETURN_ERROR_UNLESS(logical_data.resultant != nullptr)
457 << "Error adding or constraint: " << name << ".";
458 SCIP_CONS* constraint = nullptr;
460 SCIPcreateConsOr(scip_, &constraint, name.c_str(), logical_data.resultant,
461 logical_data.operators.size(),
462 const_cast<SCIP_Var**>(logical_data.operators.data()),
463 /*initial=*/options.initial,
464 /*separate=*/options.separate,
465 /*enforce=*/options.enforce,
466 /*check=*/options.check,
467 /*propagate=*/options.propagate,
468 /*local=*/options.local,
469 /*modifiable=*/options.modifiable,
470 /*dynamic=*/options.dynamic,
471 /*removable=*/options.removable,
472 /*stickingatnode=*/options.sticking_at_node));
473 RETURN_IF_SCIP_ERROR(SCIPaddCons(scip_, constraint));
474 RETURN_IF_ERROR(MaybeKeepConstraintAlive(constraint, options));
475 return constraint;
476}
477
478namespace {
479
480absl::Status ValidateSOSData(const GScipSOSData& sos_data,
481 const std::string& name) {
482 RETURN_ERROR_UNLESS(!sos_data.variables.empty())
483 << "Error adding SOS constraint: " << name << ".";
484 if (!sos_data.weights.empty()) {
485 RETURN_ERROR_UNLESS(sos_data.variables.size() == sos_data.weights.size())
486 << " Error adding SOS constraint: " << name << ".";
487 }
488 absl::flat_hash_set<double> distinct_weights;
489 for (const double w : sos_data.weights) {
490 RETURN_ERROR_UNLESS(!distinct_weights.contains(w))
491 << "Error adding SOS constraint: " << name
492 << ", weights must be distinct, but found value " << w << " twice.";
493 distinct_weights.insert(w);
494 }
495 return absl::OkStatus();
496}
497
498} // namespace
499
500absl::StatusOr<SCIP_CONS*> GScip::AddSOS1Constraint(
501 const GScipSOSData& sos_data, const std::string& name,
502 const GScipConstraintOptions& options) {
503 RETURN_IF_ERROR(ValidateSOSData(sos_data, name));
504 SCIP_CONS* constraint = nullptr;
505 double* weights = nullptr;
506 if (!sos_data.weights.empty()) {
507 weights = const_cast<double*>(sos_data.weights.data());
508 }
509
510 RETURN_IF_SCIP_ERROR(SCIPcreateConsSOS1(
511 scip_, &constraint, name.c_str(), sos_data.variables.size(),
512 const_cast<SCIP_Var**>(sos_data.variables.data()), weights,
513 /*initial=*/options.initial,
514 /*separate=*/options.separate,
515 /*enforce=*/options.enforce,
516 /*check=*/options.check,
517 /*propagate=*/options.propagate,
518 /*local=*/options.local,
519 /*dynamic=*/options.dynamic,
520 /*removable=*/options.removable,
521 /*stickingatnode=*/options.sticking_at_node));
522 RETURN_IF_SCIP_ERROR(SCIPaddCons(scip_, constraint));
523 RETURN_IF_ERROR(MaybeKeepConstraintAlive(constraint, options));
524 return constraint;
525}
526
527absl::StatusOr<SCIP_CONS*> GScip::AddSOS2Constraint(
528 const GScipSOSData& sos_data, const std::string& name,
529 const GScipConstraintOptions& options) {
530 RETURN_IF_ERROR(ValidateSOSData(sos_data, name));
531 SCIP_CONS* constraint = nullptr;
532 double* weights = nullptr;
533 if (!sos_data.weights.empty()) {
534 weights = const_cast<double*>(sos_data.weights.data());
535 }
536 RETURN_IF_SCIP_ERROR(SCIPcreateConsSOS2(
537 scip_, &constraint, name.c_str(), sos_data.variables.size(),
538 const_cast<SCIP_Var**>(sos_data.variables.data()), weights,
539 /*initial=*/options.initial,
540 /*separate=*/options.separate,
541 /*enforce=*/options.enforce,
542 /*check=*/options.check,
543 /*propagate=*/options.propagate,
544 /*local=*/options.local,
545 /*dynamic=*/options.dynamic,
546 /*removable=*/options.removable,
547 /*stickingatnode=*/options.sticking_at_node));
548 RETURN_IF_SCIP_ERROR(SCIPaddCons(scip_, constraint));
549 RETURN_IF_ERROR(MaybeKeepConstraintAlive(constraint, options));
550 return constraint;
551}
552
553absl::Status GScip::SetMaximize(bool is_maximize) {
554 RETURN_IF_SCIP_ERROR(SCIPsetObjsense(
555 scip_, is_maximize ? SCIP_OBJSENSE_MAXIMIZE : SCIP_OBJSENSE_MINIMIZE));
556 return absl::OkStatus();
557}
558
559absl::Status GScip::SetObjectiveOffset(double offset) {
560 double old_offset = SCIPgetOrigObjoffset(scip_);
561 double delta_offset = offset - old_offset;
562 RETURN_IF_SCIP_ERROR(SCIPaddOrigObjoffset(scip_, delta_offset));
563 return absl::OkStatus();
564}
565
567 return SCIPgetObjsense(scip_) == SCIP_OBJSENSE_MAXIMIZE;
568}
569
570double GScip::ObjectiveOffset() { return SCIPgetOrigObjoffset(scip_); }
571
572absl::Status GScip::SetBranchingPriority(SCIP_VAR* var, int priority) {
573 RETURN_IF_SCIP_ERROR(SCIPchgVarBranchPriority(scip_, var, priority));
574 return absl::OkStatus();
575}
576
577absl::Status GScip::SetLb(SCIP_VAR* var, double lb) {
578 lb = ScipInfClamp(lb);
579 RETURN_IF_SCIP_ERROR(SCIPchgVarLb(scip_, var, lb));
580 return absl::OkStatus();
581}
582
583absl::Status GScip::SetUb(SCIP_VAR* var, double ub) {
584 ub = ScipInfClamp(ub);
585 RETURN_IF_SCIP_ERROR(SCIPchgVarUb(scip_, var, ub));
586 return absl::OkStatus();
587}
588
589absl::Status GScip::SetObjCoef(SCIP_VAR* var, double obj_coef) {
590 RETURN_IF_SCIP_ERROR(SCIPchgVarObj(scip_, var, obj_coef));
591 return absl::OkStatus();
592}
593
594absl::Status GScip::SetVarType(SCIP_VAR* var, GScipVarType var_type) {
595 SCIP_Bool infeasible;
597 SCIPchgVarType(scip_, var, ConvertVarType(var_type), &infeasible));
598 return absl::OkStatus();
599}
600
601absl::Status GScip::DeleteVariable(SCIP_VAR* var) {
602 SCIP_Bool did_delete;
603 RETURN_IF_SCIP_ERROR(SCIPdelVar(scip_, var, &did_delete));
604 RETURN_ERROR_UNLESS(static_cast<bool>(did_delete))
605 << "Failed to delete variable named: " << Name(var);
606 variables_.erase(var);
607 RETURN_IF_SCIP_ERROR(SCIPreleaseVar(scip_, &var));
608 return absl::OkStatus();
609}
610
612 const absl::flat_hash_set<SCIP_VAR*>& vars) {
613 for (SCIP_CONS* constraint : constraints_) {
614 if (!IsConstraintLinear(constraint)) {
615 return absl::InvalidArgumentError(absl::StrCat(
616 "Model contains nonlinear constraint: ", Name(constraint)));
617 }
618 }
619 return absl::OkStatus();
620}
621
622absl::Status GScip::SafeBulkDelete(const absl::flat_hash_set<SCIP_VAR*>& vars) {
624 // Now, we can assume that all constraints are linear.
625 for (SCIP_CONS* constraint : constraints_) {
626 const absl::Span<SCIP_VAR* const> nonzeros =
627 LinearConstraintVariables(constraint);
628 const std::vector<SCIP_VAR*> nonzeros_copy(nonzeros.begin(),
629 nonzeros.end());
630 for (SCIP_VAR* var : nonzeros_copy) {
631 if (vars.contains(var)) {
633 }
634 }
635 }
636 for (SCIP_VAR* const var : vars) {
638 }
639 return absl::OkStatus();
640}
641
642double GScip::Lb(SCIP_VAR* var) {
643 return ScipInfUnclamp(SCIPvarGetLbOriginal(var));
644}
645
646double GScip::Ub(SCIP_VAR* var) {
647 return ScipInfUnclamp(SCIPvarGetUbOriginal(var));
648}
649
650double GScip::ObjCoef(SCIP_VAR* var) { return SCIPvarGetObj(var); }
651
653 return ConvertVarType(SCIPvarGetType(var));
654}
655
656absl::string_view GScip::Name(SCIP_VAR* var) { return SCIPvarGetName(var); }
657
658absl::string_view GScip::ConstraintType(SCIP_CONS* constraint) {
659 return absl::string_view(SCIPconshdlrGetName(SCIPconsGetHdlr(constraint)));
660}
661
662bool GScip::IsConstraintLinear(SCIP_CONS* constraint) {
663 return ConstraintType(constraint) == kLinearConstraintHandlerName;
664}
665
666absl::Span<const double> GScip::LinearConstraintCoefficients(
667 SCIP_CONS* constraint) {
668 int num_vars = SCIPgetNVarsLinear(scip_, constraint);
669 return absl::MakeConstSpan(SCIPgetValsLinear(scip_, constraint), num_vars);
670}
671
672absl::Span<SCIP_VAR* const> GScip::LinearConstraintVariables(
673 SCIP_CONS* constraint) {
674 int num_vars = SCIPgetNVarsLinear(scip_, constraint);
675 return absl::MakeConstSpan(SCIPgetVarsLinear(scip_, constraint), num_vars);
676}
677
678double GScip::LinearConstraintLb(SCIP_CONS* constraint) {
679 return ScipInfUnclamp(SCIPgetLhsLinear(scip_, constraint));
680}
681
682double GScip::LinearConstraintUb(SCIP_CONS* constraint) {
683 return ScipInfUnclamp(SCIPgetRhsLinear(scip_, constraint));
684}
685
686absl::string_view GScip::Name(SCIP_CONS* constraint) {
687 return SCIPconsGetName(constraint);
688}
689
690absl::Status GScip::SetLinearConstraintLb(SCIP_CONS* constraint, double lb) {
691 lb = ScipInfClamp(lb);
692 RETURN_IF_SCIP_ERROR(SCIPchgLhsLinear(scip_, constraint, lb));
693 return absl::OkStatus();
694}
695
696absl::Status GScip::SetLinearConstraintUb(SCIP_CONS* constraint, double ub) {
697 ub = ScipInfClamp(ub);
698 RETURN_IF_SCIP_ERROR(SCIPchgRhsLinear(scip_, constraint, ub));
699 return absl::OkStatus();
700}
701
702absl::Status GScip::DeleteConstraint(SCIP_CONS* constraint) {
703 RETURN_IF_SCIP_ERROR(SCIPdelCons(scip_, constraint));
704 constraints_.erase(constraint);
705 RETURN_IF_SCIP_ERROR(SCIPreleaseCons(scip_, &constraint));
706 return absl::OkStatus();
707}
708
709absl::Status GScip::SetLinearConstraintCoef(SCIP_CONS* constraint,
710 SCIP_VAR* var, double value) {
711 // TODO(user): this operation is slow (linear in the nnz in the constraint).
712 // It would be better to just use a bulk operation, but there doesn't appear
713 // to be any?
714 RETURN_IF_SCIP_ERROR(SCIPchgCoefLinear(scip_, constraint, var, value));
715 return absl::OkStatus();
716}
717
718absl::StatusOr<GScipHintResult> GScip::SuggestHint(
719 const GScipSolution& partial_solution) {
720 SCIP_SOL* solution;
721 const int scip_num_vars = SCIPgetNOrigVars(scip_);
722 const bool is_solution_partial = partial_solution.size() < scip_num_vars;
723 if (is_solution_partial) {
724 RETURN_IF_SCIP_ERROR(SCIPcreatePartialSol(scip_, &solution, nullptr));
725 } else {
726 // This is actually a full solution
727 RETURN_ERROR_UNLESS(partial_solution.size() == scip_num_vars)
728 << "Error suggesting hint.";
729 RETURN_IF_SCIP_ERROR(SCIPcreateSol(scip_, &solution, nullptr));
730 }
731 for (const auto& var_value_pair : partial_solution) {
732 RETURN_IF_SCIP_ERROR(SCIPsetSolVal(scip_, solution, var_value_pair.first,
733 var_value_pair.second));
734 }
735 if (!is_solution_partial) {
736 SCIP_Bool is_feasible;
737 RETURN_IF_SCIP_ERROR(SCIPcheckSol(
738 scip_, solution, /*printreason=*/false, /*completely=*/true,
739 /*checkbounds=*/true, /*checkintegrality=*/true, /*checklprows=*/true,
740 &is_feasible));
741 if (!static_cast<bool>(is_feasible)) {
742 RETURN_IF_SCIP_ERROR(SCIPfreeSol(scip_, &solution));
744 }
745 }
746 SCIP_Bool is_stored;
747 RETURN_IF_SCIP_ERROR(SCIPaddSolFree(scip_, &solution, &is_stored));
748 if (static_cast<bool>(is_stored)) {
750 } else {
752 }
753}
754
755absl::StatusOr<GScipResult> GScip::Solve(
756 const GScipParameters& params, const std::string& legacy_params,
757 const GScipMessageHandler message_handler) {
758 // A four step process:
759 // 1. Apply parameters.
760 // 2. Solve the problem.
761 // 3. Extract solution and solve statistics.
762 // 4. Prepare the solver for further modification/solves (reset parameters,
763 // free the solutions found).
764 GScipResult result;
765
766 // Step 1: apply parameters.
767 const absl::Status param_status = SetParams(params, legacy_params);
768 if (!param_status.ok()) {
770 // Conversion to std::string for open source build.
772 std::string(param_status.message())); // NOLINT
773 return result;
774 }
775 if (params.print_scip_model()) {
776 RETURN_IF_SCIP_ERROR(SCIPwriteOrigProblem(scip_, nullptr, "cip", FALSE));
777 }
778 if (!params.scip_model_filename().empty()) {
779 RETURN_IF_SCIP_ERROR(SCIPwriteOrigProblem(
780 scip_, params.scip_model_filename().c_str(), "cip", FALSE));
781 }
782
783 // Install the message handler if necessary. We do this after setting the
784 // parameters so that parameters that applies to the default message handler
785 // like `quiet` are indeed applied to it and not to our temporary
786 // handler.
789 MessageHandlerPtr previous_handler;
790 MessageHandlerPtr new_handler;
791 if (message_handler != nullptr) {
792 previous_handler = CaptureMessageHandlerPtr(SCIPgetMessagehdlr(scip_));
793 ASSIGN_OR_RETURN(new_handler,
794 internal::MakeSCIPMessageHandler(message_handler));
795 SCIPsetMessagehdlr(scip_, new_handler.get());
796 }
797 // Make sure we prevent any call of message_handler after this function has
798 // returned, until the new_handler is reset (see below).
799 const internal::ScopedSCIPMessageHandlerDisabler new_handler_disabler(
800 new_handler);
801
802 // Step 2: Solve.
803 // NOTE(user): after solve, SCIP will either be in stage PRESOLVING,
804 // SOLVING, OR SOLVED.
805 if (GScipMaxNumThreads(params) > 1) {
806 RETURN_IF_SCIP_ERROR(SCIPsolveConcurrent(scip_));
807 } else {
808 RETURN_IF_SCIP_ERROR(SCIPsolve(scip_));
809 }
810 const SCIP_STAGE stage = SCIPgetStage(scip_);
811 if (stage != SCIP_STAGE_PRESOLVING && stage != SCIP_STAGE_SOLVING &&
812 stage != SCIP_STAGE_SOLVED) {
815 absl::StrCat("Unpexpected SCIP final stage= ", stage,
816 " was expected to be either SCIP_STAGE_PRESOLVING, "
817 "SCIP_STAGE_SOLVING, or SCIP_STAGE_SOLVED"));
818 return result;
819 }
820 if (params.print_detailed_solving_stats()) {
821 RETURN_IF_SCIP_ERROR(SCIPprintStatistics(scip_, nullptr));
822 }
823 if (!params.detailed_solving_stats_filename().empty()) {
824 FILE* file = fopen(params.detailed_solving_stats_filename().c_str(), "w");
825 if (file == nullptr) {
826 return absl::InvalidArgumentError(absl::StrCat(
827 "Could not open file: ", params.detailed_solving_stats_filename(),
828 " to write SCIP solve stats."));
829 }
830 RETURN_IF_SCIP_ERROR(SCIPprintStatistics(scip_, file));
831 int close_result = fclose(file);
832 if (close_result != 0) {
833 return absl::InvalidArgumentError(absl::StrCat(
834 "Error: ", close_result,
835 " closing file: ", params.detailed_solving_stats_filename(),
836 " when writing solve stats."));
837 }
838 }
839 // Step 3: Extract solution information.
840 // Some outputs are available unconditionally, and some are only ready if at
841 // least presolve succeeded.
843 const int num_scip_solutions = SCIPgetNSols(scip_);
844 const int num_returned_solutions =
845 std::min(num_scip_solutions, std::max(1, params.num_solutions()));
846 SCIP_SOL** all_solutions = SCIPgetSols(scip_);
847 stats->set_best_objective(ScipInfUnclamp(SCIPgetPrimalbound(scip_)));
848 for (int i = 0; i < num_returned_solutions; ++i) {
849 SCIP_SOL* scip_sol = all_solutions[i];
850 const double obj_value = ScipInfUnclamp(SCIPgetSolOrigObj(scip_, scip_sol));
851 GScipSolution solution;
852 for (SCIP_VAR* v : variables_) {
853 solution[v] = SCIPgetSolVal(scip_, scip_sol, v);
854 }
855 result.solutions.push_back(solution);
856 result.objective_values.push_back(obj_value);
857 }
858 // Can only check for primal ray if we made it past presolve.
859 if (stage != SCIP_STAGE_PRESOLVING && SCIPhasPrimalRay(scip_)) {
860 for (SCIP_VAR* v : variables_) {
861 result.primal_ray[v] = SCIPgetPrimalRayVal(scip_, v);
862 }
863 }
864 // TODO(user): refactor this into a new method.
865 stats->set_best_bound(ScipInfUnclamp(SCIPgetDualbound(scip_)));
866 stats->set_node_count(SCIPgetNTotalNodes(scip_));
867 stats->set_first_lp_relaxation_bound(SCIPgetFirstLPDualboundRoot(scip_));
868 stats->set_root_node_bound(SCIPgetDualboundRoot(scip_));
869 if (stage != SCIP_STAGE_PRESOLVING) {
870 stats->set_total_lp_iterations(SCIPgetNLPIterations(scip_));
871 stats->set_primal_simplex_iterations(SCIPgetNPrimalLPIterations(scip_));
872 stats->set_dual_simplex_iterations(SCIPgetNDualLPIterations(scip_));
873 stats->set_deterministic_time(SCIPgetDeterministicTime(scip_));
874 }
875 result.gscip_output.set_status(ConvertStatus(SCIPgetStatus(scip_)));
876
877 // Step 4: clean up.
878 RETURN_IF_ERROR(FreeTransform());
879
880 // Restore the previous message handler. We must do so AFTER we reset the
881 // stage of the problem with FreeTransform(). Doing so before will fail since
882 // changing the message handler is only possible in INIT and PROBLEM stages.
883 if (message_handler != nullptr) {
884 RETURN_IF_SCIP_ERROR(SCIPsetMessagehdlr(scip_, previous_handler.get()));
885
886 // Resetting the unique_ptr will free the associated handler which will
887 // flush the buffer if the last log line was unfinished. If we were not
888 // resetting it, the last new_handler_disabler would disable the handler and
889 // the remainder of the buffer content would be lost.
890 new_handler.reset();
891 }
892
893 RETURN_IF_SCIP_ERROR(SCIPresetParams(scip_));
894 // The `silence_output` and `search_logs_filename` parameters are special
895 // since those are not parameters but properties of the SCIP message
896 // handler. Hence we reset them explicitly.
897 SCIPsetMessagehdlrQuiet(scip_, false);
898 SCIPsetMessagehdlrLogfile(scip_, nullptr);
899
900 return result;
901}
902
903absl::StatusOr<bool> GScip::DefaultBoolParamValue(
904 const std::string& parameter_name) {
905 SCIP_Bool default_value;
907 SCIPgetBoolParam(scip_, parameter_name.c_str(), &default_value));
908 return static_cast<bool>(default_value);
909}
910
911absl::StatusOr<int> GScip::DefaultIntParamValue(
912 const std::string& parameter_name) {
913 int default_value;
915 SCIPgetIntParam(scip_, parameter_name.c_str(), &default_value));
916 return default_value;
917}
918
919absl::StatusOr<int64_t> GScip::DefaultLongParamValue(
920 const std::string& parameter_name) {
921 SCIP_Longint result;
923 SCIPgetLongintParam(scip_, parameter_name.c_str(), &result));
924 return static_cast<int64_t>(result);
925}
926
927absl::StatusOr<double> GScip::DefaultRealParamValue(
928 const std::string& parameter_name) {
929 double result;
931 SCIPgetRealParam(scip_, parameter_name.c_str(), &result));
932 return result;
933}
934
935absl::StatusOr<char> GScip::DefaultCharParamValue(
936 const std::string& parameter_name) {
937 char result;
939 SCIPgetCharParam(scip_, parameter_name.c_str(), &result));
940 return result;
941}
942
943absl::StatusOr<std::string> GScip::DefaultStringParamValue(
944 const std::string& parameter_name) {
945 char* result;
947 SCIPgetStringParam(scip_, parameter_name.c_str(), &result));
948 return std::string(result);
949}
950
951double GScip::ScipInfClamp(double d) {
952 const double kScipInf = ScipInf();
953 if (d > kScipInf) return kScipInf;
954 if (d < -kScipInf) return -kScipInf;
955 return d;
956}
957
958double GScip::ScipInfUnclamp(double d) {
959 const double kScipInf = ScipInf();
960 if (d >= kScipInf) return std::numeric_limits<double>::infinity();
961 if (d <= -kScipInf) return -std::numeric_limits<double>::infinity();
962 return d;
963}
964
965#undef RETURN_ERROR_UNLESS
966
967} // 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:475
#define LOG(severity)
Definition: base/logging.h:416
double LinearConstraintUb(SCIP_CONS *constraint)
Definition: gscip.cc:682
absl::Status SetObjectiveOffset(double offset)
Definition: gscip.cc:559
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:302
absl::Status DeleteVariable(SCIP_VAR *var)
Definition: gscip.cc:601
absl::StatusOr< SCIP_CONS * > AddOrConstraint(const GScipLogicalConstraintData &logical_data, const std::string &name="", const GScipConstraintOptions &options=DefaultGScipConstraintOptions())
Definition: gscip.cc:453
absl::StatusOr< double > DefaultRealParamValue(const std::string &parameter_name)
Definition: gscip.cc:927
absl::Status CanSafeBulkDelete(const absl::flat_hash_set< SCIP_VAR * > &vars)
Definition: gscip.cc:611
absl::StatusOr< SCIP_CONS * > AddAndConstraint(const GScipLogicalConstraintData &logical_data, const std::string &name="", const GScipConstraintOptions &options=DefaultGScipConstraintOptions())
Definition: gscip.cc:428
absl::StatusOr< SCIP_CONS * > AddLinearConstraint(const GScipLinearRange &range, const std::string &name="", const GScipConstraintOptions &options=DefaultGScipConstraintOptions())
Definition: gscip.cc:334
bool IsConstraintLinear(SCIP_CONS *constraint)
Definition: gscip.cc:662
absl::string_view ConstraintType(SCIP_CONS *constraint)
Definition: gscip.cc:658
absl::StatusOr< int64_t > DefaultLongParamValue(const std::string &parameter_name)
Definition: gscip.cc:919
absl::StatusOr< int > DefaultIntParamValue(const std::string &parameter_name)
Definition: gscip.cc:911
absl::Status DeleteConstraint(SCIP_CONS *constraint)
Definition: gscip.cc:702
absl::Status SetLinearConstraintUb(SCIP_CONS *constraint, double ub)
Definition: gscip.cc:696
absl::Status SafeBulkDelete(const absl::flat_hash_set< SCIP_VAR * > &vars)
Definition: gscip.cc:622
static absl::StatusOr< std::unique_ptr< GScip > > Create(const std::string &problem_name)
Definition: gscip.cc:249
double Ub(SCIP_VAR *var)
Definition: gscip.cc:646
double ObjCoef(SCIP_VAR *var)
Definition: gscip.cc:650
absl::Status SetMaximize(bool is_maximize)
Definition: gscip.cc:553
absl::StatusOr< std::string > DefaultStringParamValue(const std::string &parameter_name)
Definition: gscip.cc:943
absl::StatusOr< bool > DefaultBoolParamValue(const std::string &parameter_name)
Definition: gscip.cc:903
absl::StatusOr< SCIP_CONS * > AddIndicatorConstraint(const GScipIndicatorConstraint &indicator_constraint, const std::string &name="", const GScipConstraintOptions &options=DefaultGScipConstraintOptions())
Definition: gscip.cc:394
double Lb(SCIP_VAR *var)
Definition: gscip.cc:642
absl::Status SetLb(SCIP_VAR *var, double lb)
Definition: gscip.cc:577
absl::Span< SCIP_VAR *const > LinearConstraintVariables(SCIP_CONS *constraint)
Definition: gscip.cc:672
double LinearConstraintLb(SCIP_CONS *constraint)
Definition: gscip.cc:678
absl::Status SetLinearConstraintCoef(SCIP_CONS *constraint, SCIP_VAR *var, double value)
Definition: gscip.cc:709
absl::Status SetLinearConstraintLb(SCIP_CONS *constraint, double lb)
Definition: gscip.cc:690
absl::StatusOr< GScipHintResult > SuggestHint(const GScipSolution &partial_solution)
Definition: gscip.cc:718
absl::StatusOr< GScipResult > Solve(const GScipParameters &params=GScipParameters(), const std::string &legacy_params="", GScipMessageHandler message_handler=nullptr)
Definition: gscip.cc:755
GScipVarType VarType(SCIP_VAR *var)
Definition: gscip.cc:652
absl::Status SetVarType(SCIP_VAR *var, GScipVarType var_type)
Definition: gscip.cc:594
absl::Status SetBranchingPriority(SCIP_VAR *var, int priority)
Definition: gscip.cc:572
absl::StatusOr< char > DefaultCharParamValue(const std::string &parameter_name)
Definition: gscip.cc:935
absl::Span< const double > LinearConstraintCoefficients(SCIP_CONS *constraint)
Definition: gscip.cc:666
absl::Status SetUb(SCIP_VAR *var, double ub)
Definition: gscip.cc:583
absl::Status SetObjCoef(SCIP_VAR *var, double obj_coef)
Definition: gscip.cc:589
absl::StatusOr< SCIP_CONS * > AddSOS2Constraint(const GScipSOSData &sos_data, const std::string &name="", const GScipConstraintOptions &options=DefaultGScipConstraintOptions())
Definition: gscip.cc:527
static std::string ScipVersion()
Definition: gscip.cc:267
absl::StatusOr< SCIP_CONS * > AddQuadraticConstraint(const GScipQuadraticRange &range, const std::string &name="", const GScipConstraintOptions &options=DefaultGScipConstraintOptions())
Definition: gscip.cc:360
absl::string_view Name(SCIP_VAR *var)
Definition: gscip.cc:656
absl::StatusOr< SCIP_CONS * > AddSOS1Constraint(const GScipSOSData &sos_data, const std::string &name="", const GScipConstraintOptions &options=DefaultGScipConstraintOptions())
Definition: gscip.cc:500
static constexpr Status TOTAL_NODE_LIMIT
Definition: gscip.pb.h:1220
static constexpr Status BEST_SOL_LIMIT
Definition: gscip.pb.h:1232
static constexpr Status UNBOUNDED
Definition: gscip.pb.h:1240
static constexpr Status INF_OR_UNBD
Definition: gscip.pb.h:1242
static constexpr Status SOL_LIMIT
Definition: gscip.pb.h:1230
static constexpr Status STALL_NODE_LIMIT
Definition: gscip.pb.h:1222
static constexpr Status TERMINATE
Definition: gscip.pb.h:1244
void set_status(::operations_research::GScipOutput_Status value)
Definition: gscip.pb.h:2072
static constexpr Status GAP_LIMIT
Definition: gscip.pb.h:1228
static constexpr Status RESTART_LIMIT
Definition: gscip.pb.h:1234
static constexpr Status USER_INTERRUPT
Definition: gscip.pb.h:1216
static constexpr Status TIME_LIMIT
Definition: gscip.pb.h:1224
static constexpr Status INVALID_SOLVER_PARAMETERS
Definition: gscip.pb.h:1246
static constexpr Status NODE_LIMIT
Definition: gscip.pb.h:1218
static constexpr Status INFEASIBLE
Definition: gscip.pb.h:1238
static constexpr Status MEM_LIMIT
Definition: gscip.pb.h:1226
GScipOutput_Status Status
Definition: gscip.pb.h:1213
void set_status_detail(ArgT0 &&arg0, ArgT... args)
static constexpr Status OPTIMAL
Definition: gscip.pb.h:1236
::operations_research::GScipSolvingStats * mutable_stats()
Definition: gscip.pb.h:2188
static constexpr Status UNKNOWN
Definition: gscip.pb.h:1214
static constexpr Emphasis PHASE_IMPROVE
Definition: gscip.pb.h:492
static constexpr Emphasis FEASIBILITY
Definition: gscip.pb.h:484
static constexpr MetaParamValue FAST
Definition: gscip.pb.h:526
static constexpr Emphasis HARD_LP
Definition: gscip.pb.h:486
static constexpr Emphasis CP_SOLVER
Definition: gscip.pb.h:480
const std::string & scip_model_filename() const
Definition: gscip.pb.h:1799
static constexpr MetaParamValue AGGRESSIVE
Definition: gscip.pb.h:524
static constexpr Emphasis PHASE_FEAS
Definition: gscip.pb.h:490
static constexpr Emphasis PHASE_PROOF
Definition: gscip.pb.h:494
static constexpr MetaParamValue DEFAULT_META_PARAM_VALUE
Definition: gscip.pb.h:522
static constexpr Emphasis COUNTER
Definition: gscip.pb.h:478
static constexpr Emphasis OPTIMALITY
Definition: gscip.pb.h:488
static constexpr Emphasis EASY_CIP
Definition: gscip.pb.h:482
::PROTOBUF_NAMESPACE_ID::int32 num_solutions() const
Definition: gscip.pb.h:1856
GScipParameters_MetaParamValue MetaParamValue
Definition: gscip.pb.h:521
static constexpr Emphasis DEFAULT_EMPHASIS
Definition: gscip.pb.h:476
const std::string & detailed_solving_stats_filename() const
Definition: gscip.pb.h:1753
static constexpr MetaParamValue OFF
Definition: gscip.pb.h:528
GScipParameters_Emphasis Emphasis
Definition: gscip.pb.h:475
void set_node_count(::PROTOBUF_NAMESPACE_ID::int64 value)
Definition: gscip.pb.h:1988
void set_primal_simplex_iterations(::PROTOBUF_NAMESPACE_ID::int64 value)
Definition: gscip.pb.h:1928
void set_root_node_bound(double value)
Definition: gscip.pb.h:2028
void set_total_lp_iterations(::PROTOBUF_NAMESPACE_ID::int64 value)
Definition: gscip.pb.h:1968
void set_best_objective(double value)
Definition: gscip.pb.h:1888
void set_dual_simplex_iterations(::PROTOBUF_NAMESPACE_ID::int64 value)
Definition: gscip.pb.h:1948
void set_first_lp_relaxation_bound(double value)
Definition: gscip.pb.h:2008
void set_deterministic_time(double value)
Definition: gscip.pb.h:2048
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:181
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:176
absl::flat_hash_map< SCIP_VAR *, double > GScipSolution
Definition: gscip.h:74
#define SCIP_TO_STATUS(x)
#define RETURN_IF_SCIP_ERROR(x)
#define ASSIGN_OR_RETURN(lhs, rexpr)
Definition: status_macros.h:55
#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