diff -r d8475431bbbb -r 8e85e6bbefdf lemon/lp_glpk.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/lp_glpk.cc Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,447 @@ +/* -*- C++ -*- + * 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 { + + ///\e + + ///\bug Unimplemented! + /// + LpSolverBase &LpGlpk::_newLp() + { + LpSolverBase *tmp=0; + return *tmp; + } + + ///\e + + ///\bug Unimplemented! + /// + LpSolverBase &LpGlpk::_copyLp() + { + LpSolverBase *tmp=0; + return *tmp; + } + + 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::_eraseCol(int i) { + int cols[2]; + cols[1]=i; + lpx_del_cols(lp, 1, cols); + } + + void LpGlpk::_eraseRow(int i) { + int rows[2]; + rows[1]=i; + lpx_del_rows(lp, 1, rows); + } + + 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::_setCoeff(int row, int col, Value value) + { + ///FIXME Of course this is not efficient at all, but GLPK knows not more. + // First approach: get one row, apply changes and set it again + //(one idea to improve this: maybe it is better to do this with 1 coloumn) + + int mem_length=2+lpx_get_num_cols(lp); + int* indices = new int[mem_length]; + Value* values = new Value[mem_length]; + + + int length=lpx_get_mat_row(lp, row, indices, values); + + //The following code does not suppose that the elements of the array indices are sorted + int i=1; + bool found=false; + while (i <= length && !found){ + if (indices[i]==col){ + found = true; + values[i]=value; + } + ++i; + } + if (!found){ + ++length; + indices[length]=col; + values[length]=value; + } + + lpx_set_mat_row(lp, row, length, indices, values); + delete [] indices; + delete [] 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::_setRowBounds(int i, Value lb, Value ub) + { + //Bad parameter + if (lb==INF || ub==-INF) { + //FIXME error + } + + if (lb == -INF){ + if (ub == INF){ + lpx_set_row_bnds(lp, i, LPX_FR, lb, ub); + } + else{ + lpx_set_row_bnds(lp, i, LPX_UP, lb, ub); + } + } + else{ + if (ub==INF){ + lpx_set_row_bnds(lp, i, LPX_LO, lb, ub); + + } + else{ + if (lb == ub){ + lpx_set_row_bnds(lp, i, LPX_FX, lb, ub); + } + else{ + lpx_set_row_bnds(lp, i, LPX_DB, lb, ub); + } + } + } + + } + + void LpGlpk::_setObjCoeff(int i, Value obj_coef) + { + //i=0 means the constant term (shift) + lpx_set_obj_coef(lp, i, obj_coef); + } + + void LpGlpk::_clearObj() + { + for (int i=0;i<=lpx_get_num_cols(lp);++i){ + lpx_set_obj_coef(lp, i, 0); + } + } +// void LpGlpk::_setObj(int length, +// int const * indices, +// Value const * values ) +// { +// Value new_values[1+lpx_num_cols()]; +// for (i=0;i<=lpx_num_cols();++i){ +// new_values[i]=0; +// } +// for (i=1;i<=length;++i){ +// new_values[indices[i]]=values[i]; +// } + +// for (i=0;i<=lpx_num_cols();++i){ +// lpx_set_obj_coef(lp, i, new_values[i]); +// } +// } + + 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