27#include "absl/memory/memory.h"
28#include "absl/strings/str_format.h"
34#include "ortools/glpk/glpk_env_deleter.h"
43class GLPKInformation {
45 explicit GLPKInformation(
bool maximize) : num_all_nodes_(0) {
46 ResetBestObjectiveBound(maximize);
48 void Reset(
bool maximize) {
50 ResetBestObjectiveBound(maximize);
52 void ResetBestObjectiveBound(
bool maximize) {
54 best_objective_bound_ = std::numeric_limits<double>::infinity();
56 best_objective_bound_ = -std::numeric_limits<double>::infinity();
60 double best_objective_bound_;
64void GLPKGatherInformationCallback(glp_tree* tree,
void* info) {
65 CHECK(tree !=
nullptr);
66 CHECK(info !=
nullptr);
67 GLPKInformation* glpk_info =
reinterpret_cast<GLPKInformation*
>(info);
68 switch (glp_ios_reason(tree)) {
75 glp_ios_tree_size(tree,
nullptr,
nullptr, &glpk_info->num_all_nodes_);
77 int node_id = glp_ios_best_node(tree);
79 glpk_info->best_objective_bound_ = glp_ios_node_bound(tree, node_id);
92int MPSolverIndexToGlpkIndex(
int index) {
return index + 1; }
95class GLPKInterface :
public MPSolverInterface {
98 GLPKInterface(MPSolver*
const solver,
bool mip);
99 ~GLPKInterface()
override;
102 void SetOptimizationDirection(
bool maximize)
override;
110 void Reset()
override;
113 void SetVariableBounds(
int mpsolver_var_index,
double lb,
double ub)
override;
114 void SetVariableInteger(
int mpsolver_var_index,
bool integer)
override;
115 void SetConstraintBounds(
int mpsolver_constraint_index,
double lb,
119 void AddRowConstraint(MPConstraint*
const ct)
override;
121 void AddVariable(MPVariable*
const var)
override;
123 void SetCoefficient(MPConstraint*
const constraint,
124 const MPVariable*
const variable,
double new_value,
125 double old_value)
override;
127 void ClearConstraint(MPConstraint*
const constraint)
override;
129 void SetObjectiveCoefficient(
const MPVariable*
const variable,
132 void SetObjectiveOffset(
double value)
override;
134 void ClearObjective()
override;
138 int64_t iterations()
const override;
140 int64_t
nodes()
const override;
148 bool CheckSolutionExists()
const override;
152 bool IsContinuous()
const override {
return IsLP(); }
153 bool IsLP()
const override {
return !mip_; }
154 bool IsMIP()
const override {
return mip_; }
156 void ExtractNewVariables()
override;
157 void ExtractNewConstraints()
override;
158 void ExtractObjective()
override;
160 std::string SolverVersion()
const override {
161 return absl::StrFormat(
"GLPK %s", glp_version());
164 void* underlying_solver()
override {
return reinterpret_cast<void*
>(lp_); }
166 double ComputeExactConditionNumber()
const override;
170 void ConfigureGLPKParameters(
const MPSolverParameters& param);
173 void SetParameters(
const MPSolverParameters& param)
override;
175 void SetRelativeMipGap(
double value)
override;
176 void SetPrimalTolerance(
double value)
override;
177 void SetDualTolerance(
double value)
override;
178 void SetPresolveMode(
int value)
override;
179 void SetScalingMode(
int value)
override;
180 void SetLpAlgorithm(
int value)
override;
182 void ExtractOldConstraints();
183 void ExtractOneConstraint(MPConstraint*
const constraint,
int*
const indices,
184 double*
const coefs);
191 double ComputeScaledBasisL1Norm(
int num_rows,
int num_cols,
192 double* row_scaling_factor,
193 double* column_scaling_factor)
const;
198 double ComputeInverseScaledBasisL1Norm(
int num_rows,
int num_cols,
199 double* row_scaling_factor,
200 double* column_scaling_factor)
const;
209 std::unique_ptr<GLPKInformation> mip_callback_info_;
213GLPKInterface::GLPKInterface(MPSolver*
const solver,
bool mip)
214 : MPSolverInterface(solver), lp_(nullptr), mip_(mip) {
216 SetupGlpkEnvAutomaticDeletion();
218 lp_ = glp_create_prob();
219 glp_set_prob_name(lp_, solver_->name_.c_str());
220 glp_set_obj_dir(lp_, GLP_MIN);
221 mip_callback_info_ = absl::make_unique<GLPKInformation>(
maximize_);
225GLPKInterface::~GLPKInterface() {
226 CHECK(lp_ !=
nullptr);
227 glp_delete_prob(lp_);
231void GLPKInterface::Reset() {
232 CHECK(lp_ !=
nullptr);
233 glp_delete_prob(lp_);
234 lp_ = glp_create_prob();
235 glp_set_prob_name(lp_, solver_->name_.c_str());
236 glp_set_obj_dir(lp_,
maximize_ ? GLP_MAX : GLP_MIN);
237 ResetExtractionInformation();
243void GLPKInterface::SetOptimizationDirection(
bool maximize) {
244 InvalidateSolutionSynchronization();
245 glp_set_obj_dir(lp_, maximize ? GLP_MAX : GLP_MIN);
248void GLPKInterface::SetVariableBounds(
int mpsolver_var_index,
double lb,
250 InvalidateSolutionSynchronization();
251 if (!variable_is_extracted(mpsolver_var_index)) {
252 sync_status_ = MUST_RELOAD;
257 const double infinity = solver_->infinity();
258 const int glpk_var_index = MPSolverIndexToGlpkIndex(mpsolver_var_index);
259 if (lb != -infinity) {
260 if (ub != infinity) {
262 glp_set_col_bnds(lp_, glpk_var_index, GLP_FX, lb, ub);
264 glp_set_col_bnds(lp_, glpk_var_index, GLP_DB, lb, ub);
267 glp_set_col_bnds(lp_, glpk_var_index, GLP_LO, lb, 0.0);
269 }
else if (ub != infinity) {
270 glp_set_col_bnds(lp_, glpk_var_index, GLP_UP, 0.0, ub);
272 glp_set_col_bnds(lp_, glpk_var_index, GLP_FR, 0.0, 0.0);
276void GLPKInterface::SetVariableInteger(
int mpsolver_var_index,
bool integer) {
277 InvalidateSolutionSynchronization();
279 if (variable_is_extracted(mpsolver_var_index)) {
281 glp_set_col_kind(lp_, MPSolverIndexToGlpkIndex(mpsolver_var_index),
282 integer ? GLP_IV : GLP_CV);
284 sync_status_ = MUST_RELOAD;
289void GLPKInterface::SetConstraintBounds(
int mpsolver_constraint_index,
290 double lb,
double ub) {
291 InvalidateSolutionSynchronization();
292 if (!constraint_is_extracted(mpsolver_constraint_index)) {
293 sync_status_ = MUST_RELOAD;
297 const int glpk_constraint_index =
298 MPSolverIndexToGlpkIndex(mpsolver_constraint_index);
300 const double infinity = solver_->infinity();
301 if (lb != -infinity) {
302 if (ub != infinity) {
304 glp_set_row_bnds(lp_, glpk_constraint_index, GLP_FX, lb, ub);
306 glp_set_row_bnds(lp_, glpk_constraint_index, GLP_DB, lb, ub);
309 glp_set_row_bnds(lp_, glpk_constraint_index, GLP_LO, lb, 0.0);
311 }
else if (ub != infinity) {
312 glp_set_row_bnds(lp_, glpk_constraint_index, GLP_UP, 0.0, ub);
314 glp_set_row_bnds(lp_, glpk_constraint_index, GLP_FR, 0.0, 0.0);
318void GLPKInterface::SetCoefficient(MPConstraint*
const constraint,
319 const MPVariable*
const variable,
320 double new_value,
double old_value) {
321 InvalidateSolutionSynchronization();
326 if (constraint_is_extracted(constraint->index()) &&
327 (sync_status_ == MODEL_SYNCHRONIZED ||
328 !constraint->ContainsNewVariables())) {
329 const int size = constraint->coefficients_.size();
330 std::unique_ptr<int[]> indices(
new int[size + 1]);
331 std::unique_ptr<double[]> coefs(
new double[size + 1]);
332 ExtractOneConstraint(constraint, indices.get(), coefs.get());
337void GLPKInterface::ClearConstraint(MPConstraint*
const constraint) {
338 InvalidateSolutionSynchronization();
340 if (constraint_is_extracted(constraint->index())) {
341 glp_set_mat_row(lp_, MPSolverIndexToGlpkIndex(constraint->index()), 0,
347void GLPKInterface::SetObjectiveCoefficient(
const MPVariable*
const variable,
349 sync_status_ = MUST_RELOAD;
353void GLPKInterface::SetObjectiveOffset(
double value) {
354 sync_status_ = MUST_RELOAD;
358void GLPKInterface::ClearObjective() {
359 InvalidateSolutionSynchronization();
360 for (
const auto& entry : solver_->objective_->coefficients_) {
361 const int mpsolver_var_index = entry.first->index();
363 if (!variable_is_extracted(mpsolver_var_index)) {
364 DCHECK_NE(MODEL_SYNCHRONIZED, sync_status_);
366 glp_set_obj_coef(lp_, MPSolverIndexToGlpkIndex(mpsolver_var_index), 0.0);
370 glp_set_obj_coef(lp_, 0, 0.0);
373void GLPKInterface::AddRowConstraint(MPConstraint*
const ct) {
374 sync_status_ = MUST_RELOAD;
377void GLPKInterface::AddVariable(MPVariable*
const var) {
378 sync_status_ = MUST_RELOAD;
382void GLPKInterface::ExtractNewVariables() {
383 int total_num_vars = solver_->variables_.size();
384 if (total_num_vars > last_variable_index_) {
385 glp_add_cols(lp_, total_num_vars - last_variable_index_);
386 for (
int j = last_variable_index_; j < solver_->variables_.size(); ++j) {
387 MPVariable*
const var = solver_->variables_[j];
388 set_variable_as_extracted(j,
true);
389 if (!
var->name().empty()) {
390 glp_set_col_name(lp_, MPSolverIndexToGlpkIndex(j),
var->name().c_str());
392 SetVariableBounds(j,
var->lb(),
var->ub());
393 SetVariableInteger(j,
var->integer());
396 double tmp_obj_coef = 0.0;
397 glp_set_obj_coef(lp_, MPSolverIndexToGlpkIndex(j), tmp_obj_coef);
400 ExtractOldConstraints();
405void GLPKInterface::ExtractOldConstraints() {
406 const int max_constraint_size =
407 solver_->ComputeMaxConstraintSize(0, last_constraint_index_);
410 std::unique_ptr<int[]> indices(
new int[max_constraint_size + 1]);
411 std::unique_ptr<double[]> coefs(
new double[max_constraint_size + 1]);
413 for (
int i = 0; i < last_constraint_index_; ++i) {
414 MPConstraint*
const ct = solver_->constraints_[i];
415 DCHECK(constraint_is_extracted(i));
416 const int size =
ct->coefficients_.size();
421 if (
ct->ContainsNewVariables()) {
422 ExtractOneConstraint(
ct, indices.get(), coefs.get());
430void GLPKInterface::ExtractOneConstraint(MPConstraint*
const constraint,
432 double*
const coefs) {
435 for (
const auto& entry : constraint->coefficients_) {
436 DCHECK(variable_is_extracted(entry.first->index()));
437 indices[k] = MPSolverIndexToGlpkIndex(entry.first->index());
438 coefs[k] = entry.second;
441 glp_set_mat_row(lp_, MPSolverIndexToGlpkIndex(constraint->index()), k - 1,
446void GLPKInterface::ExtractNewConstraints() {
447 int total_num_rows = solver_->constraints_.size();
448 if (last_constraint_index_ < total_num_rows) {
450 glp_add_rows(lp_, total_num_rows - last_constraint_index_);
452 for (
int i = last_constraint_index_; i < total_num_rows; ++i) {
453 MPConstraint*
ct = solver_->constraints_[i];
454 set_constraint_as_extracted(i,
true);
455 if (
ct->name().empty()) {
456 glp_set_row_name(lp_, MPSolverIndexToGlpkIndex(i),
457 absl::StrFormat(
"ct_%i", i).c_str());
459 glp_set_row_name(lp_, MPSolverIndexToGlpkIndex(i),
ct->name().c_str());
462 SetConstraintBounds(i,
ct->lb(),
ct->ub());
463 num_coefs +=
ct->coefficients_.size();
467 if (last_variable_index_ == 0 && last_constraint_index_ == 0) {
474 std::unique_ptr<int[]> variable_indices(
new int[num_coefs + 1]);
475 std::unique_ptr<int[]> constraint_indices(
new int[num_coefs + 1]);
476 std::unique_ptr<double[]> coefs(
new double[num_coefs + 1]);
478 for (
int i = 0; i < solver_->constraints_.size(); ++i) {
479 MPConstraint*
ct = solver_->constraints_[i];
480 for (
const auto& entry :
ct->coefficients_) {
481 DCHECK(variable_is_extracted(entry.first->index()));
482 constraint_indices[k] = MPSolverIndexToGlpkIndex(
ct->index());
483 variable_indices[k] = MPSolverIndexToGlpkIndex(entry.first->index());
484 coefs[k] = entry.second;
489 glp_load_matrix(lp_, num_coefs, constraint_indices.get(),
490 variable_indices.get(), coefs.get());
493 int max_constraint_size = solver_->ComputeMaxConstraintSize(
494 last_constraint_index_, total_num_rows);
497 std::unique_ptr<int[]> indices(
new int[max_constraint_size + 1]);
498 std::unique_ptr<double[]> coefs(
new double[max_constraint_size + 1]);
499 for (
int i = last_constraint_index_; i < total_num_rows; i++) {
500 ExtractOneConstraint(solver_->constraints_[i], indices.get(),
507void GLPKInterface::ExtractObjective() {
510 for (
const auto& entry : solver_->objective_->coefficients_) {
511 glp_set_obj_coef(lp_, MPSolverIndexToGlpkIndex(entry.first->index()),
515 glp_set_obj_coef(lp_, 0, solver_->Objective().offset());
524 if (param.GetIntegerParam(MPSolverParameters::INCREMENTALITY) ==
525 MPSolverParameters::INCREMENTALITY_OFF) {
531 glp_term_out(GLP_OFF);
533 glp_term_out(GLP_ON);
537 VLOG(1) << absl::StrFormat(
"Model built in %.3f seconds.", timer.
Get());
542 ConfigureGLPKParameters(param);
546 int solver_status = glp_simplex(lp_, &lp_param_);
550 if (solver_status == 0) {
551 solver_status = glp_intopt(lp_, &mip_param_);
557 result_status_ = MPSolver::ABNORMAL;
558 if (solver_status == GLP_ETMLIM) {
559 result_status_ = MPSolver::NOT_SOLVED;
561 sync_status_ = SOLUTION_SYNCHRONIZED;
562 return result_status_;
565 VLOG(1) << absl::StrFormat(
"GLPK Status: %i (time spent: %.3f seconds).",
566 solver_status, timer.
Get());
570 objective_value_ = glp_mip_obj_val(lp_);
571 best_objective_bound_ = mip_callback_info_->best_objective_bound_;
573 objective_value_ = glp_get_obj_val(lp_);
575 VLOG(1) <<
"objective=" << objective_value_
576 <<
", bound=" << best_objective_bound_;
577 for (
int i = 0; i < solver_->variables_.size(); ++i) {
578 MPVariable*
const var = solver_->variables_[i];
581 val = glp_mip_col_val(lp_, MPSolverIndexToGlpkIndex(i));
583 val = glp_get_col_prim(lp_, MPSolverIndexToGlpkIndex(i));
585 var->set_solution_value(val);
586 VLOG(3) <<
var->name() <<
": value =" << val;
589 reduced_cost = glp_get_col_dual(lp_, MPSolverIndexToGlpkIndex(i));
590 var->set_reduced_cost(reduced_cost);
591 VLOG(4) <<
var->name() <<
": reduced cost = " << reduced_cost;
594 for (
int i = 0; i < solver_->constraints_.size(); ++i) {
595 MPConstraint*
const ct = solver_->constraints_[i];
597 const double dual_value =
598 glp_get_row_dual(lp_, MPSolverIndexToGlpkIndex(i));
599 ct->set_dual_value(dual_value);
600 VLOG(4) <<
"row " << MPSolverIndexToGlpkIndex(i)
601 <<
": dual value = " << dual_value;
607 int tmp_status = glp_mip_status(lp_);
608 VLOG(1) <<
"GLPK result status: " << tmp_status;
609 if (tmp_status == GLP_OPT) {
611 }
else if (tmp_status == GLP_FEAS) {
613 }
else if (tmp_status == GLP_NOFEAS) {
618 }
else if (solver_status == GLP_ETMLIM) {
619 result_status_ = MPSolver::NOT_SOLVED;
621 result_status_ = MPSolver::ABNORMAL;
626 int tmp_status = glp_get_status(lp_);
627 VLOG(1) <<
"GLPK result status: " << tmp_status;
628 if (tmp_status == GLP_OPT) {
630 }
else if (tmp_status == GLP_FEAS) {
632 }
else if (tmp_status == GLP_NOFEAS || tmp_status == GLP_INFEAS) {
637 }
else if (tmp_status == GLP_UNBND) {
641 result_status_ = MPSolver::UNBOUNDED;
642 }
else if (solver_status == GLP_ETMLIM) {
643 result_status_ = MPSolver::NOT_SOLVED;
645 result_status_ = MPSolver::ABNORMAL;
649 sync_status_ = SOLUTION_SYNCHRONIZED;
651 return result_status_;
654MPSolver::BasisStatus GLPKInterface::TransformGLPKBasisStatus(
655 int glpk_basis_status)
const {
656 switch (glpk_basis_status) {
658 return MPSolver::BASIC;
660 return MPSolver::AT_LOWER_BOUND;
662 return MPSolver::AT_UPPER_BOUND;
664 return MPSolver::FREE;
666 return MPSolver::FIXED_VALUE;
668 LOG(
FATAL) <<
"Unknown GLPK basis status";
669 return MPSolver::FREE;
675int64_t GLPKInterface::iterations()
const {
676#if GLP_MAJOR_VERSION == 4 && GLP_MINOR_VERSION < 49
677 if (!mip_ && CheckSolutionIsSynchronized()) {
678 return lpx_get_int_parm(lp_, LPX_K_ITCNT);
680#elif (GLP_MAJOR_VERSION == 4 && GLP_MINOR_VERSION >= 53) || \
681 GLP_MAJOR_VERSION >= 5
682 if (!mip_ && CheckSolutionIsSynchronized()) {
683 return glp_get_it_cnt(lp_);
686 LOG(
WARNING) <<
"Total number of iterations is not available";
687 return kUnknownNumberOfIterations;
692 if (!CheckSolutionIsSynchronized())
return kUnknownNumberOfNodes;
693 return mip_callback_info_->num_all_nodes_;
695 LOG(DFATAL) <<
"Number of nodes only available for discrete problems";
696 return kUnknownNumberOfNodes;
700MPSolver::BasisStatus GLPKInterface::row_status(
int constraint_index)
const {
702 DCHECK_LT(constraint_index, last_constraint_index_);
703 const int glpk_basis_status =
704 glp_get_row_stat(lp_, MPSolverIndexToGlpkIndex(constraint_index));
705 return TransformGLPKBasisStatus(glpk_basis_status);
708MPSolver::BasisStatus GLPKInterface::column_status(
int variable_index)
const {
710 DCHECK_LT(variable_index, last_variable_index_);
711 const int glpk_basis_status =
712 glp_get_col_stat(lp_, MPSolverIndexToGlpkIndex(variable_index));
713 return TransformGLPKBasisStatus(glpk_basis_status);
716bool GLPKInterface::CheckSolutionExists()
const {
717 if (result_status_ == MPSolver::ABNORMAL) {
718 LOG(
WARNING) <<
"Ignoring ABNORMAL status from GLPK: This status may or may"
719 <<
" not indicate that a solution exists.";
723 return MPSolverInterface::CheckSolutionExists();
727double GLPKInterface::ComputeExactConditionNumber()
const {
728 if (!IsContinuous()) {
730 LOG(DFATAL) <<
"ComputeExactConditionNumber not implemented for"
731 <<
" GLPK_MIXED_INTEGER_PROGRAMMING";
734 if (!CheckSolutionIsSynchronized())
return 0.0;
737 CheckSolutionExists();
738 const int num_rows = glp_get_num_rows(lp_);
739 const int num_cols = glp_get_num_cols(lp_);
741 std::unique_ptr<double[]> row_scaling_factor(
new double[num_rows + 1]);
742 std::unique_ptr<double[]> column_scaling_factor(
new double[num_cols + 1]);
743 for (
int row = 1;
row <= num_rows; ++
row) {
744 row_scaling_factor[
row] = glp_get_rii(lp_,
row);
746 for (
int col = 1;
col <= num_cols; ++
col) {
747 column_scaling_factor[
col] = glp_get_sjj(lp_,
col);
749 return ComputeInverseScaledBasisL1Norm(num_rows, num_cols,
750 row_scaling_factor.get(),
751 column_scaling_factor.get()) *
752 ComputeScaledBasisL1Norm(num_rows, num_cols, row_scaling_factor.get(),
753 column_scaling_factor.get());
756double GLPKInterface::ComputeScaledBasisL1Norm(
757 int num_rows,
int num_cols,
double* row_scaling_factor,
758 double* column_scaling_factor)
const {
760 std::unique_ptr<double[]> values(
new double[num_rows + 1]);
761 std::unique_ptr<int[]> indices(
new int[num_rows + 1]);
762 for (
int col = 1;
col <= num_cols; ++
col) {
763 const int glpk_basis_status = glp_get_col_stat(lp_,
col);
765 if (glpk_basis_status == GLP_BS) {
767 const int num_nz = glp_get_mat_col(lp_,
col, indices.get(), values.get());
768 double column_norm = 0.0;
769 for (
int k = 1; k <= num_nz; k++) {
770 column_norm += fabs(values[k] * row_scaling_factor[indices[k]]);
772 column_norm *= fabs(column_scaling_factor[
col]);
778 for (
int row = 1;
row <= num_rows; ++
row) {
779 const int glpk_basis_status = glp_get_row_stat(lp_,
row);
781 if (glpk_basis_status == GLP_BS) {
785 const double column_norm = fabs(row_scaling_factor[
row]);
793double GLPKInterface::ComputeInverseScaledBasisL1Norm(
794 int num_rows,
int num_cols,
double* row_scaling_factor,
795 double* column_scaling_factor)
const {
797 if (!glp_bf_exists(lp_)) {
798 const int factorize_status = glp_factorize(lp_);
799 switch (factorize_status) {
801 LOG(
FATAL) <<
"Not able to factorize: error GLP_EBADB.";
806 <<
"Not able to factorize: "
807 <<
"the basis matrix is singular within the working precision.";
808 return MPSolver::infinity();
812 <<
"Not able to factorize: the basis matrix is ill-conditioned.";
813 return MPSolver::infinity();
819 std::unique_ptr<double[]> right_hand_side(
new double[num_rows + 1]);
833 for (
int k = 1; k <= num_rows; ++k) {
834 for (
int row = 1;
row <= num_rows; ++
row) {
835 right_hand_side[
row] = 0.0;
837 right_hand_side[k] = 1.0;
839 for (
int row = 1;
row <= num_rows; ++
row) {
840 right_hand_side[
row] /= row_scaling_factor[
row];
842 glp_ftran(lp_, right_hand_side.get());
846 for (
int row = 1;
row <= num_rows; ++
row) {
847 const int k = glp_get_bhead(lp_,
row);
850 right_hand_side[
row] *= row_scaling_factor[k];
853 right_hand_side[
row] /= column_scaling_factor[k - num_rows];
857 double column_norm = 0.0;
858 for (
int row = 1;
row <= num_rows; ++
row) {
859 column_norm += fabs(right_hand_side[
row]);
869void GLPKInterface::ConfigureGLPKParameters(
const MPSolverParameters& param) {
871 glp_init_iocp(&mip_param_);
873 if (solver_->time_limit()) {
874 VLOG(1) <<
"Setting time limit = " << solver_->time_limit() <<
" ms.";
875 mip_param_.tm_lim = solver_->time_limit();
878 mip_param_.cb_func = GLPKGatherInformationCallback;
880 mip_param_.cb_info = mip_callback_info_.get();
886 glp_init_smcp(&lp_param_);
888 if (solver_->time_limit()) {
889 VLOG(1) <<
"Setting time limit = " << solver_->time_limit() <<
" ms.";
890 lp_param_.tm_lim = solver_->time_limit();
894 glp_scale_prob(lp_, GLP_SF_AUTO);
897 glp_adv_basis(lp_, 0);
900 SetParameters(param);
903void GLPKInterface::SetParameters(
const MPSolverParameters& param) {
904 SetCommonParameters(param);
906 SetMIPParameters(param);
910void GLPKInterface::SetRelativeMipGap(
double value) {
912 mip_param_.mip_gap =
value;
914 LOG(
WARNING) <<
"The relative MIP gap is only available "
915 <<
"for discrete problems.";
919void GLPKInterface::SetPrimalTolerance(
double value) {
920 lp_param_.tol_bnd =
value;
923void GLPKInterface::SetDualTolerance(
double value) { lp_param_.tol_dj =
value; }
925void GLPKInterface::SetPresolveMode(
int value) {
927 case MPSolverParameters::PRESOLVE_OFF: {
928 mip_param_.presolve = GLP_OFF;
929 lp_param_.presolve = GLP_OFF;
932 case MPSolverParameters::PRESOLVE_ON: {
933 mip_param_.presolve = GLP_ON;
934 lp_param_.presolve = GLP_ON;
938 SetIntegerParamToUnsupportedValue(MPSolverParameters::PRESOLVE,
value);
943void GLPKInterface::SetScalingMode(
int value) {
944 SetUnsupportedIntegerParam(MPSolverParameters::SCALING);
947void GLPKInterface::SetLpAlgorithm(
int value) {
949 case MPSolverParameters::DUAL: {
951 lp_param_.meth = GLP_DUALP;
954 case MPSolverParameters::PRIMAL: {
955 lp_param_.meth = GLP_PRIMAL;
958 case MPSolverParameters::BARRIER:
960 SetIntegerParamToUnsupportedValue(MPSolverParameters::LP_ALGORITHM,
966MPSolverInterface* BuildGLPKInterface(
bool mip, MPSolver*
const solver) {
967 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...
CpSolverResponse Solve(const CpModelProto &model_proto)
Solves the given CpModelProto and returns an instance of CpSolverResponse.
Collection of objects used to extend the Constraint Solver library.