28 #include "absl/base/attributes.h"
29 #include "absl/memory/memory.h"
30 #include "absl/strings/str_format.h"
45 class GLPKInformation {
47 explicit GLPKInformation(
bool maximize) : num_all_nodes_(0) {
48 ResetBestObjectiveBound(maximize);
50 void Reset(
bool maximize) {
52 ResetBestObjectiveBound(maximize);
54 void ResetBestObjectiveBound(
bool maximize) {
56 best_objective_bound_ = std::numeric_limits<double>::infinity();
58 best_objective_bound_ = -std::numeric_limits<double>::infinity();
62 double best_objective_bound_;
66 void GLPKGatherInformationCallback(glp_tree* tree,
void* info) {
67 CHECK(tree !=
nullptr);
68 CHECK(info !=
nullptr);
69 GLPKInformation* glpk_info =
reinterpret_cast<GLPKInformation*
>(info);
70 switch (glp_ios_reason(tree)) {
77 glp_ios_tree_size(tree,
nullptr,
nullptr, &glpk_info->num_all_nodes_);
79 int node_id = glp_ios_best_node(tree);
81 glpk_info->best_objective_bound_ = glp_ios_node_bound(tree, node_id);
94 int MPSolverIndexToGlpkIndex(
int index) {
return index + 1; }
97 class GLPKInterface :
public MPSolverInterface {
100 GLPKInterface(MPSolver*
const solver,
bool mip);
101 ~GLPKInterface()
override;
104 void SetOptimizationDirection(
bool maximize)
override;
112 void Reset()
override;
115 void SetVariableBounds(
int mpsolver_var_index,
double lb,
double ub)
override;
116 void SetVariableInteger(
int mpsolver_var_index,
bool integer)
override;
117 void SetConstraintBounds(
int mpsolver_constraint_index,
double lb,
121 void AddRowConstraint(MPConstraint*
const ct)
override;
123 void AddVariable(MPVariable*
const var)
override;
125 void SetCoefficient(MPConstraint*
const constraint,
126 const MPVariable*
const variable,
double new_value,
127 double old_value)
override;
129 void ClearConstraint(MPConstraint*
const constraint)
override;
131 void SetObjectiveCoefficient(
const MPVariable*
const variable,
134 void SetObjectiveOffset(
double value)
override;
136 void ClearObjective()
override;
140 int64_t iterations()
const override;
142 int64_t
nodes()
const override;
150 bool CheckSolutionExists()
const override;
154 bool IsContinuous()
const override {
return IsLP(); }
155 bool IsLP()
const override {
return !mip_; }
156 bool IsMIP()
const override {
return mip_; }
158 void ExtractNewVariables()
override;
159 void ExtractNewConstraints()
override;
160 void ExtractObjective()
override;
162 std::string SolverVersion()
const override {
163 return absl::StrFormat(
"GLPK %s", glp_version());
166 void* underlying_solver()
override {
return reinterpret_cast<void*
>(lp_); }
168 double ComputeExactConditionNumber()
const override;
172 void ConfigureGLPKParameters(
const MPSolverParameters& param);
175 void SetParameters(
const MPSolverParameters& param)
override;
177 void SetRelativeMipGap(
double value)
override;
178 void SetPrimalTolerance(
double value)
override;
179 void SetDualTolerance(
double value)
override;
180 void SetPresolveMode(
int value)
override;
181 void SetScalingMode(
int value)
override;
182 void SetLpAlgorithm(
int value)
override;
184 void ExtractOldConstraints();
185 void ExtractOneConstraint(MPConstraint*
const constraint,
int*
const indices,
186 double*
const coefs);
193 double ComputeScaledBasisL1Norm(
int num_rows,
int num_cols,
194 double* row_scaling_factor,
195 double* column_scaling_factor)
const;
200 double ComputeInverseScaledBasisL1Norm(
int num_rows,
int num_cols,
201 double* row_scaling_factor,
202 double* column_scaling_factor)
const;
211 std::unique_ptr<GLPKInformation> mip_callback_info_;
215 GLPKInterface::GLPKInterface(MPSolver*
const solver,
bool mip)
216 : MPSolverInterface(solver), lp_(nullptr), mip_(mip) {
220 lp_ = glp_create_prob();
221 glp_set_prob_name(lp_, solver_->name_.c_str());
222 glp_set_obj_dir(lp_, GLP_MIN);
223 mip_callback_info_ = std::make_unique<GLPKInformation>(
maximize_);
227 GLPKInterface::~GLPKInterface() {
228 CHECK(lp_ !=
nullptr);
229 glp_delete_prob(lp_);
233 void GLPKInterface::Reset() {
234 CHECK(lp_ !=
nullptr);
235 glp_delete_prob(lp_);
236 lp_ = glp_create_prob();
237 glp_set_prob_name(lp_, solver_->name_.c_str());
238 glp_set_obj_dir(lp_,
maximize_ ? GLP_MAX : GLP_MIN);
239 ResetExtractionInformation();
245 void GLPKInterface::SetOptimizationDirection(
bool maximize) {
246 InvalidateSolutionSynchronization();
247 glp_set_obj_dir(lp_, maximize ? GLP_MAX : GLP_MIN);
250 void GLPKInterface::SetVariableBounds(
int mpsolver_var_index,
double lb,
252 InvalidateSolutionSynchronization();
253 if (!variable_is_extracted(mpsolver_var_index)) {
254 sync_status_ = MUST_RELOAD;
258 DCHECK(lp_ !=
nullptr);
259 const double infinity = solver_->infinity();
260 const int glpk_var_index = MPSolverIndexToGlpkIndex(mpsolver_var_index);
261 if (lb != -infinity) {
262 if (ub != infinity) {
264 glp_set_col_bnds(lp_, glpk_var_index, GLP_FX, lb, ub);
266 glp_set_col_bnds(lp_, glpk_var_index, GLP_DB, lb, ub);
269 glp_set_col_bnds(lp_, glpk_var_index, GLP_LO, lb, 0.0);
271 }
else if (ub != infinity) {
272 glp_set_col_bnds(lp_, glpk_var_index, GLP_UP, 0.0, ub);
274 glp_set_col_bnds(lp_, glpk_var_index, GLP_FR, 0.0, 0.0);
278 void GLPKInterface::SetVariableInteger(
int mpsolver_var_index,
bool integer) {
279 InvalidateSolutionSynchronization();
281 if (variable_is_extracted(mpsolver_var_index)) {
283 glp_set_col_kind(lp_, MPSolverIndexToGlpkIndex(mpsolver_var_index),
284 integer ? GLP_IV : GLP_CV);
286 sync_status_ = MUST_RELOAD;
291 void GLPKInterface::SetConstraintBounds(
int mpsolver_constraint_index,
292 double lb,
double ub) {
293 InvalidateSolutionSynchronization();
294 if (!constraint_is_extracted(mpsolver_constraint_index)) {
295 sync_status_ = MUST_RELOAD;
299 const int glpk_constraint_index =
300 MPSolverIndexToGlpkIndex(mpsolver_constraint_index);
301 DCHECK(lp_ !=
nullptr);
302 const double infinity = solver_->infinity();
303 if (lb != -infinity) {
304 if (ub != infinity) {
306 glp_set_row_bnds(lp_, glpk_constraint_index, GLP_FX, lb, ub);
308 glp_set_row_bnds(lp_, glpk_constraint_index, GLP_DB, lb, ub);
311 glp_set_row_bnds(lp_, glpk_constraint_index, GLP_LO, lb, 0.0);
313 }
else if (ub != infinity) {
314 glp_set_row_bnds(lp_, glpk_constraint_index, GLP_UP, 0.0, ub);
316 glp_set_row_bnds(lp_, glpk_constraint_index, GLP_FR, 0.0, 0.0);
320 void GLPKInterface::SetCoefficient(MPConstraint*
const constraint,
321 const MPVariable*
const variable,
322 double new_value,
double old_value) {
323 InvalidateSolutionSynchronization();
328 if (constraint_is_extracted(constraint->index()) &&
329 (sync_status_ == MODEL_SYNCHRONIZED ||
330 !constraint->ContainsNewVariables())) {
331 const int size = constraint->coefficients_.size();
332 std::unique_ptr<int[]> indices(
new int[size + 1]);
333 std::unique_ptr<double[]> coefs(
new double[size + 1]);
334 ExtractOneConstraint(constraint, indices.get(), coefs.get());
339 void GLPKInterface::ClearConstraint(MPConstraint*
const constraint) {
340 InvalidateSolutionSynchronization();
342 if (constraint_is_extracted(constraint->index())) {
343 glp_set_mat_row(lp_, MPSolverIndexToGlpkIndex(constraint->index()), 0,
349 void GLPKInterface::SetObjectiveCoefficient(
const MPVariable*
const variable,
351 sync_status_ = MUST_RELOAD;
355 void GLPKInterface::SetObjectiveOffset(
double value) {
356 sync_status_ = MUST_RELOAD;
360 void GLPKInterface::ClearObjective() {
361 InvalidateSolutionSynchronization();
362 for (
const auto& entry : solver_->objective_->coefficients_) {
363 const int mpsolver_var_index = entry.first->index();
365 if (!variable_is_extracted(mpsolver_var_index)) {
366 DCHECK_NE(MODEL_SYNCHRONIZED, sync_status_);
368 glp_set_obj_coef(lp_, MPSolverIndexToGlpkIndex(mpsolver_var_index), 0.0);
372 glp_set_obj_coef(lp_, 0, 0.0);
375 void GLPKInterface::AddRowConstraint(MPConstraint*
const ct) {
376 sync_status_ = MUST_RELOAD;
379 void GLPKInterface::AddVariable(MPVariable*
const var) {
380 sync_status_ = MUST_RELOAD;
384 void GLPKInterface::ExtractNewVariables() {
385 int total_num_vars = solver_->variables_.size();
386 if (total_num_vars > last_variable_index_) {
387 glp_add_cols(lp_, total_num_vars - last_variable_index_);
388 for (
int j = last_variable_index_; j < solver_->variables_.size(); ++j) {
389 MPVariable*
const var = solver_->variables_[j];
390 set_variable_as_extracted(j,
true);
391 if (!
var->name().empty()) {
392 glp_set_col_name(lp_, MPSolverIndexToGlpkIndex(j),
var->name().c_str());
394 SetVariableBounds(j,
var->lb(),
var->ub());
395 SetVariableInteger(j,
var->integer());
398 double tmp_obj_coef = 0.0;
399 glp_set_obj_coef(lp_, MPSolverIndexToGlpkIndex(j), tmp_obj_coef);
402 ExtractOldConstraints();
407 void GLPKInterface::ExtractOldConstraints() {
408 const int max_constraint_size =
409 solver_->ComputeMaxConstraintSize(0, last_constraint_index_);
412 std::unique_ptr<int[]> indices(
new int[max_constraint_size + 1]);
413 std::unique_ptr<double[]> coefs(
new double[max_constraint_size + 1]);
415 for (
int i = 0; i < last_constraint_index_; ++i) {
416 MPConstraint*
const ct = solver_->constraints_[i];
417 DCHECK(constraint_is_extracted(i));
418 const int size =
ct->coefficients_.size();
423 if (
ct->ContainsNewVariables()) {
424 ExtractOneConstraint(
ct, indices.get(), coefs.get());
432 void GLPKInterface::ExtractOneConstraint(MPConstraint*
const constraint,
434 double*
const coefs) {
437 for (
const auto& entry : constraint->coefficients_) {
438 DCHECK(variable_is_extracted(entry.first->index()));
439 indices[k] = MPSolverIndexToGlpkIndex(entry.first->index());
440 coefs[k] = entry.second;
443 glp_set_mat_row(lp_, MPSolverIndexToGlpkIndex(constraint->index()), k - 1,
448 void GLPKInterface::ExtractNewConstraints() {
449 int total_num_rows = solver_->constraints_.size();
450 if (last_constraint_index_ < total_num_rows) {
452 glp_add_rows(lp_, total_num_rows - last_constraint_index_);
454 for (
int i = last_constraint_index_; i < total_num_rows; ++i) {
455 MPConstraint*
ct = solver_->constraints_[i];
456 set_constraint_as_extracted(i,
true);
457 if (
ct->name().empty()) {
458 glp_set_row_name(lp_, MPSolverIndexToGlpkIndex(i),
459 absl::StrFormat(
"ct_%i", i).c_str());
461 glp_set_row_name(lp_, MPSolverIndexToGlpkIndex(i),
ct->name().c_str());
464 SetConstraintBounds(i,
ct->lb(),
ct->ub());
465 num_coefs +=
ct->coefficients_.size();
469 if (last_variable_index_ == 0 && last_constraint_index_ == 0) {
476 std::unique_ptr<int[]> variable_indices(
new int[num_coefs + 1]);
477 std::unique_ptr<int[]> constraint_indices(
new int[num_coefs + 1]);
478 std::unique_ptr<double[]> coefs(
new double[num_coefs + 1]);
480 for (
int i = 0; i < solver_->constraints_.size(); ++i) {
481 MPConstraint*
ct = solver_->constraints_[i];
482 for (
const auto& entry :
ct->coefficients_) {
483 DCHECK(variable_is_extracted(entry.first->index()));
484 constraint_indices[k] = MPSolverIndexToGlpkIndex(
ct->index());
485 variable_indices[k] = MPSolverIndexToGlpkIndex(entry.first->index());
486 coefs[k] = entry.second;
490 CHECK_EQ(num_coefs + 1, k);
491 glp_load_matrix(lp_, num_coefs, constraint_indices.get(),
492 variable_indices.get(), coefs.get());
495 int max_constraint_size = solver_->ComputeMaxConstraintSize(
496 last_constraint_index_, total_num_rows);
499 std::unique_ptr<int[]> indices(
new int[max_constraint_size + 1]);
500 std::unique_ptr<double[]> coefs(
new double[max_constraint_size + 1]);
501 for (
int i = last_constraint_index_; i < total_num_rows; i++) {
502 ExtractOneConstraint(solver_->constraints_[i], indices.get(),
509 void GLPKInterface::ExtractObjective() {
512 for (
const auto& entry : solver_->objective_->coefficients_) {
513 glp_set_obj_coef(lp_, MPSolverIndexToGlpkIndex(entry.first->index()),
517 glp_set_obj_coef(lp_, 0, solver_->Objective().offset());
526 if (param.GetIntegerParam(MPSolverParameters::INCREMENTALITY) ==
527 MPSolverParameters::INCREMENTALITY_OFF) {
533 glp_term_out(GLP_OFF);
535 glp_term_out(GLP_ON);
539 VLOG(1) << absl::StrFormat(
"Model built in %.3f seconds.", timer.
Get());
544 ConfigureGLPKParameters(param);
548 int solver_status = glp_simplex(lp_, &lp_param_);
552 if (solver_status == 0) {
553 solver_status = glp_intopt(lp_, &mip_param_);
560 if (solver_status == GLP_ETMLIM) {
563 sync_status_ = SOLUTION_SYNCHRONIZED;
564 return result_status_;
567 VLOG(1) << absl::StrFormat(
"GLPK Status: %i (time spent: %.3f seconds).",
568 solver_status, timer.
Get());
572 objective_value_ = glp_mip_obj_val(lp_);
573 best_objective_bound_ = mip_callback_info_->best_objective_bound_;
575 objective_value_ = glp_get_obj_val(lp_);
577 VLOG(1) <<
"objective=" << objective_value_
578 <<
", bound=" << best_objective_bound_;
579 for (
int i = 0; i < solver_->variables_.size(); ++i) {
580 MPVariable*
const var = solver_->variables_[i];
583 val = glp_mip_col_val(lp_, MPSolverIndexToGlpkIndex(i));
585 val = glp_get_col_prim(lp_, MPSolverIndexToGlpkIndex(i));
587 var->set_solution_value(val);
588 VLOG(3) <<
var->name() <<
": value =" << val;
591 reduced_cost = glp_get_col_dual(lp_, MPSolverIndexToGlpkIndex(i));
592 var->set_reduced_cost(reduced_cost);
593 VLOG(4) <<
var->name() <<
": reduced cost = " << reduced_cost;
596 for (
int i = 0; i < solver_->constraints_.size(); ++i) {
597 MPConstraint*
const ct = solver_->constraints_[i];
599 const double dual_value =
600 glp_get_row_dual(lp_, MPSolverIndexToGlpkIndex(i));
601 ct->set_dual_value(dual_value);
602 VLOG(4) <<
"row " << MPSolverIndexToGlpkIndex(i)
603 <<
": dual value = " << dual_value;
609 int tmp_status = glp_mip_status(lp_);
610 VLOG(1) <<
"GLPK result status: " << tmp_status;
611 if (tmp_status == GLP_OPT) {
613 }
else if (tmp_status == GLP_FEAS) {
615 }
else if (tmp_status == GLP_NOFEAS) {
620 }
else if (solver_status == GLP_ETMLIM) {
628 int tmp_status = glp_get_status(lp_);
629 VLOG(1) <<
"GLPK result status: " << tmp_status;
630 if (tmp_status == GLP_OPT) {
632 }
else if (tmp_status == GLP_FEAS) {
634 }
else if (tmp_status == GLP_NOFEAS || tmp_status == GLP_INFEAS) {
639 }
else if (tmp_status == GLP_UNBND) {
644 }
else if (solver_status == GLP_ETMLIM) {
651 sync_status_ = SOLUTION_SYNCHRONIZED;
653 return result_status_;
657 int glpk_basis_status)
const {
658 switch (glpk_basis_status) {
660 return MPSolver::BASIC;
662 return MPSolver::AT_LOWER_BOUND;
664 return MPSolver::AT_UPPER_BOUND;
666 return MPSolver::FREE;
668 return MPSolver::FIXED_VALUE;
670 LOG(FATAL) <<
"Unknown GLPK basis status";
671 return MPSolver::FREE;
677 int64_t GLPKInterface::iterations()
const {
678 #if GLP_MAJOR_VERSION == 4 && GLP_MINOR_VERSION < 49
679 if (!mip_ && CheckSolutionIsSynchronized()) {
680 return lpx_get_int_parm(lp_, LPX_K_ITCNT);
682 #elif (GLP_MAJOR_VERSION == 4 && GLP_MINOR_VERSION >= 53) || \
683 GLP_MAJOR_VERSION >= 5
684 if (!mip_ && CheckSolutionIsSynchronized()) {
685 return glp_get_it_cnt(lp_);
688 LOG(WARNING) <<
"Total number of iterations is not available";
689 return kUnknownNumberOfIterations;
694 if (!CheckSolutionIsSynchronized())
return kUnknownNumberOfNodes;
695 return mip_callback_info_->num_all_nodes_;
697 LOG(DFATAL) <<
"Number of nodes only available for discrete problems";
698 return kUnknownNumberOfNodes;
703 DCHECK_GE(constraint_index, 0);
704 DCHECK_LT(constraint_index, last_constraint_index_);
705 const int glpk_basis_status =
706 glp_get_row_stat(lp_, MPSolverIndexToGlpkIndex(constraint_index));
707 return TransformGLPKBasisStatus(glpk_basis_status);
711 DCHECK_GE(variable_index, 0);
712 DCHECK_LT(variable_index, last_variable_index_);
713 const int glpk_basis_status =
714 glp_get_col_stat(lp_, MPSolverIndexToGlpkIndex(variable_index));
715 return TransformGLPKBasisStatus(glpk_basis_status);
718 bool GLPKInterface::CheckSolutionExists()
const {
720 LOG(WARNING) <<
"Ignoring ABNORMAL status from GLPK: This status may or may"
721 <<
" not indicate that a solution exists.";
725 return MPSolverInterface::CheckSolutionExists();
729 double GLPKInterface::ComputeExactConditionNumber()
const {
730 if (!IsContinuous()) {
732 LOG(DFATAL) <<
"ComputeExactConditionNumber not implemented for"
733 <<
" GLPK_MIXED_INTEGER_PROGRAMMING";
736 if (!CheckSolutionIsSynchronized())
return 0.0;
739 CheckSolutionExists();
740 const int num_rows = glp_get_num_rows(lp_);
741 const int num_cols = glp_get_num_cols(lp_);
743 std::unique_ptr<double[]> row_scaling_factor(
new double[num_rows + 1]);
744 std::unique_ptr<double[]> column_scaling_factor(
new double[num_cols + 1]);
745 for (
int row = 1;
row <= num_rows; ++
row) {
746 row_scaling_factor[
row] = glp_get_rii(lp_,
row);
748 for (
int col = 1;
col <= num_cols; ++
col) {
749 column_scaling_factor[
col] = glp_get_sjj(lp_,
col);
751 return ComputeInverseScaledBasisL1Norm(num_rows, num_cols,
752 row_scaling_factor.get(),
753 column_scaling_factor.get()) *
754 ComputeScaledBasisL1Norm(num_rows, num_cols, row_scaling_factor.get(),
755 column_scaling_factor.get());
758 double GLPKInterface::ComputeScaledBasisL1Norm(
759 int num_rows,
int num_cols,
double* row_scaling_factor,
760 double* column_scaling_factor)
const {
762 std::unique_ptr<double[]> values(
new double[num_rows + 1]);
763 std::unique_ptr<int[]> indices(
new int[num_rows + 1]);
764 for (
int col = 1;
col <= num_cols; ++
col) {
765 const int glpk_basis_status = glp_get_col_stat(lp_,
col);
767 if (glpk_basis_status == GLP_BS) {
769 const int num_nz = glp_get_mat_col(lp_,
col, indices.get(), values.get());
770 double column_norm = 0.0;
771 for (
int k = 1; k <= num_nz; k++) {
772 column_norm += fabs(values[k] * row_scaling_factor[indices[k]]);
774 column_norm *= fabs(column_scaling_factor[
col]);
780 for (
int row = 1;
row <= num_rows; ++
row) {
781 const int glpk_basis_status = glp_get_row_stat(lp_,
row);
783 if (glpk_basis_status == GLP_BS) {
787 const double column_norm = fabs(row_scaling_factor[
row]);
795 double GLPKInterface::ComputeInverseScaledBasisL1Norm(
796 int num_rows,
int num_cols,
double* row_scaling_factor,
797 double* column_scaling_factor)
const {
799 if (!glp_bf_exists(lp_)) {
800 const int factorize_status = glp_factorize(lp_);
801 switch (factorize_status) {
803 LOG(FATAL) <<
"Not able to factorize: error GLP_EBADB.";
808 <<
"Not able to factorize: "
809 <<
"the basis matrix is singular within the working precision.";
810 return MPSolver::infinity();
814 <<
"Not able to factorize: the basis matrix is ill-conditioned.";
815 return MPSolver::infinity();
821 std::unique_ptr<double[]> right_hand_side(
new double[num_rows + 1]);
835 for (
int k = 1; k <= num_rows; ++k) {
836 for (
int row = 1;
row <= num_rows; ++
row) {
837 right_hand_side[
row] = 0.0;
839 right_hand_side[k] = 1.0;
841 for (
int row = 1;
row <= num_rows; ++
row) {
842 right_hand_side[
row] /= row_scaling_factor[
row];
844 glp_ftran(lp_, right_hand_side.get());
848 for (
int row = 1;
row <= num_rows; ++
row) {
849 const int k = glp_get_bhead(lp_,
row);
852 right_hand_side[
row] *= row_scaling_factor[k];
855 right_hand_side[
row] /= column_scaling_factor[k - num_rows];
859 double column_norm = 0.0;
860 for (
int row = 1;
row <= num_rows; ++
row) {
861 column_norm += fabs(right_hand_side[
row]);
871 void GLPKInterface::ConfigureGLPKParameters(
const MPSolverParameters& param) {
873 glp_init_iocp(&mip_param_);
875 if (solver_->time_limit()) {
876 VLOG(1) <<
"Setting time limit = " << solver_->time_limit() <<
" ms.";
877 mip_param_.tm_lim = solver_->time_limit();
880 mip_param_.cb_func = GLPKGatherInformationCallback;
882 mip_param_.cb_info = mip_callback_info_.get();
888 glp_init_smcp(&lp_param_);
890 if (solver_->time_limit()) {
891 VLOG(1) <<
"Setting time limit = " << solver_->time_limit() <<
" ms.";
892 lp_param_.tm_lim = solver_->time_limit();
896 glp_scale_prob(lp_, GLP_SF_AUTO);
899 glp_adv_basis(lp_, 0);
902 SetParameters(param);
905 void GLPKInterface::SetParameters(
const MPSolverParameters& param) {
906 SetCommonParameters(param);
908 SetMIPParameters(param);
912 void GLPKInterface::SetRelativeMipGap(
double value) {
914 mip_param_.mip_gap =
value;
916 LOG(WARNING) <<
"The relative MIP gap is only available "
917 <<
"for discrete problems.";
921 void GLPKInterface::SetPrimalTolerance(
double value) {
922 lp_param_.tol_bnd =
value;
925 void GLPKInterface::SetDualTolerance(
double value) { lp_param_.tol_dj =
value; }
927 void GLPKInterface::SetPresolveMode(
int value) {
929 case MPSolverParameters::PRESOLVE_OFF: {
930 mip_param_.presolve = GLP_OFF;
931 lp_param_.presolve = GLP_OFF;
934 case MPSolverParameters::PRESOLVE_ON: {
935 mip_param_.presolve = GLP_ON;
936 lp_param_.presolve = GLP_ON;
940 SetIntegerParamToUnsupportedValue(MPSolverParameters::PRESOLVE,
value);
945 void GLPKInterface::SetScalingMode(
int value) {
946 SetUnsupportedIntegerParam(MPSolverParameters::SCALING);
949 void GLPKInterface::SetLpAlgorithm(
int value) {
951 case MPSolverParameters::DUAL: {
953 lp_param_.meth = GLP_DUALP;
956 case MPSolverParameters::PRIMAL: {
957 lp_param_.meth = GLP_PRIMAL;
960 case MPSolverParameters::BARRIER:
962 SetIntegerParamToUnsupportedValue(MPSolverParameters::LP_ALGORITHM,
968 MPSolverInterface* BuildGLPKInterface(
bool mip, MPSolver*
const solver) {
969 return new GLPKInterface(solver, mip);
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.
void SetupGlpkEnvAutomaticDeletion()
#define VLOG(verboselevel)