27 #include "absl/memory/memory.h"
28 #include "absl/strings/str_format.h"
42 class GLPKInformation {
44 explicit GLPKInformation(
bool maximize) : num_all_nodes_(0) {
45 ResetBestObjectiveBound(maximize);
47 void Reset(
bool maximize) {
49 ResetBestObjectiveBound(maximize);
51 void ResetBestObjectiveBound(
bool maximize) {
53 best_objective_bound_ = std::numeric_limits<double>::infinity();
55 best_objective_bound_ = -std::numeric_limits<double>::infinity();
59 double best_objective_bound_;
63 void GLPKGatherInformationCallback(glp_tree* tree,
void* info) {
64 CHECK(tree !=
nullptr);
65 CHECK(info !=
nullptr);
66 GLPKInformation* glpk_info =
reinterpret_cast<GLPKInformation*
>(info);
67 switch (glp_ios_reason(tree)) {
74 glp_ios_tree_size(tree,
nullptr,
nullptr, &glpk_info->num_all_nodes_);
76 int node_id = glp_ios_best_node(tree);
78 glpk_info->best_objective_bound_ = glp_ios_node_bound(tree, node_id);
91 int MPSolverIndexToGlpkIndex(
int index) {
return index + 1; }
94 class GLPKInterface :
public MPSolverInterface {
97 GLPKInterface(MPSolver*
const solver,
bool mip);
98 ~GLPKInterface()
override;
101 void SetOptimizationDirection(
bool maximize)
override;
109 void Reset()
override;
112 void SetVariableBounds(
int mpsolver_var_index,
double lb,
double ub)
override;
113 void SetVariableInteger(
int mpsolver_var_index,
bool integer)
override;
114 void SetConstraintBounds(
int mpsolver_constraint_index,
double lb,
118 void AddRowConstraint(MPConstraint*
const ct)
override;
120 void AddVariable(MPVariable*
const var)
override;
122 void SetCoefficient(MPConstraint*
const constraint,
123 const MPVariable*
const variable,
double new_value,
124 double old_value)
override;
126 void ClearConstraint(MPConstraint*
const constraint)
override;
128 void SetObjectiveCoefficient(
const MPVariable*
const variable,
131 void SetObjectiveOffset(
double value)
override;
133 void ClearObjective()
override;
137 int64_t iterations()
const override;
139 int64_t
nodes()
const override;
147 bool CheckSolutionExists()
const override;
151 bool IsContinuous()
const override {
return IsLP(); }
152 bool IsLP()
const override {
return !mip_; }
153 bool IsMIP()
const override {
return mip_; }
155 void ExtractNewVariables()
override;
156 void ExtractNewConstraints()
override;
157 void ExtractObjective()
override;
159 std::string SolverVersion()
const override {
160 return absl::StrFormat(
"GLPK %s", glp_version());
163 void* underlying_solver()
override {
return reinterpret_cast<void*
>(lp_); }
165 double ComputeExactConditionNumber()
const override;
169 void ConfigureGLPKParameters(
const MPSolverParameters& param);
172 void SetParameters(
const MPSolverParameters& param)
override;
174 void SetRelativeMipGap(
double value)
override;
175 void SetPrimalTolerance(
double value)
override;
176 void SetDualTolerance(
double value)
override;
177 void SetPresolveMode(
int value)
override;
178 void SetScalingMode(
int value)
override;
179 void SetLpAlgorithm(
int value)
override;
181 void ExtractOldConstraints();
182 void ExtractOneConstraint(MPConstraint*
const constraint,
int*
const indices,
183 double*
const coefs);
190 double ComputeScaledBasisL1Norm(
int num_rows,
int num_cols,
191 double* row_scaling_factor,
192 double* column_scaling_factor)
const;
197 double ComputeInverseScaledBasisL1Norm(
int num_rows,
int num_cols,
198 double* row_scaling_factor,
199 double* column_scaling_factor)
const;
208 std::unique_ptr<GLPKInformation> mip_callback_info_;
212 GLPKInterface::GLPKInterface(MPSolver*
const solver,
bool mip)
213 : MPSolverInterface(solver), lp_(nullptr), mip_(mip) {
214 lp_ = glp_create_prob();
215 glp_set_prob_name(lp_, solver_->name_.c_str());
216 glp_set_obj_dir(lp_, GLP_MIN);
217 mip_callback_info_ = absl::make_unique<GLPKInformation>(
maximize_);
221 GLPKInterface::~GLPKInterface() {
222 CHECK(lp_ !=
nullptr);
223 glp_delete_prob(lp_);
227 void GLPKInterface::Reset() {
228 CHECK(lp_ !=
nullptr);
229 glp_delete_prob(lp_);
230 lp_ = glp_create_prob();
231 glp_set_prob_name(lp_, solver_->name_.c_str());
232 glp_set_obj_dir(lp_,
maximize_ ? GLP_MAX : GLP_MIN);
233 ResetExtractionInformation();
239 void GLPKInterface::SetOptimizationDirection(
bool maximize) {
240 InvalidateSolutionSynchronization();
241 glp_set_obj_dir(lp_, maximize ? GLP_MAX : GLP_MIN);
244 void GLPKInterface::SetVariableBounds(
int mpsolver_var_index,
double lb,
246 InvalidateSolutionSynchronization();
247 if (!variable_is_extracted(mpsolver_var_index)) {
248 sync_status_ = MUST_RELOAD;
253 const double infinity = solver_->infinity();
254 const int glpk_var_index = MPSolverIndexToGlpkIndex(mpsolver_var_index);
255 if (lb != -infinity) {
256 if (ub != infinity) {
258 glp_set_col_bnds(lp_, glpk_var_index, GLP_FX, lb, ub);
260 glp_set_col_bnds(lp_, glpk_var_index, GLP_DB, lb, ub);
263 glp_set_col_bnds(lp_, glpk_var_index, GLP_LO, lb, 0.0);
265 }
else if (ub != infinity) {
266 glp_set_col_bnds(lp_, glpk_var_index, GLP_UP, 0.0, ub);
268 glp_set_col_bnds(lp_, glpk_var_index, GLP_FR, 0.0, 0.0);
272 void GLPKInterface::SetVariableInteger(
int mpsolver_var_index,
bool integer) {
273 InvalidateSolutionSynchronization();
275 if (variable_is_extracted(mpsolver_var_index)) {
277 glp_set_col_kind(lp_, MPSolverIndexToGlpkIndex(mpsolver_var_index),
278 integer ? GLP_IV : GLP_CV);
280 sync_status_ = MUST_RELOAD;
285 void GLPKInterface::SetConstraintBounds(
int mpsolver_constraint_index,
286 double lb,
double ub) {
287 InvalidateSolutionSynchronization();
288 if (!constraint_is_extracted(mpsolver_constraint_index)) {
289 sync_status_ = MUST_RELOAD;
293 const int glpk_constraint_index =
294 MPSolverIndexToGlpkIndex(mpsolver_constraint_index);
296 const double infinity = solver_->infinity();
297 if (lb != -infinity) {
298 if (ub != infinity) {
300 glp_set_row_bnds(lp_, glpk_constraint_index, GLP_FX, lb, ub);
302 glp_set_row_bnds(lp_, glpk_constraint_index, GLP_DB, lb, ub);
305 glp_set_row_bnds(lp_, glpk_constraint_index, GLP_LO, lb, 0.0);
307 }
else if (ub != infinity) {
308 glp_set_row_bnds(lp_, glpk_constraint_index, GLP_UP, 0.0, ub);
310 glp_set_row_bnds(lp_, glpk_constraint_index, GLP_FR, 0.0, 0.0);
314 void GLPKInterface::SetCoefficient(MPConstraint*
const constraint,
315 const MPVariable*
const variable,
316 double new_value,
double old_value) {
317 InvalidateSolutionSynchronization();
322 if (constraint_is_extracted(constraint->index()) &&
323 (sync_status_ == MODEL_SYNCHRONIZED ||
324 !constraint->ContainsNewVariables())) {
325 const int size = constraint->coefficients_.size();
326 std::unique_ptr<int[]> indices(
new int[size + 1]);
327 std::unique_ptr<double[]> coefs(
new double[size + 1]);
328 ExtractOneConstraint(constraint, indices.get(), coefs.get());
333 void GLPKInterface::ClearConstraint(MPConstraint*
const constraint) {
334 InvalidateSolutionSynchronization();
336 if (constraint_is_extracted(constraint->index())) {
337 glp_set_mat_row(lp_, MPSolverIndexToGlpkIndex(constraint->index()), 0,
343 void GLPKInterface::SetObjectiveCoefficient(
const MPVariable*
const variable,
345 sync_status_ = MUST_RELOAD;
349 void GLPKInterface::SetObjectiveOffset(
double value) {
350 sync_status_ = MUST_RELOAD;
354 void GLPKInterface::ClearObjective() {
355 InvalidateSolutionSynchronization();
356 for (
const auto& entry : solver_->objective_->coefficients_) {
357 const int mpsolver_var_index = entry.first->index();
359 if (!variable_is_extracted(mpsolver_var_index)) {
360 DCHECK_NE(MODEL_SYNCHRONIZED, sync_status_);
362 glp_set_obj_coef(lp_, MPSolverIndexToGlpkIndex(mpsolver_var_index), 0.0);
366 glp_set_obj_coef(lp_, 0, 0.0);
369 void GLPKInterface::AddRowConstraint(MPConstraint*
const ct) {
370 sync_status_ = MUST_RELOAD;
373 void GLPKInterface::AddVariable(MPVariable*
const var) {
374 sync_status_ = MUST_RELOAD;
378 void GLPKInterface::ExtractNewVariables() {
379 int total_num_vars = solver_->variables_.size();
380 if (total_num_vars > last_variable_index_) {
381 glp_add_cols(lp_, total_num_vars - last_variable_index_);
382 for (
int j = last_variable_index_; j < solver_->variables_.size(); ++j) {
383 MPVariable*
const var = solver_->variables_[j];
384 set_variable_as_extracted(j,
true);
385 if (!
var->name().empty()) {
386 glp_set_col_name(lp_, MPSolverIndexToGlpkIndex(j),
var->name().c_str());
388 SetVariableBounds(j,
var->lb(),
var->ub());
389 SetVariableInteger(j,
var->integer());
392 double tmp_obj_coef = 0.0;
393 glp_set_obj_coef(lp_, MPSolverIndexToGlpkIndex(j), tmp_obj_coef);
396 ExtractOldConstraints();
401 void GLPKInterface::ExtractOldConstraints() {
402 const int max_constraint_size =
403 solver_->ComputeMaxConstraintSize(0, last_constraint_index_);
406 std::unique_ptr<int[]> indices(
new int[max_constraint_size + 1]);
407 std::unique_ptr<double[]> coefs(
new double[max_constraint_size + 1]);
409 for (
int i = 0; i < last_constraint_index_; ++i) {
410 MPConstraint*
const ct = solver_->constraints_[i];
411 DCHECK(constraint_is_extracted(i));
412 const int size =
ct->coefficients_.size();
417 if (
ct->ContainsNewVariables()) {
418 ExtractOneConstraint(
ct, indices.get(), coefs.get());
426 void GLPKInterface::ExtractOneConstraint(MPConstraint*
const constraint,
428 double*
const coefs) {
431 for (
const auto& entry : constraint->coefficients_) {
432 DCHECK(variable_is_extracted(entry.first->index()));
433 indices[k] = MPSolverIndexToGlpkIndex(entry.first->index());
434 coefs[k] = entry.second;
437 glp_set_mat_row(lp_, MPSolverIndexToGlpkIndex(constraint->index()), k - 1,
442 void GLPKInterface::ExtractNewConstraints() {
443 int total_num_rows = solver_->constraints_.size();
444 if (last_constraint_index_ < total_num_rows) {
446 glp_add_rows(lp_, total_num_rows - last_constraint_index_);
448 for (
int i = last_constraint_index_; i < total_num_rows; ++i) {
449 MPConstraint*
ct = solver_->constraints_[i];
450 set_constraint_as_extracted(i,
true);
451 if (
ct->name().empty()) {
452 glp_set_row_name(lp_, MPSolverIndexToGlpkIndex(i),
453 absl::StrFormat(
"ct_%i", i).c_str());
455 glp_set_row_name(lp_, MPSolverIndexToGlpkIndex(i),
ct->name().c_str());
458 SetConstraintBounds(i,
ct->lb(),
ct->ub());
459 num_coefs +=
ct->coefficients_.size();
463 if (last_variable_index_ == 0 && last_constraint_index_ == 0) {
470 std::unique_ptr<int[]> variable_indices(
new int[num_coefs + 1]);
471 std::unique_ptr<int[]> constraint_indices(
new int[num_coefs + 1]);
472 std::unique_ptr<double[]> coefs(
new double[num_coefs + 1]);
474 for (
int i = 0; i < solver_->constraints_.size(); ++i) {
475 MPConstraint*
ct = solver_->constraints_[i];
476 for (
const auto& entry :
ct->coefficients_) {
477 DCHECK(variable_is_extracted(entry.first->index()));
478 constraint_indices[k] = MPSolverIndexToGlpkIndex(
ct->index());
479 variable_indices[k] = MPSolverIndexToGlpkIndex(entry.first->index());
480 coefs[k] = entry.second;
485 glp_load_matrix(lp_, num_coefs, constraint_indices.get(),
486 variable_indices.get(), coefs.get());
489 int max_constraint_size = solver_->ComputeMaxConstraintSize(
490 last_constraint_index_, total_num_rows);
493 std::unique_ptr<int[]> indices(
new int[max_constraint_size + 1]);
494 std::unique_ptr<double[]> coefs(
new double[max_constraint_size + 1]);
495 for (
int i = last_constraint_index_; i < total_num_rows; i++) {
496 ExtractOneConstraint(solver_->constraints_[i], indices.get(),
503 void GLPKInterface::ExtractObjective() {
506 for (
const auto& entry : solver_->objective_->coefficients_) {
507 glp_set_obj_coef(lp_, MPSolverIndexToGlpkIndex(entry.first->index()),
511 glp_set_obj_coef(lp_, 0, solver_->Objective().offset());
520 if (param.GetIntegerParam(MPSolverParameters::INCREMENTALITY) ==
521 MPSolverParameters::INCREMENTALITY_OFF) {
527 glp_term_out(GLP_OFF);
529 glp_term_out(GLP_ON);
533 VLOG(1) << absl::StrFormat(
"Model built in %.3f seconds.", timer.
Get());
538 ConfigureGLPKParameters(param);
542 int solver_status = glp_simplex(lp_, &lp_param_);
546 if (solver_status == 0) {
547 solver_status = glp_intopt(lp_, &mip_param_);
553 result_status_ = MPSolver::ABNORMAL;
554 if (solver_status == GLP_ETMLIM) {
555 result_status_ = MPSolver::NOT_SOLVED;
557 sync_status_ = SOLUTION_SYNCHRONIZED;
558 return result_status_;
561 VLOG(1) << absl::StrFormat(
"GLPK Status: %i (time spent: %.3f seconds).",
562 solver_status, timer.
Get());
566 objective_value_ = glp_mip_obj_val(lp_);
567 best_objective_bound_ = mip_callback_info_->best_objective_bound_;
569 objective_value_ = glp_get_obj_val(lp_);
571 VLOG(1) <<
"objective=" << objective_value_
572 <<
", bound=" << best_objective_bound_;
573 for (
int i = 0; i < solver_->variables_.size(); ++i) {
574 MPVariable*
const var = solver_->variables_[i];
577 val = glp_mip_col_val(lp_, MPSolverIndexToGlpkIndex(i));
579 val = glp_get_col_prim(lp_, MPSolverIndexToGlpkIndex(i));
581 var->set_solution_value(val);
582 VLOG(3) <<
var->name() <<
": value =" << val;
585 reduced_cost = glp_get_col_dual(lp_, MPSolverIndexToGlpkIndex(i));
586 var->set_reduced_cost(reduced_cost);
587 VLOG(4) <<
var->name() <<
": reduced cost = " << reduced_cost;
590 for (
int i = 0; i < solver_->constraints_.size(); ++i) {
591 MPConstraint*
const ct = solver_->constraints_[i];
593 const double dual_value =
594 glp_get_row_dual(lp_, MPSolverIndexToGlpkIndex(i));
595 ct->set_dual_value(dual_value);
596 VLOG(4) <<
"row " << MPSolverIndexToGlpkIndex(i)
597 <<
": dual value = " << dual_value;
603 int tmp_status = glp_mip_status(lp_);
604 VLOG(1) <<
"GLPK result status: " << tmp_status;
605 if (tmp_status == GLP_OPT) {
607 }
else if (tmp_status == GLP_FEAS) {
609 }
else if (tmp_status == GLP_NOFEAS) {
614 }
else if (solver_status == GLP_ETMLIM) {
615 result_status_ = MPSolver::NOT_SOLVED;
617 result_status_ = MPSolver::ABNORMAL;
622 int tmp_status = glp_get_status(lp_);
623 VLOG(1) <<
"GLPK result status: " << tmp_status;
624 if (tmp_status == GLP_OPT) {
626 }
else if (tmp_status == GLP_FEAS) {
628 }
else if (tmp_status == GLP_NOFEAS || tmp_status == GLP_INFEAS) {
633 }
else if (tmp_status == GLP_UNBND) {
637 result_status_ = MPSolver::UNBOUNDED;
638 }
else if (solver_status == GLP_ETMLIM) {
639 result_status_ = MPSolver::NOT_SOLVED;
641 result_status_ = MPSolver::ABNORMAL;
645 sync_status_ = SOLUTION_SYNCHRONIZED;
647 return result_status_;
650 MPSolver::BasisStatus GLPKInterface::TransformGLPKBasisStatus(
651 int glpk_basis_status)
const {
652 switch (glpk_basis_status) {
654 return MPSolver::BASIC;
656 return MPSolver::AT_LOWER_BOUND;
658 return MPSolver::AT_UPPER_BOUND;
660 return MPSolver::FREE;
662 return MPSolver::FIXED_VALUE;
664 LOG(
FATAL) <<
"Unknown GLPK basis status";
665 return MPSolver::FREE;
671 int64_t GLPKInterface::iterations()
const {
672 #if GLP_MAJOR_VERSION == 4 && GLP_MINOR_VERSION < 49
673 if (!mip_ && CheckSolutionIsSynchronized()) {
674 return lpx_get_int_parm(lp_, LPX_K_ITCNT);
676 #elif GLP_MAJOR_VERSION == 4 && GLP_MINOR_VERSION >= 53
677 if (!mip_ && CheckSolutionIsSynchronized()) {
678 return glp_get_it_cnt(lp_);
681 LOG(
WARNING) <<
"Total number of iterations is not available";
682 return kUnknownNumberOfIterations;
687 if (!CheckSolutionIsSynchronized())
return kUnknownNumberOfNodes;
688 return mip_callback_info_->num_all_nodes_;
690 LOG(DFATAL) <<
"Number of nodes only available for discrete problems";
691 return kUnknownNumberOfNodes;
695 MPSolver::BasisStatus GLPKInterface::row_status(
int constraint_index)
const {
697 DCHECK_LT(constraint_index, last_constraint_index_);
698 const int glpk_basis_status =
699 glp_get_row_stat(lp_, MPSolverIndexToGlpkIndex(constraint_index));
700 return TransformGLPKBasisStatus(glpk_basis_status);
703 MPSolver::BasisStatus GLPKInterface::column_status(
int variable_index)
const {
705 DCHECK_LT(variable_index, last_variable_index_);
706 const int glpk_basis_status =
707 glp_get_col_stat(lp_, MPSolverIndexToGlpkIndex(variable_index));
708 return TransformGLPKBasisStatus(glpk_basis_status);
711 bool GLPKInterface::CheckSolutionExists()
const {
712 if (result_status_ == MPSolver::ABNORMAL) {
713 LOG(
WARNING) <<
"Ignoring ABNORMAL status from GLPK: This status may or may"
714 <<
" not indicate that a solution exists.";
718 return MPSolverInterface::CheckSolutionExists();
722 double GLPKInterface::ComputeExactConditionNumber()
const {
723 if (!IsContinuous()) {
725 LOG(DFATAL) <<
"ComputeExactConditionNumber not implemented for"
726 <<
" GLPK_MIXED_INTEGER_PROGRAMMING";
729 if (!CheckSolutionIsSynchronized())
return 0.0;
732 CheckSolutionExists();
733 const int num_rows = glp_get_num_rows(lp_);
734 const int num_cols = glp_get_num_cols(lp_);
736 std::unique_ptr<double[]> row_scaling_factor(
new double[num_rows + 1]);
737 std::unique_ptr<double[]> column_scaling_factor(
new double[num_cols + 1]);
738 for (
int row = 1;
row <= num_rows; ++
row) {
739 row_scaling_factor[
row] = glp_get_rii(lp_,
row);
741 for (
int col = 1;
col <= num_cols; ++
col) {
742 column_scaling_factor[
col] = glp_get_sjj(lp_,
col);
744 return ComputeInverseScaledBasisL1Norm(num_rows, num_cols,
745 row_scaling_factor.get(),
746 column_scaling_factor.get()) *
747 ComputeScaledBasisL1Norm(num_rows, num_cols, row_scaling_factor.get(),
748 column_scaling_factor.get());
751 double GLPKInterface::ComputeScaledBasisL1Norm(
752 int num_rows,
int num_cols,
double* row_scaling_factor,
753 double* column_scaling_factor)
const {
755 std::unique_ptr<double[]> values(
new double[num_rows + 1]);
756 std::unique_ptr<int[]> indices(
new int[num_rows + 1]);
757 for (
int col = 1;
col <= num_cols; ++
col) {
758 const int glpk_basis_status = glp_get_col_stat(lp_,
col);
760 if (glpk_basis_status == GLP_BS) {
762 const int num_nz = glp_get_mat_col(lp_,
col, indices.get(), values.get());
763 double column_norm = 0.0;
764 for (
int k = 1; k <= num_nz; k++) {
765 column_norm += fabs(values[k] * row_scaling_factor[indices[k]]);
767 column_norm *= fabs(column_scaling_factor[
col]);
773 for (
int row = 1;
row <= num_rows; ++
row) {
774 const int glpk_basis_status = glp_get_row_stat(lp_,
row);
776 if (glpk_basis_status == GLP_BS) {
780 const double column_norm = fabs(row_scaling_factor[
row]);
788 double GLPKInterface::ComputeInverseScaledBasisL1Norm(
789 int num_rows,
int num_cols,
double* row_scaling_factor,
790 double* column_scaling_factor)
const {
792 if (!glp_bf_exists(lp_)) {
793 const int factorize_status = glp_factorize(lp_);
794 switch (factorize_status) {
796 LOG(
FATAL) <<
"Not able to factorize: error GLP_EBADB.";
801 <<
"Not able to factorize: "
802 <<
"the basis matrix is singular within the working precision.";
803 return MPSolver::infinity();
807 <<
"Not able to factorize: the basis matrix is ill-conditioned.";
808 return MPSolver::infinity();
814 std::unique_ptr<double[]> right_hand_side(
new double[num_rows + 1]);
828 for (
int k = 1; k <= num_rows; ++k) {
829 for (
int row = 1;
row <= num_rows; ++
row) {
830 right_hand_side[
row] = 0.0;
832 right_hand_side[k] = 1.0;
834 for (
int row = 1;
row <= num_rows; ++
row) {
835 right_hand_side[
row] /= row_scaling_factor[
row];
837 glp_ftran(lp_, right_hand_side.get());
841 for (
int row = 1;
row <= num_rows; ++
row) {
842 const int k = glp_get_bhead(lp_,
row);
845 right_hand_side[
row] *= row_scaling_factor[k];
848 right_hand_side[
row] /= column_scaling_factor[k - num_rows];
852 double column_norm = 0.0;
853 for (
int row = 1;
row <= num_rows; ++
row) {
854 column_norm += fabs(right_hand_side[
row]);
864 void GLPKInterface::ConfigureGLPKParameters(
const MPSolverParameters& param) {
866 glp_init_iocp(&mip_param_);
868 if (solver_->time_limit()) {
869 VLOG(1) <<
"Setting time limit = " << solver_->time_limit() <<
" ms.";
870 mip_param_.tm_lim = solver_->time_limit();
873 mip_param_.cb_func = GLPKGatherInformationCallback;
875 mip_param_.cb_info = mip_callback_info_.get();
881 glp_init_smcp(&lp_param_);
883 if (solver_->time_limit()) {
884 VLOG(1) <<
"Setting time limit = " << solver_->time_limit() <<
" ms.";
885 lp_param_.tm_lim = solver_->time_limit();
889 glp_scale_prob(lp_, GLP_SF_AUTO);
892 glp_adv_basis(lp_, 0);
895 SetParameters(param);
898 void GLPKInterface::SetParameters(
const MPSolverParameters& param) {
899 SetCommonParameters(param);
901 SetMIPParameters(param);
905 void GLPKInterface::SetRelativeMipGap(
double value) {
907 mip_param_.mip_gap =
value;
909 LOG(
WARNING) <<
"The relative MIP gap is only available "
910 <<
"for discrete problems.";
914 void GLPKInterface::SetPrimalTolerance(
double value) {
915 lp_param_.tol_bnd =
value;
918 void GLPKInterface::SetDualTolerance(
double value) { lp_param_.tol_dj =
value; }
920 void GLPKInterface::SetPresolveMode(
int value) {
922 case MPSolverParameters::PRESOLVE_OFF: {
923 mip_param_.presolve = GLP_OFF;
924 lp_param_.presolve = GLP_OFF;
927 case MPSolverParameters::PRESOLVE_ON: {
928 mip_param_.presolve = GLP_ON;
929 lp_param_.presolve = GLP_ON;
933 SetIntegerParamToUnsupportedValue(MPSolverParameters::PRESOLVE,
value);
938 void GLPKInterface::SetScalingMode(
int value) {
939 SetUnsupportedIntegerParam(MPSolverParameters::SCALING);
942 void GLPKInterface::SetLpAlgorithm(
int value) {
944 case MPSolverParameters::DUAL: {
946 lp_param_.meth = GLP_DUALP;
949 case MPSolverParameters::PRIMAL: {
950 lp_param_.meth = GLP_PRIMAL;
953 case MPSolverParameters::BARRIER:
955 SetIntegerParamToUnsupportedValue(MPSolverParameters::LP_ALGORITHM,
961 MPSolverInterface* BuildGLPKInterface(
bool mip, MPSolver*
const solver) {
962 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.