/* -*- mode: C++; indent-tabs-mode: nil; -*-
* This file is a part of LEMON, a generic C++ optimization library.
* Copyright (C) 2003-2008
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
///\brief Implementation of the LEMON-GLPK lp solver interface.
#include <lemon/lp_glpk.h>
#if GLP_MAJOR_VERSION > 4 || (GLP_MAJOR_VERSION == 4 && GLP_MINOR_VERSION > 15)
#define LEMON_glp(func) (glp_##func)
#define LEMON_lpx(func) (lpx_##func)
#define LEMON_GLP(def) (GLP_##def)
#define LEMON_LPX(def) (LPX_##def)
#define LEMON_glp(func) (lpx_##func)
#define LEMON_lpx(func) (lpx_##func)
#define LEMON_GLP(def) (LPX_##def)
#define LEMON_LPX(def) (LPX_##def)
LpGlpk::LpGlpk() : Parent() {
rows = _lp_bits::LpId(1);
cols = _lp_bits::LpId(1);
lp = LEMON_glp(create_prob)();
LEMON_glp(create_index)(lp);
LpGlpk::LpGlpk(const LpGlpk &glp) : Parent() {
rows = _lp_bits::LpId(1);
cols = _lp_bits::LpId(1);
lp = LEMON_glp(create_prob)();
LEMON_glp(create_index)(lp);
//Coefficient matrix, row bounds
LEMON_glp(add_rows)(lp, LEMON_glp(get_num_rows)(glp.lp));
LEMON_glp(add_cols)(lp, LEMON_glp(get_num_cols)(glp.lp));
std::vector<int> ind(1+LEMON_glp(get_num_cols)(glp.lp));
std::vector<Value> val(1+LEMON_glp(get_num_cols)(glp.lp));
for (int i=1;i<=LEMON_glp(get_num_rows)(glp.lp);++i)
len=LEMON_glp(get_mat_row)(glp.lp,i,&*ind.begin(),&*val.begin());
LEMON_glp(set_mat_row)(lp, i,len,&*ind.begin(),&*val.begin());
LEMON_glp(set_row_bnds)(lp,i,
LEMON_glp(get_row_type)(glp.lp,i),
LEMON_glp(get_row_lb)(glp.lp,i),
LEMON_glp(get_row_ub)(glp.lp,i));
//Objective function, coloumn bounds
LEMON_glp(set_obj_dir)(lp, LEMON_glp(get_obj_dir)(glp.lp));
//Objectif function's constant term treated separately
LEMON_glp(set_obj_coef)(lp,0,LEMON_glp(get_obj_coef)(glp.lp,0));
for (int i=1;i<=LEMON_glp(get_num_cols)(glp.lp);++i)
LEMON_glp(set_obj_coef)(lp,i,
LEMON_glp(get_obj_coef)(glp.lp,i));
LEMON_glp(set_col_bnds)(lp,i,
LEMON_glp(get_col_type)(glp.lp,i),
LEMON_glp(get_col_lb)(glp.lp,i),
LEMON_glp(get_col_ub)(glp.lp,i));
LEMON_glp(delete_prob)(lp);
int i=LEMON_glp(add_cols)(lp, 1);
LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(FR), 0.0, 0.0);
LpSolverBase* LpGlpk::_newLp()
LpGlpk* newlp = new LpGlpk;
LpSolverBase* LpGlpk::_copyLp()
LpGlpk *newlp = new LpGlpk(*this);
int i=LEMON_glp(add_rows)(lp, 1);
void LpGlpk::_eraseCol(int i) {
LEMON_glp(del_cols)(lp, 1, ca);
void LpGlpk::_eraseRow(int i) {
LEMON_glp(del_rows)(lp, 1, ra);
void LpGlpk::_getColName(int c, std::string & name) const
const char *n = LEMON_glp(get_col_name)(lp,c);
void LpGlpk::_setColName(int c, const std::string & name)
LEMON_glp(set_col_name)(lp,c,const_cast<char*>(name.c_str()));
int LpGlpk::_colByName(const std::string& name) const
int k = LEMON_glp(find_col)(lp, const_cast<char*>(name.c_str()));
void LpGlpk::_setRowCoeffs(int i, ConstRowIterator b, ConstRowIterator e)
std::vector<int> indices;
std::vector<Value> values;
for(ConstRowIterator it=b; it!=e; ++it) {
indices.push_back(it->first);
values.push_back(it->second);
LEMON_glp(set_mat_row)(lp, i, values.size() - 1,
&indices[0], &values[0]);
void LpGlpk::_getRowCoeffs(int ix, RowIterator b) const
int length = LEMON_glp(get_mat_row)(lp, ix, 0, 0);
std::vector<int> indices(length + 1);
std::vector<Value> values(length + 1);
LEMON_glp(get_mat_row)(lp, ix, &indices[0], &values[0]);
for (int i = 1; i <= length; ++i) {
*b = std::make_pair(indices[i], values[i]);
void LpGlpk::_setColCoeffs(int ix, ConstColIterator b, ConstColIterator e) {
std::vector<int> indices;
std::vector<Value> values;
for(ConstColIterator it=b; it!=e; ++it) {
indices.push_back(it->first);
values.push_back(it->second);
LEMON_glp(set_mat_col)(lp, ix, values.size() - 1,
&indices[0], &values[0]);
void LpGlpk::_getColCoeffs(int ix, ColIterator b) const
int length = LEMON_glp(get_mat_col)(lp, ix, 0, 0);
std::vector<int> indices(length + 1);
std::vector<Value> values(length + 1);
LEMON_glp(get_mat_col)(lp, ix, &indices[0], &values[0]);
for (int i = 1; i <= length; ++i) {
*b = std::make_pair(indices[i], values[i]);
void LpGlpk::_setCoeff(int ix, int jx, Value value)
if (LEMON_glp(get_num_cols)(lp) < LEMON_glp(get_num_rows)(lp)) {
int length=LEMON_glp(get_mat_row)(lp, ix, 0, 0);
std::vector<int> indices(length + 2);
std::vector<Value> values(length + 2);
LEMON_glp(get_mat_row)(lp, ix, &indices[0], &values[0]);
//The following code does not suppose that the elements of the
//array indices are sorted
for (int i = 1; i <= length; ++i) {
LEMON_glp(set_mat_row)(lp, ix, length, &indices[0], &values[0]);
int length=LEMON_glp(get_mat_col)(lp, jx, 0, 0);
std::vector<int> indices(length + 2);
std::vector<Value> values(length + 2);
LEMON_glp(get_mat_col)(lp, jx, &indices[0], &values[0]);
//The following code does not suppose that the elements of the
//array indices are sorted
for (int i = 1; i <= length; ++i) {
LEMON_glp(set_mat_col)(lp, jx, length, &indices[0], &values[0]);
LpGlpk::Value LpGlpk::_getCoeff(int ix, int jx) const
int length=LEMON_glp(get_mat_row)(lp, ix, 0, 0);
std::vector<int> indices(length + 1);
std::vector<Value> values(length + 1);
LEMON_glp(get_mat_row)(lp, ix, &indices[0], &values[0]);
//The following code does not suppose that the elements of the
//array indices are sorted
for (int i = 1; i <= length; ++i) {
void LpGlpk::_setColLowerBound(int i, Value lo)
int b=LEMON_glp(get_col_type)(lp, i);
double up=LEMON_glp(get_col_ub)(lp, i);
LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(FR), lo, up);
LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(UP), lo, up);
LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(LO), lo, up);
LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(FX), lo, up);
LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(DB), lo, up);
LpGlpk::Value LpGlpk::_getColLowerBound(int i) const
int b=LEMON_glp(get_col_type)(lp, i);
return LEMON_glp(get_col_lb)(lp, i);
void LpGlpk::_setColUpperBound(int i, Value up)
int b=LEMON_glp(get_col_type)(lp, i);
double lo=LEMON_glp(get_col_lb)(lp, i);
LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(FR), lo, up);
LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(LO), lo, up);
LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(UP), lo, up);
LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(UP), lo, up);
LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(FX), lo, up);
LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(DB), lo, up);
LpGlpk::Value LpGlpk::_getColUpperBound(int i) const
int b=LEMON_glp(get_col_type)(lp, i);
return LEMON_glp(get_col_ub)(lp, i);
void LpGlpk::_setRowBounds(int i, Value lb, Value ub)
if (lb==INF || ub==-INF) {
LEMON_glp(set_row_bnds)(lp, i, LEMON_GLP(FR), lb, ub);
LEMON_glp(set_row_bnds)(lp, i, LEMON_GLP(UP), lb, ub);
LEMON_glp(set_row_bnds)(lp, i, LEMON_GLP(LO), lb, ub);
LEMON_glp(set_row_bnds)(lp, i, LEMON_GLP(FX), lb, ub);
LEMON_glp(set_row_bnds)(lp, i, LEMON_GLP(DB), lb, ub);
void LpGlpk::_getRowBounds(int i, Value &lb, Value &ub) const
int b=LEMON_glp(get_row_type)(lp, i);
lb=LEMON_glp(get_row_lb)(lp, i);
ub=LEMON_glp(get_row_ub)(lp, i);
void LpGlpk::_setObjCoeff(int i, Value obj_coef)
//i=0 means the constant term (shift)
LEMON_glp(set_obj_coef)(lp, i, obj_coef);
LpGlpk::Value LpGlpk::_getObjCoeff(int i) const {
//i=0 means the constant term (shift)
return LEMON_glp(get_obj_coef)(lp, i);
for (int i=0;i<=LEMON_glp(get_num_cols)(lp);++i){
LEMON_glp(set_obj_coef)(lp, i, 0);
LpGlpk::SolveExitStatus LpGlpk::_solve()
// A way to check the problem to be solved
//LEMON_glp(write_cpxlp(lp,"naittvan.cpx");
LEMON_lpx(std_basis)(lp);
int i = LEMON_lpx(simplex)(lp);
LpGlpk::Value LpGlpk::_getPrimal(int i) const
return LEMON_glp(get_col_prim)(lp,i);
LpGlpk::Value LpGlpk::_getDual(int i) const
return LEMON_glp(get_row_dual)(lp,i);
LpGlpk::Value LpGlpk::_getPrimalValue() const
return LEMON_glp(get_obj_val)(lp);
bool LpGlpk::_isBasicCol(int i) const
return (LEMON_glp(get_col_stat)(lp, i)==LEMON_GLP(BS));
LpGlpk::SolutionStatus LpGlpk::_getPrimalStatus() const
if (!solved) return UNDEFINED;
int stat= LEMON_lpx(get_status)(lp);
case LEMON_LPX(UNDEF):
//Undefined (no solve has been run yet)
case LEMON_LPX(NOFEAS):
//There is no feasible solution (primal, I guess)
case LEMON_LPX(INFEAS):
//Infeasible
case LEMON_LPX(UNBND):
//Unbounded
case LEMON_LPX(FEAS):
//Feasible
case LEMON_LPX(OPT):
//Feasible
return UNDEFINED; //to avoid gcc warning
LpGlpk::SolutionStatus LpGlpk::_getDualStatus() const
if (!solved) return UNDEFINED;
switch (LEMON_lpx(get_dual_stat)(lp)) {
case LEMON_LPX(D_UNDEF):
//Undefined (no solve has been run yet)
case LEMON_LPX(D_NOFEAS):
//There is no dual feasible solution
// case LEMON_LPX(D_INFEAS://Infeasible
case LEMON_LPX(D_FEAS)://Feasible
switch (LEMON_lpx(get_status)(lp)) {
return UNDEFINED; //to avoid gcc warning
LpGlpk::ProblemTypes LpGlpk::_getProblemType() const
if (!solved) return UNKNOWN;
//int stat= LEMON_glp(get_status(lp);
int statp= LEMON_lpx(get_prim_stat)(lp);
int statd= LEMON_lpx(get_dual_stat)(lp);
if (statp==LEMON_LPX(P_FEAS) && statd==LEMON_LPX(D_FEAS))
return PRIMAL_DUAL_FEASIBLE;
if (statp==LEMON_LPX(P_FEAS) && statd==LEMON_LPX(D_NOFEAS))
return PRIMAL_FEASIBLE_DUAL_INFEASIBLE;
if (statp==LEMON_LPX(P_NOFEAS) && statd==LEMON_LPX(D_FEAS))
return PRIMAL_INFEASIBLE_DUAL_FEASIBLE;
if (statp==LEMON_LPX(P_NOFEAS) && statd==LEMON_LPX(D_NOFEAS))
return PRIMAL_DUAL_INFEASIBLE;
LEMON_glp(set_obj_dir)(lp, LEMON_GLP(MAX));
LEMON_glp(set_obj_dir)(lp, LEMON_GLP(MIN));
bool LpGlpk::_isMax() const
return (LEMON_glp(get_obj_dir)(lp)==LEMON_GLP(MAX));
void LpGlpk::messageLevel(int m)
LEMON_lpx(set_int_parm)(lp, LEMON_LPX(K_MSGLEV), m);
void LpGlpk::presolver(bool b)
LEMON_lpx(set_int_parm)(lp, LEMON_LPX(K_PRESOL), b);
} //END OF NAMESPACE LEMON