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"
36 #include "ortools/base/logging.h"
38 #include "ortools/gscip/gscip.pb.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 
55 namespace 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 
62 namespace {
63 
64 constexpr absl::string_view kLinearConstraintHandlerName = "linear";
65 
66 SCIP_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 
77 GScipVarType 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 
89 GScipOutput::Status ConvertStatus(const SCIP_STATUS scip_status) {
90  switch (scip_status) {
91  case SCIP_STATUS_UNKNOWN:
92  return GScipOutput::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:
104  return GScipOutput::SOL_LIMIT;
105  case SCIP_STATUS_STALLNODELIMIT:
107  case SCIP_STATUS_TIMELIMIT:
109  case SCIP_STATUS_TOTALNODELIMIT:
111  case SCIP_STATUS_OPTIMAL:
112  return GScipOutput::OPTIMAL;
113  case SCIP_STATUS_GAPLIMIT:
114  return GScipOutput::GAP_LIMIT;
115  case SCIP_STATUS_INFEASIBLE:
117  case SCIP_STATUS_UNBOUNDED:
118  return GScipOutput::UNBOUNDED;
119  case SCIP_STATUS_INFORUNBD:
121  case SCIP_STATUS_TERMINATE:
122  return GScipOutput::TERMINATE;
123  default:
124  LOG(FATAL) << "Unrecognized scip status: " << scip_status;
125  }
126 }
127 
128 SCIP_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 
157 SCIP_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 
186 absl::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 
249 absl::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 
259 GScip::GScip(SCIP* scip) : scip_(scip) {}
260 
261 double GScip::ScipInf() { return SCIPinfinity(scip_); }
262 
263 absl::Status GScip::FreeTransform() {
264  return SCIP_TO_STATUS(SCIPfreeTransform(scip_));
265 }
266 
267 std::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 
280 absl::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 
302 absl::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 
324 absl::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 
334 absl::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 
360 absl::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 
394 absl::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 
428 absl::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 
453 absl::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 
478 namespace {
479 
480 absl::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 
500 absl::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 
527 absl::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 
553 absl::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 
559 absl::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 
570 double GScip::ObjectiveOffset() { return SCIPgetOrigObjoffset(scip_); }
571 
572 absl::Status GScip::SetBranchingPriority(SCIP_VAR* var, int priority) {
573  RETURN_IF_SCIP_ERROR(SCIPchgVarBranchPriority(scip_, var, priority));
574  return absl::OkStatus();
575 }
576 
577 absl::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 
583 absl::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 
589 absl::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 
594 absl::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 
601 absl::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 
622 absl::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)) {
632  RETURN_IF_ERROR(SetLinearConstraintCoef(constraint, var, 0.0));
633  }
634  }
635  }
636  for (SCIP_VAR* const var : vars) {
638  }
639  return absl::OkStatus();
640 }
641 
642 double GScip::Lb(SCIP_VAR* var) {
643  return ScipInfUnclamp(SCIPvarGetLbOriginal(var));
644 }
645 
646 double GScip::Ub(SCIP_VAR* var) {
647  return ScipInfUnclamp(SCIPvarGetUbOriginal(var));
648 }
649 
650 double GScip::ObjCoef(SCIP_VAR* var) { return SCIPvarGetObj(var); }
651 
653  return ConvertVarType(SCIPvarGetType(var));
654 }
655 
656 absl::string_view GScip::Name(SCIP_VAR* var) { return SCIPvarGetName(var); }
657 
658 absl::string_view GScip::ConstraintType(SCIP_CONS* constraint) {
659  return absl::string_view(SCIPconshdlrGetName(SCIPconsGetHdlr(constraint)));
660 }
661 
662 bool GScip::IsConstraintLinear(SCIP_CONS* constraint) {
663  return ConstraintType(constraint) == kLinearConstraintHandlerName;
664 }
665 
666 absl::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 
672 absl::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 
678 double GScip::LinearConstraintLb(SCIP_CONS* constraint) {
679  return ScipInfUnclamp(SCIPgetLhsLinear(scip_, constraint));
680 }
681 
682 double GScip::LinearConstraintUb(SCIP_CONS* constraint) {
683  return ScipInfUnclamp(SCIPgetRhsLinear(scip_, constraint));
684 }
685 
686 absl::string_view GScip::Name(SCIP_CONS* constraint) {
687  return SCIPconsGetName(constraint);
688 }
689 
690 absl::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 
696 absl::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 
702 absl::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 
709 absl::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 
718 absl::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 
755 absl::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.
842  GScipSolvingStats* stats = result.gscip_output.mutable_stats();
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 
903 absl::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 
911 absl::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 
919 absl::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 
927 absl::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 
935 absl::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 
943 absl::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 
951 double 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 
958 double 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
absl::Status SetLinearConstraintUb(SCIP_CONS *constraint, double ub)
Definition: gscip.cc:696
absl::Status SetObjCoef(SCIP_VAR *var, double obj_coef)
Definition: gscip.cc:589
absl::StatusOr< GScipResult > Solve(const GScipParameters &params=GScipParameters(), const std::string &legacy_params="", GScipMessageHandler message_handler=nullptr)
Definition: gscip.cc:755
static constexpr Emphasis COUNTER
Definition: gscip.pb.h:474
void set_root_node_bound(double value)
Definition: gscip.pb.h:2016
absl::StatusOr< SCIP_CONS * > AddSOS1Constraint(const GScipSOSData &sos_data, const std::string &name="", const GScipConstraintOptions &options=DefaultGScipConstraintOptions())
Definition: gscip.cc:500
void set_total_lp_iterations(::PROTOBUF_NAMESPACE_ID::int64 value)
Definition: gscip.pb.h:1956
absl::Status LegacyScipSetSolverSpecificParameters(const std::string &parameters, SCIP *scip)
static constexpr Status TERMINATE
Definition: gscip.pb.h:1232
int64_t min
Definition: alldiff_cst.cc:139
absl::StatusOr< double > DefaultRealParamValue(const std::string &parameter_name)
Definition: gscip.cc:927
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
std::vector< double > objective_values
Definition: gscip.h:85
static constexpr Status TOTAL_NODE_LIMIT
Definition: gscip.pb.h:1208
std::vector< SCIP_VAR * > variables
Definition: gscip.h:417
static absl::StatusOr< std::unique_ptr< GScip > > Create(const std::string &problem_name)
Definition: gscip.cc:249
const int FATAL
Definition: log_severity.h:32
MessageHandlerPtr CaptureMessageHandlerPtr(SCIP_MESSAGEHDLR *const handler)
std::vector< SCIP_Var * > variables
Definition: gscip.h:436
std::vector< double > quadratic_coefficients
Definition: gscip.h:398
static constexpr Status STALL_NODE_LIMIT
Definition: gscip.pb.h:1210
void set_node_count(::PROTOBUF_NAMESPACE_ID::int64 value)
Definition: gscip.pb.h:1976
absl::StatusOr< std::string > DefaultStringParamValue(const std::string &parameter_name)
Definition: gscip.cc:943
const std::string name
absl::StatusOr< SCIP_CONS * > AddIndicatorConstraint(const GScipIndicatorConstraint &indicator_constraint, const std::string &name="", const GScipConstraintOptions &options=DefaultGScipConstraintOptions())
Definition: gscip.cc:394
GScipParameters_Emphasis Emphasis
Definition: gscip.pb.h:471
std::vector< SCIP_Var * > quadratic_variables1
Definition: gscip.h:396
static constexpr MetaParamValue OFF
Definition: gscip.pb.h:524
std::vector< SCIP_VAR * > operators
Definition: gscip.h:449
static constexpr Emphasis CP_SOLVER
Definition: gscip.pb.h:476
static constexpr Emphasis OPTIMALITY
Definition: gscip.pb.h:484
#define LOG(severity)
Definition: base/logging.h:416
std::vector< GScipSolution > solutions
Definition: gscip.h:83
static constexpr Status USER_INTERRUPT
Definition: gscip.pb.h:1204
#define SCIP_TO_STATUS(x)
const std::string & detailed_solving_stats_filename() const
Definition: gscip.pb.h:1741
absl::StatusOr< MessageHandlerPtr > MakeSCIPMessageHandler(const GScipMessageHandler gscip_message_handler)
const char * SCIPlpiGetSolverName(void)
gets name and version of LP solver
Definition: lpi_glop.cc:137
::operations_research::GScipSolvingStats * mutable_stats()
Definition: gscip.pb.h:2176
absl::Status SetLinearConstraintLb(SCIP_CONS *constraint, double lb)
Definition: gscip.cc:690
static constexpr Status MEM_LIMIT
Definition: gscip.pb.h:1214
static constexpr Emphasis EASY_CIP
Definition: gscip.pb.h:478
double Ub(SCIP_VAR *var)
Definition: gscip.cc:646
#define RETURN_ERROR_UNLESS(x)
Definition: gscip.cc:57
void set_status_detail(ArgT0 &&arg0, ArgT... args)
absl::Status DeleteConstraint(SCIP_CONS *constraint)
Definition: gscip.cc:702
absl::StatusOr< SCIP_CONS * > AddSOS2Constraint(const GScipSOSData &sos_data, const std::string &name="", const GScipConstraintOptions &options=DefaultGScipConstraintOptions())
Definition: gscip.cc:527
void set_status(::operations_research::GScipOutput_Status value)
Definition: gscip.pb.h:2060
double LinearConstraintLb(SCIP_CONS *constraint)
Definition: gscip.cc:678
absl::Status CanSafeBulkDelete(const absl::flat_hash_set< SCIP_VAR * > &vars)
Definition: gscip.cc:611
void set_deterministic_time(double value)
Definition: gscip.pb.h:2036
GScipVarType VarType(SCIP_VAR *var)
Definition: gscip.cc:652
static constexpr Emphasis DEFAULT_EMPHASIS
Definition: gscip.pb.h:472
static constexpr Status BEST_SOL_LIMIT
Definition: gscip.pb.h:1220
absl::StatusOr< bool > DefaultBoolParamValue(const std::string &parameter_name)
Definition: gscip.cc:903
int64_t max
Definition: alldiff_cst.cc:140
static constexpr Status UNKNOWN
Definition: gscip.pb.h:1202
static constexpr Emphasis PHASE_PROOF
Definition: gscip.pb.h:490
absl::Status SetLb(SCIP_VAR *var, double lb)
Definition: gscip.cc:577
static constexpr MetaParamValue FAST
Definition: gscip.pb.h:522
static constexpr Emphasis HARD_LP
Definition: gscip.pb.h:482
::PROTOBUF_NAMESPACE_ID::int32 num_solutions() const
Definition: gscip.pb.h:1844
absl::StatusOr< char > DefaultCharParamValue(const std::string &parameter_name)
Definition: gscip.cc:935
const std::string & scip_model_filename() const
Definition: gscip.pb.h:1787
static constexpr Status INF_OR_UNBD
Definition: gscip.pb.h:1230
absl::flat_hash_map< SCIP_VAR *, double > primal_ray
Definition: gscip.h:90
absl::Status SetMaximize(bool is_maximize)
Definition: gscip.cc:553
absl::StatusOr< GScipHintResult > SuggestHint(const GScipSolution &partial_solution)
Definition: gscip.cc:718
std::vector< double > coefficients
Definition: gscip.h:101
const GScipVariableOptions & DefaultGScipVariableOptions()
Definition: gscip.cc:176
static constexpr Status GAP_LIMIT
Definition: gscip.pb.h:1216
absl::string_view ConstraintType(SCIP_CONS *constraint)
Definition: gscip.cc:658
void set_dual_simplex_iterations(::PROTOBUF_NAMESPACE_ID::int64 value)
Definition: gscip.pb.h:1936
std::vector< double > linear_coefficients
Definition: gscip.h:384
const GScipConstraintOptions & DefaultGScipConstraintOptions()
Definition: gscip.cc:181
static constexpr Status TIME_LIMIT
Definition: gscip.pb.h:1212
std::string ProtoEnumToString(ProtoEnumType enum_value)
static constexpr Emphasis PHASE_FEAS
Definition: gscip.pb.h:486
void set_primal_simplex_iterations(::PROTOBUF_NAMESPACE_ID::int64 value)
Definition: gscip.pb.h:1916
absl::StatusOr< SCIP_CONS * > AddQuadraticConstraint(const GScipQuadraticRange &range, const std::string &name="", const GScipConstraintOptions &options=DefaultGScipConstraintOptions())
Definition: gscip.cc:360
std::vector< SCIP_Var * > linear_variables
Definition: gscip.h:383
GScipParameters_MetaParamValue MetaParamValue
Definition: gscip.pb.h:517
#define RETURN_IF_SCIP_ERROR(x)
absl::StatusOr< SCIP_CONS * > AddAndConstraint(const GScipLogicalConstraintData &logical_data, const std::string &name="", const GScipConstraintOptions &options=DefaultGScipConstraintOptions())
Definition: gscip.cc:428
static constexpr Status NODE_LIMIT
Definition: gscip.pb.h:1206
absl::Status SetBranchingPriority(SCIP_VAR *var, int priority)
Definition: gscip.cc:572
std::vector< SCIP_Var * > quadratic_variables2
Definition: gscip.h:397
double LinearConstraintUb(SCIP_CONS *constraint)
Definition: gscip.cc:682
absl::string_view Name(SCIP_VAR *var)
Definition: gscip.cc:656
static constexpr Status INVALID_SOLVER_PARAMETERS
Definition: gscip.pb.h:1234
#define LOG_IF(severity, condition)
Definition: base/logging.h:475
std::unique_ptr< SCIP_MESSAGEHDLR, ReleaseSCIPMessageHandler > MessageHandlerPtr
static constexpr MetaParamValue DEFAULT_META_PARAM_VALUE
Definition: gscip.pb.h:518
absl::Status SetUb(SCIP_VAR *var, double ub)
Definition: gscip.cc:583
static constexpr Status OPTIMAL
Definition: gscip.pb.h:1224
int GScipMaxNumThreads(const GScipParameters &parameters)
absl::Span< const double > LinearConstraintCoefficients(SCIP_CONS *constraint)
Definition: gscip.cc:666
absl::StatusOr< SCIP_CONS * > AddLinearConstraint(const GScipLinearRange &range, const std::string &name="", const GScipConstraintOptions &options=DefaultGScipConstraintOptions())
Definition: gscip.cc:334
static constexpr MetaParamValue AGGRESSIVE
Definition: gscip.pb.h:520
static constexpr Emphasis FEASIBILITY
Definition: gscip.pb.h:480
absl::StatusOr< int > DefaultIntParamValue(const std::string &parameter_name)
Definition: gscip.cc:911
Collection of objects used to extend the Constraint Solver library.
std::vector< double > weights
Definition: gscip.h:426
absl::StatusOr< SCIP_CONS * > AddOrConstraint(const GScipLogicalConstraintData &logical_data, const std::string &name="", const GScipConstraintOptions &options=DefaultGScipConstraintOptions())
Definition: gscip.cc:453
void set_first_lp_relaxation_bound(double value)
Definition: gscip.pb.h:1996
absl::StatusOr< int64_t > DefaultLongParamValue(const std::string &parameter_name)
Definition: gscip.cc:919
static constexpr Status RESTART_LIMIT
Definition: gscip.pb.h:1222
double ObjCoef(SCIP_VAR *var)
Definition: gscip.cc:650
GScipOutput_Status Status
Definition: gscip.pb.h:1201
#define RETURN_IF_ERROR(expr)
Definition: status_macros.h:29
IntVar * var
Definition: expr_array.cc:1874
double Lb(SCIP_VAR *var)
Definition: gscip.cc:642
absl::Status SetVarType(SCIP_VAR *var, GScipVarType var_type)
Definition: gscip.cc:594
absl::Status SafeBulkDelete(const absl::flat_hash_set< SCIP_VAR * > &vars)
Definition: gscip.cc:622
std::vector< SCIP_VAR * > variables
Definition: gscip.h:100
static constexpr Status INFEASIBLE
Definition: gscip.pb.h:1226
absl::Status SetLinearConstraintCoef(SCIP_CONS *constraint, SCIP_VAR *var, double value)
Definition: gscip.cc:709
static constexpr Status SOL_LIMIT
Definition: gscip.pb.h:1218
static std::string ScipVersion()
Definition: gscip.cc:267
absl::Span< SCIP_VAR *const > LinearConstraintVariables(SCIP_CONS *constraint)
Definition: gscip.cc:672
absl::Status SetObjectiveOffset(double offset)
Definition: gscip.cc:559
absl::Status DeleteVariable(SCIP_VAR *var)
Definition: gscip.cc:601
int64_t value
std::function< void(GScipMessageType type, absl::string_view message)> GScipMessageHandler
absl::flat_hash_map< SCIP_VAR *, double > GScipSolution
Definition: gscip.h:74
void set_best_objective(double value)
Definition: gscip.pb.h:1876
#define ASSIGN_OR_RETURN(lhs, rexpr)
Definition: status_macros.h:55
bool IsConstraintLinear(SCIP_CONS *constraint)
Definition: gscip.cc:662
static constexpr Emphasis PHASE_IMPROVE
Definition: gscip.pb.h:488
static constexpr Status UNBOUNDED
Definition: gscip.pb.h:1228