/* -*- C++ -*- * src/lemon/lp_glpk.cc - Part of LEMON, a generic C++ optimization library * * Copyright (C) 2005 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 * purpose. * */ #ifndef LEMON_LP_GLPK_CC #define LEMON_LP_GLPK_CC ///\file ///\brief Implementation of the LEMON-GLPK lp solver interface. #include namespace lemon { LpGlpk::LpGlpk() : Parent(), lp(lpx_create_prob()) { ///\todo constrol function for this: lpx_set_int_parm(lp, LPX_K_DUAL, 1); messageLevel(0); } LpGlpk::~LpGlpk() { lpx_delete_prob(lp); } int LpGlpk::_addCol() { int i=lpx_add_cols(lp, 1); _setColLowerBound(i, -INF); _setColUpperBound(i, INF); return i; } int LpGlpk::_addRow() { int i=lpx_add_rows(lp, 1); return i; } void LpGlpk::_setRowCoeffs(int i, int length, const int * indices, const Value * values ) { lpx_set_mat_row(lp, i, length, const_cast(indices) , const_cast(values)); } void LpGlpk::_setColCoeffs(int i, int length, const int * indices, const Value * values) { lpx_set_mat_col(lp, i, length, const_cast(indices), const_cast(values)); } void LpGlpk::_setColLowerBound(int i, Value lo) { if (lo==INF) { //FIXME error } int b=lpx_get_col_type(lp, i); double up=lpx_get_col_ub(lp, i); if (lo==-INF) { switch (b) { case LPX_FR: case LPX_LO: lpx_set_col_bnds(lp, i, LPX_FR, lo, up); break; case LPX_UP: break; case LPX_DB: case LPX_FX: lpx_set_col_bnds(lp, i, LPX_UP, lo, up); break; default: ; //FIXME error } } else { switch (b) { case LPX_FR: case LPX_LO: lpx_set_col_bnds(lp, i, LPX_LO, lo, up); break; case LPX_UP: case LPX_DB: case LPX_FX: if (lo==up) lpx_set_col_bnds(lp, i, LPX_FX, lo, up); else lpx_set_col_bnds(lp, i, LPX_DB, lo, up); break; default: ; //FIXME error } } } void LpGlpk::_setColUpperBound(int i, Value up) { if (up==-INF) { //FIXME error } int b=lpx_get_col_type(lp, i); double lo=lpx_get_col_lb(lp, i); if (up==INF) { switch (b) { case LPX_FR: case LPX_LO: break; case LPX_UP: lpx_set_col_bnds(lp, i, LPX_FR, lo, up); break; case LPX_DB: case LPX_FX: lpx_set_col_bnds(lp, i, LPX_LO, lo, up); break; default: ; //FIXME error } } else { switch (b) { case LPX_FR: lpx_set_col_bnds(lp, i, LPX_UP, lo, up); break; case LPX_UP: lpx_set_col_bnds(lp, i, LPX_UP, lo, up); break; case LPX_LO: case LPX_DB: case LPX_FX: if (lo==up) lpx_set_col_bnds(lp, i, LPX_FX, lo, up); else lpx_set_col_bnds(lp, i, LPX_DB, lo, up); break; default: ; //FIXME error } } } void LpGlpk::_setRowLowerBound(int i, Value lo) { if (lo==INF) { //FIXME error } int b=lpx_get_row_type(lp, i); double up=lpx_get_row_ub(lp, i); if (lo==-INF) { switch (b) { case LPX_FR: case LPX_LO: lpx_set_row_bnds(lp, i, LPX_FR, lo, up); break; case LPX_UP: break; case LPX_DB: case LPX_FX: lpx_set_row_bnds(lp, i, LPX_UP, lo, up); break; default: ; //FIXME error } } else { switch (b) { case LPX_FR: case LPX_LO: lpx_set_row_bnds(lp, i, LPX_LO, lo, up); break; case LPX_UP: case LPX_DB: case LPX_FX: if (lo==up) lpx_set_row_bnds(lp, i, LPX_FX, lo, up); else lpx_set_row_bnds(lp, i, LPX_DB, lo, up); break; default: ; //FIXME error } } } void LpGlpk::_setRowUpperBound(int i, Value up) { if (up==-INF) { //FIXME error } int b=lpx_get_row_type(lp, i); double lo=lpx_get_row_lb(lp, i); if (up==INF) { switch (b) { case LPX_FR: case LPX_LO: break; case LPX_UP: lpx_set_row_bnds(lp, i, LPX_FR, lo, up); break; case LPX_DB: case LPX_FX: lpx_set_row_bnds(lp, i, LPX_LO, lo, up); break; default: ; //FIXME error } } else { switch (b) { case LPX_FR: lpx_set_row_bnds(lp, i, LPX_UP, lo, up); break; case LPX_UP: lpx_set_row_bnds(lp, i, LPX_UP, lo, up); break; case LPX_LO: case LPX_DB: case LPX_FX: if (lo==up) lpx_set_row_bnds(lp, i, LPX_FX, lo, up); else lpx_set_row_bnds(lp, i, LPX_DB, lo, up); break; default: ; //FIXME error } } } void LpGlpk::_setObjCoeff(int i, Value obj_coef) { lpx_set_obj_coef(lp, i, obj_coef); } LpGlpk::SolveExitStatus LpGlpk::_solve() { int i= lpx_simplex(lp); switch (i) { case LPX_E_OK: return SOLVED; break; default: return UNSOLVED; } } LpGlpk::Value LpGlpk::_getPrimal(int i) { return lpx_get_col_prim(lp,i); } LpGlpk::Value LpGlpk::_getPrimalValue() { return lpx_get_obj_val(lp); } LpGlpk::SolutionStatus LpGlpk::_getPrimalStatus() { int stat= lpx_get_status(lp); switch (stat) { case LPX_UNDEF://Undefined (no solve has been run yet) return UNDEFINED; break; case LPX_NOFEAS://There is no feasible solution (primal, I guess) case LPX_INFEAS://Infeasible return INFEASIBLE; break; case LPX_UNBND://Unbounded return INFINITE; break; case LPX_FEAS://Feasible return FEASIBLE; break; case LPX_OPT://Feasible return OPTIMAL; break; default: return UNDEFINED; //to avoid gcc warning //FIXME error } } void LpGlpk::_setMax() { lpx_set_obj_dir(lp, LPX_MAX); } void LpGlpk::_setMin() { lpx_set_obj_dir(lp, LPX_MIN); } void LpGlpk::messageLevel(int m) { lpx_set_int_parm(lp, LPX_K_MSGLEV, m); } void LpGlpk::presolver(bool b) { lpx_set_int_parm(lp, LPX_K_PRESOL, b); } } //END OF NAMESPACE LEMON #endif //LEMON_LP_GLPK_CC