27#include "absl/base/attributes.h"
28#include "absl/memory/memory.h"
29#include "absl/strings/str_format.h"
44class GLPKInformation {
46 explicit GLPKInformation(
bool maximize) : num_all_nodes_(0) {
47 ResetBestObjectiveBound(maximize);
49 void Reset(
bool maximize) {
51 ResetBestObjectiveBound(maximize);
53 void ResetBestObjectiveBound(
bool maximize) {
55 best_objective_bound_ = std::numeric_limits<double>::infinity();
57 best_objective_bound_ = -std::numeric_limits<double>::infinity();
61 double best_objective_bound_;
65void GLPKGatherInformationCallback(glp_tree* tree,
void* info) {
66 CHECK(tree !=
nullptr);
67 CHECK(info !=
nullptr);
68 GLPKInformation* glpk_info =
reinterpret_cast<GLPKInformation*
>(info);
69 switch (glp_ios_reason(tree)) {
76 glp_ios_tree_size(tree,
nullptr,
nullptr, &glpk_info->num_all_nodes_);
78 int node_id = glp_ios_best_node(tree);
80 glpk_info->best_objective_bound_ = glp_ios_node_bound(tree, node_id);
93int MPSolverIndexToGlpkIndex(
int index) {
return index + 1; }
96class GLPKInterface :
public MPSolverInterface {
99 GLPKInterface(MPSolver*
const solver,
bool mip);
100 ~GLPKInterface()
override;
103 void SetOptimizationDirection(
bool maximize)
override;
111 void Reset()
override;
114 void SetVariableBounds(
int mpsolver_var_index,
double lb,
double ub)
override;
115 void SetVariableInteger(
int mpsolver_var_index,
bool integer)
override;
116 void SetConstraintBounds(
int mpsolver_constraint_index,
double lb,
120 void AddRowConstraint(MPConstraint*
const ct)
override;
122 void AddVariable(MPVariable*
const var)
override;
124 void SetCoefficient(MPConstraint*
const constraint,
125 const MPVariable*
const variable,
double new_value,
126 double old_value)
override;
128 void ClearConstraint(MPConstraint*
const constraint)
override;
130 void SetObjectiveCoefficient(
const MPVariable*
const variable,
133 void SetObjectiveOffset(
double value)
override;
135 void ClearObjective()
override;
139 int64_t iterations()
const override;
141 int64_t
nodes()
const override;
149 bool CheckSolutionExists()
const override;
153 bool IsContinuous()
const override {
return IsLP(); }
154 bool IsLP()
const override {
return !mip_; }
155 bool IsMIP()
const override {
return mip_; }
157 void ExtractNewVariables()
override;
158 void ExtractNewConstraints()
override;
159 void ExtractObjective()
override;
161 std::string SolverVersion()
const override {
162 return absl::StrFormat(
"GLPK %s", glp_version());
165 void* underlying_solver()
override {
return reinterpret_cast<void*
>(lp_); }
167 double ComputeExactConditionNumber()
const override;
171 void ConfigureGLPKParameters(
const MPSolverParameters& param);
174 void SetParameters(
const MPSolverParameters& param)
override;
176 void SetRelativeMipGap(
double value)
override;
177 void SetPrimalTolerance(
double value)
override;
178 void SetDualTolerance(
double value)
override;
179 void SetPresolveMode(
int value)
override;
180 void SetScalingMode(
int value)
override;
181 void SetLpAlgorithm(
int value)
override;
183 void ExtractOldConstraints();
184 void ExtractOneConstraint(MPConstraint*
const constraint,
int*
const indices,
185 double*
const coefs);
192 double ComputeScaledBasisL1Norm(
int num_rows,
int num_cols,
193 double* row_scaling_factor,
194 double* column_scaling_factor)
const;
199 double ComputeInverseScaledBasisL1Norm(
int num_rows,
int num_cols,
200 double* row_scaling_factor,
201 double* column_scaling_factor)
const;
210 std::unique_ptr<GLPKInformation> mip_callback_info_;
214GLPKInterface::GLPKInterface(MPSolver*
const solver,
bool mip)
215 : MPSolverInterface(solver), lp_(nullptr), mip_(mip) {
219 lp_ = glp_create_prob();
220 glp_set_prob_name(lp_, solver_->name_.c_str());
221 glp_set_obj_dir(lp_, GLP_MIN);
222 mip_callback_info_ = absl::make_unique<GLPKInformation>(
maximize_);
226GLPKInterface::~GLPKInterface() {
227 CHECK(lp_ !=
nullptr);
228 glp_delete_prob(lp_);
232void GLPKInterface::Reset() {
233 CHECK(lp_ !=
nullptr);
234 glp_delete_prob(lp_);
235 lp_ = glp_create_prob();
236 glp_set_prob_name(lp_, solver_->name_.c_str());
237 glp_set_obj_dir(lp_,
maximize_ ? GLP_MAX : GLP_MIN);
238 ResetExtractionInformation();
244void GLPKInterface::SetOptimizationDirection(
bool maximize) {
245 InvalidateSolutionSynchronization();
246 glp_set_obj_dir(lp_, maximize ? GLP_MAX : GLP_MIN);
249void GLPKInterface::SetVariableBounds(
int mpsolver_var_index,
double lb,
251 InvalidateSolutionSynchronization();
252 if (!variable_is_extracted(mpsolver_var_index)) {
253 sync_status_ = MUST_RELOAD;
258 const double infinity = solver_->infinity();
259 const int glpk_var_index = MPSolverIndexToGlpkIndex(mpsolver_var_index);
260 if (lb != -infinity) {
261 if (ub != infinity) {
263 glp_set_col_bnds(lp_, glpk_var_index, GLP_FX, lb, ub);
265 glp_set_col_bnds(lp_, glpk_var_index, GLP_DB, lb, ub);
268 glp_set_col_bnds(lp_, glpk_var_index, GLP_LO, lb, 0.0);
270 }
else if (ub != infinity) {
271 glp_set_col_bnds(lp_, glpk_var_index, GLP_UP, 0.0, ub);
273 glp_set_col_bnds(lp_, glpk_var_index, GLP_FR, 0.0, 0.0);
277void GLPKInterface::SetVariableInteger(
int mpsolver_var_index,
bool integer) {
278 InvalidateSolutionSynchronization();
280 if (variable_is_extracted(mpsolver_var_index)) {
282 glp_set_col_kind(lp_, MPSolverIndexToGlpkIndex(mpsolver_var_index),
283 integer ? GLP_IV : GLP_CV);
285 sync_status_ = MUST_RELOAD;
290void GLPKInterface::SetConstraintBounds(
int mpsolver_constraint_index,
291 double lb,
double ub) {
292 InvalidateSolutionSynchronization();
293 if (!constraint_is_extracted(mpsolver_constraint_index)) {
294 sync_status_ = MUST_RELOAD;
298 const int glpk_constraint_index =
299 MPSolverIndexToGlpkIndex(mpsolver_constraint_index);
301 const double infinity = solver_->infinity();
302 if (lb != -infinity) {
303 if (ub != infinity) {
305 glp_set_row_bnds(lp_, glpk_constraint_index, GLP_FX, lb, ub);
307 glp_set_row_bnds(lp_, glpk_constraint_index, GLP_DB, lb, ub);
310 glp_set_row_bnds(lp_, glpk_constraint_index, GLP_LO, lb, 0.0);
312 }
else if (ub != infinity) {
313 glp_set_row_bnds(lp_, glpk_constraint_index, GLP_UP, 0.0, ub);
315 glp_set_row_bnds(lp_, glpk_constraint_index, GLP_FR, 0.0, 0.0);
319void GLPKInterface::SetCoefficient(MPConstraint*
const constraint,
320 const MPVariable*
const variable,
321 double new_value,
double old_value) {
322 InvalidateSolutionSynchronization();
327 if (constraint_is_extracted(constraint->index()) &&
328 (sync_status_ == MODEL_SYNCHRONIZED ||
329 !constraint->ContainsNewVariables())) {
330 const int size = constraint->coefficients_.size();
331 std::unique_ptr<int[]> indices(
new int[size + 1]);
332 std::unique_ptr<double[]> coefs(
new double[size + 1]);
333 ExtractOneConstraint(constraint, indices.get(), coefs.get());
338void GLPKInterface::ClearConstraint(MPConstraint*
const constraint) {
339 InvalidateSolutionSynchronization();
341 if (constraint_is_extracted(constraint->index())) {
342 glp_set_mat_row(lp_, MPSolverIndexToGlpkIndex(constraint->index()), 0,
348void GLPKInterface::SetObjectiveCoefficient(
const MPVariable*
const variable,
350 sync_status_ = MUST_RELOAD;
354void GLPKInterface::SetObjectiveOffset(
double value) {
355 sync_status_ = MUST_RELOAD;
359void GLPKInterface::ClearObjective() {
360 InvalidateSolutionSynchronization();
361 for (
const auto& entry : solver_->objective_->coefficients_) {
362 const int mpsolver_var_index = entry.first->index();
364 if (!variable_is_extracted(mpsolver_var_index)) {
365 DCHECK_NE(MODEL_SYNCHRONIZED, sync_status_);
367 glp_set_obj_coef(lp_, MPSolverIndexToGlpkIndex(mpsolver_var_index), 0.0);
371 glp_set_obj_coef(lp_, 0, 0.0);
374void GLPKInterface::AddRowConstraint(MPConstraint*
const ct) {
375 sync_status_ = MUST_RELOAD;
378void GLPKInterface::AddVariable(MPVariable*
const var) {
379 sync_status_ = MUST_RELOAD;
383void GLPKInterface::ExtractNewVariables() {
384 int total_num_vars = solver_->variables_.size();
385 if (total_num_vars > last_variable_index_) {
386 glp_add_cols(lp_, total_num_vars - last_variable_index_);
387 for (
int j = last_variable_index_; j < solver_->variables_.size(); ++j) {
388 MPVariable*
const var = solver_->variables_[j];
389 set_variable_as_extracted(j,
true);
390 if (!
var->name().empty()) {
391 glp_set_col_name(lp_, MPSolverIndexToGlpkIndex(j),
var->name().c_str());
393 SetVariableBounds(j,
var->lb(),
var->ub());
394 SetVariableInteger(j,
var->integer());
397 double tmp_obj_coef = 0.0;
398 glp_set_obj_coef(lp_, MPSolverIndexToGlpkIndex(j), tmp_obj_coef);
401 ExtractOldConstraints();
406void GLPKInterface::ExtractOldConstraints() {
407 const int max_constraint_size =
408 solver_->ComputeMaxConstraintSize(0, last_constraint_index_);
411 std::unique_ptr<int[]> indices(
new int[max_constraint_size + 1]);
412 std::unique_ptr<double[]> coefs(
new double[max_constraint_size + 1]);
414 for (
int i = 0; i < last_constraint_index_; ++i) {
415 MPConstraint*
const ct = solver_->constraints_[i];
416 DCHECK(constraint_is_extracted(i));
417 const int size =
ct->coefficients_.size();
422 if (
ct->ContainsNewVariables()) {
423 ExtractOneConstraint(
ct, indices.get(), coefs.get());
431void GLPKInterface::ExtractOneConstraint(MPConstraint*
const constraint,
433 double*
const coefs) {
436 for (
const auto& entry : constraint->coefficients_) {
437 DCHECK(variable_is_extracted(entry.first->index()));
438 indices[k] = MPSolverIndexToGlpkIndex(entry.first->index());
439 coefs[k] = entry.second;
442 glp_set_mat_row(lp_, MPSolverIndexToGlpkIndex(constraint->index()), k - 1,
447void GLPKInterface::ExtractNewConstraints() {
448 int total_num_rows = solver_->constraints_.size();
449 if (last_constraint_index_ < total_num_rows) {
451 glp_add_rows(lp_, total_num_rows - last_constraint_index_);
453 for (
int i = last_constraint_index_; i < total_num_rows; ++i) {
454 MPConstraint*
ct = solver_->constraints_[i];
455 set_constraint_as_extracted(i,
true);
456 if (
ct->name().empty()) {
457 glp_set_row_name(lp_, MPSolverIndexToGlpkIndex(i),
458 absl::StrFormat(
"ct_%i", i).c_str());
460 glp_set_row_name(lp_, MPSolverIndexToGlpkIndex(i),
ct->name().c_str());
463 SetConstraintBounds(i,
ct->lb(),
ct->ub());
464 num_coefs +=
ct->coefficients_.size();
468 if (last_variable_index_ == 0 && last_constraint_index_ == 0) {
475 std::unique_ptr<int[]> variable_indices(
new int[num_coefs + 1]);
476 std::unique_ptr<int[]> constraint_indices(
new int[num_coefs + 1]);
477 std::unique_ptr<double[]> coefs(
new double[num_coefs + 1]);
479 for (
int i = 0; i < solver_->constraints_.size(); ++i) {
480 MPConstraint*
ct = solver_->constraints_[i];
481 for (
const auto& entry :
ct->coefficients_) {
482 DCHECK(variable_is_extracted(entry.first->index()));
483 constraint_indices[k] = MPSolverIndexToGlpkIndex(
ct->index());
484 variable_indices[k] = MPSolverIndexToGlpkIndex(entry.first->index());
485 coefs[k] = entry.second;
490 glp_load_matrix(lp_, num_coefs, constraint_indices.get(),
491 variable_indices.get(), coefs.get());
494 int max_constraint_size = solver_->ComputeMaxConstraintSize(
495 last_constraint_index_, total_num_rows);
498 std::unique_ptr<int[]> indices(
new int[max_constraint_size + 1]);
499 std::unique_ptr<double[]> coefs(
new double[max_constraint_size + 1]);
500 for (
int i = last_constraint_index_; i < total_num_rows; i++) {
501 ExtractOneConstraint(solver_->constraints_[i], indices.get(),
508void GLPKInterface::ExtractObjective() {
511 for (
const auto& entry : solver_->objective_->coefficients_) {
512 glp_set_obj_coef(lp_, MPSolverIndexToGlpkIndex(entry.first->index()),
516 glp_set_obj_coef(lp_, 0, solver_->Objective().offset());
525 if (param.GetIntegerParam(MPSolverParameters::INCREMENTALITY) ==
526 MPSolverParameters::INCREMENTALITY_OFF) {
532 glp_term_out(GLP_OFF);
534 glp_term_out(GLP_ON);
538 VLOG(1) << absl::StrFormat(
"Model built in %.3f seconds.", timer.
Get());
543 ConfigureGLPKParameters(param);
547 int solver_status = glp_simplex(lp_, &lp_param_);
551 if (solver_status == 0) {
552 solver_status = glp_intopt(lp_, &mip_param_);
558 result_status_ = MPSolver::ABNORMAL;
559 if (solver_status == GLP_ETMLIM) {
560 result_status_ = MPSolver::NOT_SOLVED;
562 sync_status_ = SOLUTION_SYNCHRONIZED;
563 return result_status_;
566 VLOG(1) << absl::StrFormat(
"GLPK Status: %i (time spent: %.3f seconds).",
567 solver_status, timer.
Get());
571 objective_value_ = glp_mip_obj_val(lp_);
572 best_objective_bound_ = mip_callback_info_->best_objective_bound_;
574 objective_value_ = glp_get_obj_val(lp_);
576 VLOG(1) <<
"objective=" << objective_value_
577 <<
", bound=" << best_objective_bound_;
578 for (
int i = 0; i < solver_->variables_.size(); ++i) {
579 MPVariable*
const var = solver_->variables_[i];
582 val = glp_mip_col_val(lp_, MPSolverIndexToGlpkIndex(i));
584 val = glp_get_col_prim(lp_, MPSolverIndexToGlpkIndex(i));
586 var->set_solution_value(val);
587 VLOG(3) <<
var->name() <<
": value =" << val;
590 reduced_cost = glp_get_col_dual(lp_, MPSolverIndexToGlpkIndex(i));
591 var->set_reduced_cost(reduced_cost);
592 VLOG(4) <<
var->name() <<
": reduced cost = " << reduced_cost;
595 for (
int i = 0; i < solver_->constraints_.size(); ++i) {
596 MPConstraint*
const ct = solver_->constraints_[i];
598 const double dual_value =
599 glp_get_row_dual(lp_, MPSolverIndexToGlpkIndex(i));
600 ct->set_dual_value(dual_value);
601 VLOG(4) <<
"row " << MPSolverIndexToGlpkIndex(i)
602 <<
": dual value = " << dual_value;
608 int tmp_status = glp_mip_status(lp_);
609 VLOG(1) <<
"GLPK result status: " << tmp_status;
610 if (tmp_status == GLP_OPT) {
612 }
else if (tmp_status == GLP_FEAS) {
614 }
else if (tmp_status == GLP_NOFEAS) {
619 }
else if (solver_status == GLP_ETMLIM) {
620 result_status_ = MPSolver::NOT_SOLVED;
622 result_status_ = MPSolver::ABNORMAL;
627 int tmp_status = glp_get_status(lp_);
628 VLOG(1) <<
"GLPK result status: " << tmp_status;
629 if (tmp_status == GLP_OPT) {
631 }
else if (tmp_status == GLP_FEAS) {
633 }
else if (tmp_status == GLP_NOFEAS || tmp_status == GLP_INFEAS) {
638 }
else if (tmp_status == GLP_UNBND) {
642 result_status_ = MPSolver::UNBOUNDED;
643 }
else if (solver_status == GLP_ETMLIM) {
644 result_status_ = MPSolver::NOT_SOLVED;
646 result_status_ = MPSolver::ABNORMAL;
650 sync_status_ = SOLUTION_SYNCHRONIZED;
652 return result_status_;
656 int glpk_basis_status)
const {
657 switch (glpk_basis_status) {
659 return MPSolver::BASIC;
661 return MPSolver::AT_LOWER_BOUND;
663 return MPSolver::AT_UPPER_BOUND;
665 return MPSolver::FREE;
667 return MPSolver::FIXED_VALUE;
669 LOG(
FATAL) <<
"Unknown GLPK basis status";
670 return MPSolver::FREE;
676int64_t GLPKInterface::iterations()
const {
677#if GLP_MAJOR_VERSION == 4 && GLP_MINOR_VERSION < 49
678 if (!mip_ && CheckSolutionIsSynchronized()) {
679 return lpx_get_int_parm(lp_, LPX_K_ITCNT);
681#elif (GLP_MAJOR_VERSION == 4 && GLP_MINOR_VERSION >= 53) || \
682 GLP_MAJOR_VERSION >= 5
683 if (!mip_ && CheckSolutionIsSynchronized()) {
684 return glp_get_it_cnt(lp_);
687 LOG(
WARNING) <<
"Total number of iterations is not available";
688 return kUnknownNumberOfIterations;
693 if (!CheckSolutionIsSynchronized())
return kUnknownNumberOfNodes;
694 return mip_callback_info_->num_all_nodes_;
696 LOG(DFATAL) <<
"Number of nodes only available for discrete problems";
697 return kUnknownNumberOfNodes;
703 DCHECK_LT(constraint_index, last_constraint_index_);
704 const int glpk_basis_status =
705 glp_get_row_stat(lp_, MPSolverIndexToGlpkIndex(constraint_index));
706 return TransformGLPKBasisStatus(glpk_basis_status);
711 DCHECK_LT(variable_index, last_variable_index_);
712 const int glpk_basis_status =
713 glp_get_col_stat(lp_, MPSolverIndexToGlpkIndex(variable_index));
714 return TransformGLPKBasisStatus(glpk_basis_status);
717bool GLPKInterface::CheckSolutionExists()
const {
718 if (result_status_ == MPSolver::ABNORMAL) {
719 LOG(
WARNING) <<
"Ignoring ABNORMAL status from GLPK: This status may or may"
720 <<
" not indicate that a solution exists.";
724 return MPSolverInterface::CheckSolutionExists();
728double GLPKInterface::ComputeExactConditionNumber()
const {
729 if (!IsContinuous()) {
731 LOG(DFATAL) <<
"ComputeExactConditionNumber not implemented for"
732 <<
" GLPK_MIXED_INTEGER_PROGRAMMING";
735 if (!CheckSolutionIsSynchronized())
return 0.0;
738 CheckSolutionExists();
739 const int num_rows = glp_get_num_rows(lp_);
740 const int num_cols = glp_get_num_cols(lp_);
742 std::unique_ptr<double[]> row_scaling_factor(
new double[num_rows + 1]);
743 std::unique_ptr<double[]> column_scaling_factor(
new double[num_cols + 1]);
744 for (
int row = 1;
row <= num_rows; ++
row) {
745 row_scaling_factor[
row] = glp_get_rii(lp_,
row);
747 for (
int col = 1;
col <= num_cols; ++
col) {
748 column_scaling_factor[
col] = glp_get_sjj(lp_,
col);
750 return ComputeInverseScaledBasisL1Norm(num_rows, num_cols,
751 row_scaling_factor.get(),
752 column_scaling_factor.get()) *
753 ComputeScaledBasisL1Norm(num_rows, num_cols, row_scaling_factor.get(),
754 column_scaling_factor.get());
757double GLPKInterface::ComputeScaledBasisL1Norm(
758 int num_rows,
int num_cols,
double* row_scaling_factor,
759 double* column_scaling_factor)
const {
761 std::unique_ptr<double[]> values(
new double[num_rows + 1]);
762 std::unique_ptr<int[]> indices(
new int[num_rows + 1]);
763 for (
int col = 1;
col <= num_cols; ++
col) {
764 const int glpk_basis_status = glp_get_col_stat(lp_,
col);
766 if (glpk_basis_status == GLP_BS) {
768 const int num_nz = glp_get_mat_col(lp_,
col, indices.get(), values.get());
769 double column_norm = 0.0;
770 for (
int k = 1; k <= num_nz; k++) {
771 column_norm += fabs(values[k] * row_scaling_factor[indices[k]]);
773 column_norm *= fabs(column_scaling_factor[
col]);
779 for (
int row = 1;
row <= num_rows; ++
row) {
780 const int glpk_basis_status = glp_get_row_stat(lp_,
row);
782 if (glpk_basis_status == GLP_BS) {
786 const double column_norm = fabs(row_scaling_factor[
row]);
794double GLPKInterface::ComputeInverseScaledBasisL1Norm(
795 int num_rows,
int num_cols,
double* row_scaling_factor,
796 double* column_scaling_factor)
const {
798 if (!glp_bf_exists(lp_)) {
799 const int factorize_status = glp_factorize(lp_);
800 switch (factorize_status) {
802 LOG(
FATAL) <<
"Not able to factorize: error GLP_EBADB.";
807 <<
"Not able to factorize: "
808 <<
"the basis matrix is singular within the working precision.";
809 return MPSolver::infinity();
813 <<
"Not able to factorize: the basis matrix is ill-conditioned.";
814 return MPSolver::infinity();
820 std::unique_ptr<double[]> right_hand_side(
new double[num_rows + 1]);
834 for (
int k = 1; k <= num_rows; ++k) {
835 for (
int row = 1;
row <= num_rows; ++
row) {
836 right_hand_side[
row] = 0.0;
838 right_hand_side[k] = 1.0;
840 for (
int row = 1;
row <= num_rows; ++
row) {
841 right_hand_side[
row] /= row_scaling_factor[
row];
843 glp_ftran(lp_, right_hand_side.get());
847 for (
int row = 1;
row <= num_rows; ++
row) {
848 const int k = glp_get_bhead(lp_,
row);
851 right_hand_side[
row] *= row_scaling_factor[k];
854 right_hand_side[
row] /= column_scaling_factor[k - num_rows];
858 double column_norm = 0.0;
859 for (
int row = 1;
row <= num_rows; ++
row) {
860 column_norm += fabs(right_hand_side[
row]);
870void GLPKInterface::ConfigureGLPKParameters(
const MPSolverParameters& param) {
872 glp_init_iocp(&mip_param_);
874 if (solver_->time_limit()) {
875 VLOG(1) <<
"Setting time limit = " << solver_->time_limit() <<
" ms.";
876 mip_param_.tm_lim = solver_->time_limit();
879 mip_param_.cb_func = GLPKGatherInformationCallback;
881 mip_param_.cb_info = mip_callback_info_.get();
887 glp_init_smcp(&lp_param_);
889 if (solver_->time_limit()) {
890 VLOG(1) <<
"Setting time limit = " << solver_->time_limit() <<
" ms.";
891 lp_param_.tm_lim = solver_->time_limit();
895 glp_scale_prob(lp_, GLP_SF_AUTO);
898 glp_adv_basis(lp_, 0);
901 SetParameters(param);
904void GLPKInterface::SetParameters(
const MPSolverParameters& param) {
905 SetCommonParameters(param);
907 SetMIPParameters(param);
911void GLPKInterface::SetRelativeMipGap(
double value) {
913 mip_param_.mip_gap =
value;
915 LOG(
WARNING) <<
"The relative MIP gap is only available "
916 <<
"for discrete problems.";
920void GLPKInterface::SetPrimalTolerance(
double value) {
921 lp_param_.tol_bnd =
value;
924void GLPKInterface::SetDualTolerance(
double value) { lp_param_.tol_dj =
value; }
926void GLPKInterface::SetPresolveMode(
int value) {
928 case MPSolverParameters::PRESOLVE_OFF: {
929 mip_param_.presolve = GLP_OFF;
930 lp_param_.presolve = GLP_OFF;
933 case MPSolverParameters::PRESOLVE_ON: {
934 mip_param_.presolve = GLP_ON;
935 lp_param_.presolve = GLP_ON;
939 SetIntegerParamToUnsupportedValue(MPSolverParameters::PRESOLVE,
value);
944void GLPKInterface::SetScalingMode(
int value) {
945 SetUnsupportedIntegerParam(MPSolverParameters::SCALING);
948void GLPKInterface::SetLpAlgorithm(
int value) {
950 case MPSolverParameters::DUAL: {
952 lp_param_.meth = GLP_DUALP;
955 case MPSolverParameters::PRIMAL: {
956 lp_param_.meth = GLP_PRIMAL;
959 case MPSolverParameters::BARRIER:
961 SetIntegerParamToUnsupportedValue(MPSolverParameters::LP_ALGORITHM,
967MPSolverInterface* BuildGLPKInterface(
bool mip, MPSolver*
const solver) {
968 return new GLPKInterface(solver, mip);
#define DCHECK_NE(val1, val2)
#define CHECK_EQ(val1, val2)
#define DCHECK_GE(val1, val2)
#define DCHECK_LT(val1, val2)
#define DCHECK(condition)
#define VLOG(verboselevel)
ResultStatus
The status of solving the problem.
BasisStatus
Advanced usage: possible basis status values for a variable and the slack variable of a linear constr...
A C++ wrapper that provides a simple and unified interface to several linear programming and mixed in...
absl::StatusOr< SolveResult > Solve(const Model &model, const SolverType solver_type, const SolveArguments &solve_args, const SolverInitArguments &init_args)
Collection of objects used to extend the Constraint Solver library.