# HG changeset patch # User deba # Date 1171549328 0 # Node ID 2aabce55857427e3a2f08fb00e302b6cf244b0da # Parent eb37b9774ef6d27af8ce49d6ca22c90d165fb532 Changes on the LP interface _FixId => LpId - handling of not common ids // soplex LpGlpk row and col erase bug fix - calling lpx_std_basis before simplex LpSoplex - added getter functions - better m4 file - integration to the tests - better handling of unsolved lps diff -r eb37b9774ef6 -r 2aabce558574 lemon/Makefile.am --- a/lemon/Makefile.am Thu Feb 15 13:06:23 2007 +0000 +++ b/lemon/Makefile.am Thu Feb 15 14:22:08 2007 +0000 @@ -15,8 +15,8 @@ lemon/bits/mingw32_time.cc \ lemon/random.cc -lemon_libemon_la_CXXFLAGS = $(GLPK_CFLAGS) $(CPLEX_CFLAGS) $(SOPLEX_CFLAGS) -lemon_libemon_la_LDFLAGS = $(GLPK_LIBS) $(CPLEX_LIBS) $(SOPLEX_CFLAGS) +lemon_libemon_la_CXXFLAGS = $(GLPK_CFLAGS) $(CPLEX_CFLAGS) $(SOPLEX_CXXFLAGS) +lemon_libemon_la_LDFLAGS = $(GLPK_LIBS) $(CPLEX_LIBS) $(SOPLEX_LIBS) if HAVE_GLPK lemon_libemon_la_SOURCES += lemon/lp_glpk.cc @@ -123,6 +123,7 @@ lemon/bits/invalid.h \ lemon/bits/item_reader.h \ lemon/bits/item_writer.h \ + lemon/bits/lp_id.h \ lemon/bits/map_extender.h \ lemon/bits/mingw32_time.h \ lemon/bits/path_dump.h \ diff -r eb37b9774ef6 -r 2aabce558574 lemon/bits/lp_id.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/bits/lp_id.h Thu Feb 15 14:22:08 2007 +0000 @@ -0,0 +1,146 @@ +/* -*- C++ -*- + * + * This file is a part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2003-2006 + * 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_BITS_LP_SOLVER_ID_H +#define LEMON_BITS_LP_SOLVER_ID_H + +namespace lemon { + + namespace _lp_bits { + + struct LpIdImpl { + std::vector index; + std::vector cross; + int first_index; + int first_free; + }; + + class LpId { + public: + + class IdHandler { + public: + virtual ~IdHandler() {} + virtual int addId(LpIdImpl&) = 0; + virtual void eraseId(LpIdImpl&, int xn) = 0; + }; + + LpId(int min_index = 0) { + id_handler = 0; + impl.first_free = -1; + impl.first_index = min_index; + impl.cross.resize(impl.first_index); + } + + void setIdHandler(IdHandler& ih) { + id_handler = &ih; + } + + int fixId(int fn) const {return impl.cross[fn];} + int floatingId(int xn) const {return impl.index[xn];} + + int addId() { + if (id_handler == 0) { + int xn, fn = impl.cross.size(); + if (impl.first_free == -1) { + xn = impl.index.size(); + impl.index.push_back(fn); + } else { + xn = impl.first_free; + impl.first_free = impl.index[impl.first_free]; + impl.index[xn] = fn; + } + impl.cross.push_back(xn); + return xn; + } else { + return id_handler->addId(impl); + } + } + + void eraseId(int xn) { + if (id_handler == 0) { + int fn = impl.index[xn]; + impl.index[xn] = impl.first_free; + impl.first_free = xn; + for(int i = fn + 1; i < (int)impl.cross.size(); ++i) { + impl.cross[i - 1] = impl.cross[i]; + impl.index[impl.cross[i]]--; + } + impl.cross.pop_back(); + } else { + id_handler->eraseId(impl, xn); + } + } + + void firstFloating(int& fn) const { + fn = impl.first_index; + if (fn == (int)impl.cross.size()) fn = -1; + } + + void nextFloating(int& fn) const { + ++fn; + if (fn == (int)impl.cross.size()) fn = -1; + } + + void firstFix(int& xn) const { + int fn; + firstFloating(fn); + xn = fn != -1 ? fixId(fn) : -1; + } + + void nextFix(int& xn) const { + int fn = floatingId(xn); + nextFloating(fn); + xn = fn != -1 ? fixId(fn) : -1; + } + + protected: + LpIdImpl impl; + IdHandler *id_handler; + }; + + class RelocateIdHandler : public LpId::IdHandler { + public: + + virtual int addId(LpIdImpl& impl) { + int xn, fn = impl.cross.size(); + if (impl.first_free == -1) { + xn = impl.index.size(); + impl.index.push_back(fn); + } else { + xn = impl.first_free; + impl.first_free = impl.index[impl.first_free]; + impl.index[xn] = fn; + } + impl.cross.push_back(xn); + return xn; + } + + virtual void eraseId(LpIdImpl& impl, int xn) { + int fn = impl.index[xn]; + impl.index[xn] = impl.first_free; + impl.first_free = xn; + impl.cross[fn] = impl.cross.back(); + impl.index[impl.cross.back()] = fn; + impl.cross.pop_back(); + } + }; + } +} + +#endif diff -r eb37b9774ef6 -r 2aabce558574 lemon/lp_base.h --- a/lemon/lp_base.h Thu Feb 15 13:06:23 2007 +0000 +++ b/lemon/lp_base.h Thu Feb 15 14:22:08 2007 +0000 @@ -27,93 +27,16 @@ #include #include -#include #include #include +#include +#include ///\file ///\brief The interface of the LP solver interface. ///\ingroup gen_opt_group namespace lemon { - - ///Internal data structure to convert floating id's to fix one's - - ///\todo This might be implemented to be also usable in other places. - class _FixId - { - protected: - int _first_index; - int first_free; - public: - std::vector index; - std::vector cross; - _FixId() : _first_index(-1), first_free(-1) {}; - ///Convert a floating id to a fix one - - ///\param n is a floating id - ///\return the corresponding fix id - int fixId(int n) const {return cross[n];} - ///Convert a fix id to a floating one - - ///\param n is a fix id - ///\return the corresponding floating id - int floatingId(int n) const { return index[n];} - ///Add a new floating id. - - ///\param n is a floating id - ///\return the fix id of the new value - ///\todo Multiple additions should also be handled. - int insert(int n) - { - if(cross.empty()) _first_index=n; - if(n>=int(cross.size())) { - cross.resize(n+1); - if(first_free==-1) { - cross[n]=index.size(); - index.push_back(n); - } - else { - cross[n]=first_free; - int next=index[first_free]; - index[first_free]=n; - first_free=next; - } - return cross[n]; - } - else { - ///\todo Create an own exception type. - throw LogicError(); //floatingId-s must form a continuous range; - } - } - ///Remove a fix id. - - ///\param n is a fix id - /// - void erase(int n) - { - int fl=index[n]; - index[n]=first_free; - first_free=n; - for(int i=fl+1;icols.cross.empty()?-1: - _lp->cols.fixId(_lp->cols.firstIndex()); + _lp->cols.firstFix(id); } ColIt(const Invalid&) : Col(INVALID) {} ColIt &operator++() { - int fid = _lp->cols.floatingId(id)+1; - id = unsigned(fid)<_lp->cols.cross.size() ? _lp->cols.fixId(fid) : -1; + _lp->cols.nextFix(id); return *this; } }; @@ -746,8 +668,6 @@ virtual Value _getColLowerBound(int i) = 0; virtual void _setColUpperBound(int i, Value value) = 0; virtual Value _getColUpperBound(int i) = 0; -// virtual void _setRowLowerBound(int i, Value value) = 0; -// virtual void _setRowUpperBound(int i, Value value) = 0; virtual void _setRowBounds(int i, Value lower, Value upper) = 0; virtual void _getRowBounds(int i, Value &lower, Value &upper)=0; @@ -795,7 +715,7 @@ ///@{ ///Add a new empty column (i.e a new variable) to the LP - Col addCol() { Col c; c.id=cols.insert(_addCol()); return c;} + Col addCol() { Col c; _addCol(); c.id = cols.addId(); return c;} ///\brief Adds several new columns ///(i.e a variables) at once @@ -887,7 +807,7 @@ ///This function adds a new empty row (i.e a new constraint) to the LP. ///\return The created row - Row addRow() { Row r; r.id=rows.insert(_addRow()); return r;} + Row addRow() { Row r; _addRow(); r.id = rows.addId(); return r;} ///\brief Add several new rows ///(i.e a constraints) at once @@ -965,8 +885,6 @@ e.simplify(); _setRowCoeffs(_lpId(r), LpRowIterator(e.begin(), *this), LpRowIterator(e.end(), *this)); -// _setRowLowerBound(_lpId(r),l-e.constComp()); -// _setRowUpperBound(_lpId(r),u-e.constComp()); _setRowBounds(_lpId(r),l-e.constComp(),u-e.constComp()); } @@ -1008,7 +926,7 @@ ///\todo Please check this void eraseCol(Col c) { _eraseCol(_lpId(c)); - cols.erase(c.id); + cols.eraseId(c.id); } ///Erase a row (i.e a constraint) from the LP @@ -1016,7 +934,7 @@ ///\todo Please check this void eraseRow(Row r) { _eraseRow(_lpId(r)); - rows.erase(r.id); + rows.eraseId(r.id); } /// Get the name of a column @@ -1216,31 +1134,14 @@ } #endif -// /// Set the lower bound of a row (i.e a constraint) - -// /// The lower bound of a linear expression (row) has to be given by an -// /// extended number of type Value, i.e. a finite number of type -// /// Value or -\ref INF. -// void rowLowerBound(Row r, Value value) { -// _setRowLowerBound(_lpId(r),value); -// }; -// /// Set the upper bound of a row (i.e a constraint) - -// /// The upper bound of a linear expression (row) has to be given by an -// /// extended number of type Value, i.e. a finite number of type -// /// Value or \ref INF. -// void rowUpperBound(Row r, Value value) { -// _setRowUpperBound(_lpId(r),value); -// }; /// Set the lower and the upper bounds of a row (i.e a constraint) - /// The lower and the upper bound of - /// a constraint (row) have to be given by an - /// extended number of type Value, i.e. a finite number of type - /// Value, -\ref INF or \ref INF. There is no separate function for the - /// lower and the upper bound because that would have been hard to implement - /// for CPLEX. + /// The lower and the upper bound of a constraint (row) have to be + /// given by an extended number of type Value, i.e. a finite + /// number of type Value, -\ref INF or \ref INF. There is no + /// separate function for the lower and the upper bound because + /// that would have been hard to implement for CPLEX. void rowBounds(Row c, Value lower, Value upper) { _setRowBounds(_lpId(c),lower, upper); } diff -r eb37b9774ef6 -r 2aabce558574 lemon/lp_cplex.cc --- a/lemon/lp_cplex.cc Thu Feb 15 13:06:23 2007 +0000 +++ b/lemon/lp_cplex.cc Thu Feb 15 14:22:08 2007 +0000 @@ -24,7 +24,6 @@ namespace lemon { LpCplex::LpCplex() : LpSolverBase() { - // env = CPXopenCPLEXdevelop(&status); env = CPXopenCPLEX(&status); lp = CPXcreateprob(env, &status, "LP problem"); diff -r eb37b9774ef6 -r 2aabce558574 lemon/lp_glpk.cc --- a/lemon/lp_glpk.cc Thu Feb 15 13:06:23 2007 +0000 +++ b/lemon/lp_glpk.cc Thu Feb 15 14:22:08 2007 +0000 @@ -24,16 +24,20 @@ namespace lemon { - LpGlpk::LpGlpk() : Parent(), - lp(lpx_create_prob()) { - ///\todo constrol function for this: + LpGlpk::LpGlpk() : Parent() { + rows = _lp_bits::LpId(1); + cols = _lp_bits::LpId(1); + lp = lpx_create_prob(); + ///\todo control function for this: lpx_set_int_parm(lp, LPX_K_DUAL, 1); messageLevel(0); } - LpGlpk::LpGlpk(const LpGlpk &glp) : Parent(glp), - lp(lpx_create_prob()) { - ///\todo constrol function for this: + LpGlpk::LpGlpk(const LpGlpk &glp) : Parent() { + rows = _lp_bits::LpId(1); + cols = _lp_bits::LpId(1); + lp = lpx_create_prob(); + ///\todo control function for this: lpx_set_int_parm(lp, LPX_K_DUAL, 1); messageLevel(0); //Coefficient matrix, row bounds @@ -349,92 +353,6 @@ } } -// 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 @@ -508,29 +426,15 @@ 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() { // A way to check the problem to be solved //lpx_write_cpxlp(lp,"naittvan.cpx"); + lpx_std_basis(lp); int i = lpx_simplex(lp); + switch (i) { case LPX_E_OK: return SOLVED; diff -r eb37b9774ef6 -r 2aabce558574 lemon/lp_skeleton.h --- a/lemon/lp_skeleton.h Thu Feb 15 13:06:23 2007 +0000 +++ b/lemon/lp_skeleton.h Thu Feb 15 14:22:08 2007 +0000 @@ -30,6 +30,7 @@ int col_num,row_num; protected: + ///\e virtual LpSolverBase &_newLp(); ///\e diff -r eb37b9774ef6 -r 2aabce558574 lemon/lp_soplex.cc --- a/lemon/lp_soplex.cc Thu Feb 15 13:06:23 2007 +0000 +++ b/lemon/lp_soplex.cc Thu Feb 15 14:22:08 2007 +0000 @@ -27,7 +27,10 @@ namespace lemon { LpSoplex::LpSoplex() : LpSolverBase() { + rows.setIdHandler(relocateIdHandler); + cols.setIdHandler(relocateIdHandler); soplex = new soplex::SoPlex; + solved = false; } LpSoplex::~LpSoplex() { @@ -47,19 +50,25 @@ int LpSoplex::_addCol() { soplex::LPCol col; + col.setLower(-soplex::infinity); + col.setUpper(soplex::infinity); soplex->addCol(col); colNames.push_back(std::string()); - primal.push_back(0.0); + primal_value.push_back(0.0); + solved = false; return soplex->nCols() - 1; } int LpSoplex::_addRow() { soplex::LPRow row; + row.setLhs(-soplex::infinity); + row.setRhs(soplex::infinity); soplex->addRow(row); - dual.push_back(0.0); + dual_value.push_back(0.0); + solved = false; return soplex->nRows() - 1; } @@ -67,14 +76,18 @@ void LpSoplex::_eraseCol(int i) { soplex->removeCol(i); - primal[i] = primal.back(); - primal.pop_back(); + colNames[i] = colNames.back(); + colNames.pop_back(); + primal_value[i] = primal_value.back(); + primal_value.pop_back(); + solved = false; } void LpSoplex::_eraseRow(int i) { soplex->removeRow(i); - dual[i] = dual.back(); - dual.pop_back(); + dual_value[i] = dual_value.back(); + dual_value.pop_back(); + solved = false; } void LpSoplex::_getColName(int col, std::string &name) { @@ -93,6 +106,7 @@ for(LpRowIterator it = b; it != e; ++it) { soplex->changeElement(i, it->first, it->second); } + solved = false; } void LpSoplex::_setColCoeffs(int j, LpColIterator b, LpColIterator e) { @@ -102,47 +116,80 @@ for(LpColIterator it = b; it != e; ++it) { soplex->changeElement(it->first, j, it->second); } + solved = false; } - void LpSoplex::_setCoeff(int row, int col, Value value) { - soplex->changeElement(row, col, value); + void LpSoplex::_setCoeff(int i, int j, Value value) { + soplex->changeElement(i, j, value); + solved = false; + } + + LpSoplex::Value LpSoplex::_getCoeff(int i, int j) { + return soplex->rowVector(i)[j]; } void LpSoplex::_setColLowerBound(int i, Value value) { - soplex->changeLower(i, value); + soplex->changeLower(i, value != -INF ? value : -soplex::infinity); + solved = false; } + LpSoplex::Value LpSoplex::_getColLowerBound(int i) { + double value = soplex->lower(i); + return value != -soplex::infinity ? value : -INF; + } + void LpSoplex::_setColUpperBound(int i, Value value) { - soplex->changeUpper(i, value); + soplex->changeUpper(i, value != INF ? value : soplex::infinity); + solved = false; + } + + LpSoplex::Value LpSoplex::_getColUpperBound(int i) { + double value = soplex->upper(i); + return value != soplex::infinity ? value : INF; } void LpSoplex::_setRowBounds(int i, Value lb, Value ub) { - soplex->changeRange(i, lb, ub); + soplex->changeRange(i, lb != -INF ? lb : -soplex::infinity, + ub != INF ? ub : soplex::infinity); + solved = false; + } + void LpSoplex::_getRowBounds(int i, Value &lower, Value &upper) { + lower = soplex->lhs(i); + if (lower == -soplex::infinity) lower = -INF; + upper = soplex->rhs(i); + if (upper == -soplex::infinity) upper = INF; } void LpSoplex::_setObjCoeff(int i, Value obj_coef) { soplex->changeObj(i, obj_coef); + solved = false; + } + + LpSoplex::Value LpSoplex::_getObjCoeff(int i) { + return soplex->obj(i); } void LpSoplex::_clearObj() { for (int i = 0; i < soplex->nCols(); ++i) { soplex->changeObj(i, 0.0); } + solved = false; } LpSoplex::SolveExitStatus LpSoplex::_solve() { soplex::SPxSolver::Status status = soplex->solve(); - soplex::Vector pv(primal.size(), &primal[0]); + soplex::Vector pv(primal_value.size(), &primal_value[0]); soplex->getPrimal(pv); - soplex::Vector dv(dual.size(), &dual[0]); + soplex::Vector dv(dual_value.size(), &dual_value[0]); soplex->getDual(dv); switch (status) { case soplex::SPxSolver::OPTIMAL: case soplex::SPxSolver::INFEASIBLE: case soplex::SPxSolver::UNBOUNDED: + solved = true; return SOLVED; default: return UNSOLVED; @@ -150,11 +197,11 @@ } LpSoplex::Value LpSoplex::_getPrimal(int i) { - return primal[i]; + return primal_value[i]; } LpSoplex::Value LpSoplex::_getDual(int i) { - return dual[i]; + return dual_value[i]; } LpSoplex::Value LpSoplex::_getPrimalValue() { @@ -166,6 +213,7 @@ } LpSoplex::SolutionStatus LpSoplex::_getPrimalStatus() { + if (!solved) return UNDEFINED; switch (soplex->status()) { case soplex::SPxSolver::OPTIMAL: return OPTIMAL; @@ -179,30 +227,41 @@ } LpSoplex::SolutionStatus LpSoplex::_getDualStatus() { - switch (0) { - case 0: - return UNDEFINED; + if (!solved) return UNDEFINED; + switch (soplex->status()) { + case soplex::SPxSolver::OPTIMAL: return OPTIMAL; + case soplex::SPxSolver::UNBOUNDED: return INFEASIBLE; + default: return UNDEFINED; } } LpSoplex::ProblemTypes LpSoplex::_getProblemType() { - switch (0) { - case 0: + if (!solved) return UNKNOWN; + switch (soplex->status()) { + case soplex::SPxSolver::OPTIMAL: return PRIMAL_DUAL_FEASIBLE; + case soplex::SPxSolver::UNBOUNDED: return PRIMAL_FEASIBLE_DUAL_INFEASIBLE; + default: return UNKNOWN; } } void LpSoplex::_setMax() { soplex->changeSense(soplex::SPxSolver::MAXIMIZE); + solved = false; } void LpSoplex::_setMin() { soplex->changeSense(soplex::SPxSolver::MINIMIZE); + solved = false; } + bool LpSoplex::_isMax() { + return soplex->spxSense() == soplex::SPxSolver::MAXIMIZE; + } + } //namespace lemon diff -r eb37b9774ef6 -r 2aabce558574 lemon/lp_soplex.h --- a/lemon/lp_soplex.h Thu Feb 15 13:06:23 2007 +0000 +++ b/lemon/lp_soplex.h Thu Feb 15 14:22:08 2007 +0000 @@ -40,12 +40,15 @@ class LpSoplex :virtual public LpSolverBase { protected: + _lp_bits::RelocateIdHandler relocateIdHandler; + soplex::SoPlex* soplex; + bool solved; std::vector colNames; - std::vector primal; - std::vector dual; + std::vector primal_value; + std::vector dual_value; public: @@ -67,15 +70,20 @@ virtual int _addRow(); virtual void _eraseCol(int i); virtual void _eraseRow(int i); - virtual void _getColName(int col, std::string & name); + virtual void _getColName(int col, std::string & name); virtual void _setColName(int col, const std::string & name); virtual void _setRowCoeffs(int i, LpRowIterator b, LpRowIterator e); virtual void _setColCoeffs(int i, LpColIterator b, LpColIterator e); virtual void _setCoeff(int row, int col, Value value); + virtual Value _getCoeff(int row, int col); virtual void _setColLowerBound(int i, Value value); + virtual Value _getColLowerBound(int i); virtual void _setColUpperBound(int i, Value value); + virtual Value _getColUpperBound(int i); virtual void _setRowBounds(int i, Value lower, Value upper); + virtual void _getRowBounds(int i, Value &lower, Value &upper); virtual void _setObjCoeff(int i, Value obj_coef); + virtual Value _getObjCoeff(int i); virtual void _clearObj(); virtual SolveExitStatus _solve(); @@ -91,6 +99,7 @@ virtual void _setMax(); virtual void _setMin(); + virtual bool _isMax(); }; } //END OF NAMESPACE LEMON diff -r eb37b9774ef6 -r 2aabce558574 lemon/lp_utils.h --- a/lemon/lp_utils.h Thu Feb 15 13:06:23 2007 +0000 +++ b/lemon/lp_utils.h Thu Feb 15 14:22:08 2007 +0000 @@ -22,6 +22,7 @@ #include #include +#include namespace lemon { @@ -319,7 +320,6 @@ /// It reads the content of the section. virtual void read(std::istream& is) { std::string line; - std::map vars; while (getline(is, line)) { std::istringstream ls(line); std::string sense; @@ -359,6 +359,336 @@ ColMap cols; }; + +// class LpWriter : public LemonWriter::SectionWriter { +// typedef LemonWriter::SectionWriter Parent; +// public: + + +// /// \brief Constructor. +// /// +// /// Constructor for LpWriter. It creates the LpWriter and attach +// /// it into the given LemonWriter. The lp writer will add +// /// variables, constraints and objective function to the +// /// given lp solver. +// LpWriter(LemonWriter& _writer, LpSolverBase& _lp, +// const std::string& _name = std::string()) +// : Parent(_writer), lp(_lp), name(_name) {} + + +// /// \brief Destructor. +// /// +// /// Destructor for NodeSetWriter. +// virtual ~LpWriter() {} + +// private: +// LpWriter(const LpWriter&); +// void operator=(const LpWriter&); + +// protected: + +// /// \brief Gives back true when the SectionWriter can process +// /// the section with the given header line. +// /// +// /// It gives back the header line of the \c \@lp section. +// virtual std::string header() { +// std::ostringstream ls(line); +// ls << "@lp " << name; +// return ls.str(); +// } + +// private: + +// std::ostream& writeConstraint(std::ostream& is, LpSolverBase::Constr& c) { +// char x; + + +// LpSolverBase::Expr e1, e2; +// Relation op1; +// is >> std::ws; +// writexpression(is, e1); +// is >> std::ws; +// writeRelation(is, op1); +// is >> std::ws; +// writexpression(is, e2); +// if (!is.get(x)) { +// if (op1 == LE) { +// c = e1 <= e2; +// } else if (op1 == GE) { +// c = e1 >= e2; +// } else { +// c = e1 == e2; +// } +// } else { +// is.putback(x); +// LpSolverBase::Expr e3; +// Relation op2; +// writeRelation(is, op2); +// is >> std::ws; +// writexpression(is, e3); +// if (!e1.empty() || !e3.empty()) { +// throw DataFormatError("Wrong range format"); +// } +// if (op2 != op1 || op1 == EQ) { +// throw DataFormatError("Wrong range format"); +// } +// if (op1 == LE) { +// c = e1.constComp() <= e2 <= e3.constComp(); +// } else { +// c = e1.constComp() >= e2 >= e3.constComp(); +// } +// } +// } + +// std::ostream& writexpression(std::ostream& is, LpSolverBase::Expr& e) { +// LpSolverBase::Col c; +// double d; +// char x; +// writelement(is, c, d); +// if (c != INVALID) { +// e += d * c; +// } else { +// e += d; +// } +// is >> std::ws; +// while (is.get(x) && (x == '+' || x == '-')) { +// is >> std::ws; +// writelement(is, c, d); +// if (c != INVALID) { +// e += (x == '+' ? d : -d) * c; +// } else { +// e += (x == '+' ? d : -d); +// } +// is >> std::ws; +// } +// if (!is) { +// is.clear(); +// } else { +// is.putback(x); +// } +// return is; +// } + +// std::ostream& writelement(std::ostream& is, +// LpSolverBase::Col& c, double& d) { +// d = 1.0; +// c = INVALID; +// char x, y; +// if (!is.get(x)) throw DataFormatError("Cannot find lp element"); +// if (x == '+' || x == '-') { +// is >> std::ws; +// d *= x == '-' ? -1 : 1; +// while (is.get(x) && (x == '+' || x == '-')) { +// d *= x == '-' ? -1 : 1; +// is >> std::ws; +// } +// if (!is) throw DataFormatError("Cannot find lp element"); +// } +// if (numFirstChar(x)) { +// is.putback(x); +// double e; +// writeNum(is, e); +// d *= e; +// } else if (varFirstChar(x)) { +// is.putback(x); +// LpSolverBase::Col f; +// writeCol(is, f); +// c = f; +// } else { +// throw DataFormatError("Invalid expression format"); +// } +// is >> std::ws; +// while (is.get(y) && (y == '*' || y == '/')) { +// is >> std::ws; +// if (!is.get(x)) throw DataFormatError("Cannot find lp element"); +// if (x == '+' || x == '-') { +// is >> std::ws; +// d *= x == '-' ? -1 : 1; +// while (is.get(x) && (x == '+' || x == '-')) { +// d *= x == '-' ? -1 : 1; +// is >> std::ws; +// } +// if (!is) throw DataFormatError("Cannot find lp element"); +// } +// if (numFirstChar(x)) { +// is.putback(x); +// double e; +// writeNum(is, e); +// if (y == '*') { +// d *= e; +// } else { +// d /= e; +// } +// } else if (varFirstChar(x)) { +// is.putback(x); +// LpSolverBase::Col f; +// writeCol(is, f); +// if (y == '*') { +// if (c == INVALID) { +// c = f; +// } else { +// throw DataFormatError("Quadratic element in expression"); +// } +// } else { +// throw DataFormatError("Division by variable"); +// } +// } else { +// throw DataFormatError("Invalid expression format"); +// } +// is >> std::ws; +// } +// if (!is) { +// is.clear(); +// } else { +// is.putback(y); +// } +// return is; +// } + +// std::ostream& writeCol(std::ostream& is, LpSolverBase::Col& c) { +// char x; +// std::string var; +// while (is.get(x) && varChar(x)) { +// var += x; +// } +// if (!is) { +// is.clear(); +// } else { +// is.putback(x); +// } +// ColMap::const_iterator it = cols.find(var); +// if (cols.find(var) != cols.end()) { +// c = it->second; +// } else { +// c = lp.addCol(); +// cols.insert(std::make_pair(var, c)); +// lp.colName(c, var); +// } +// return is; +// } + +// std::ostream& writeNum(std::ostream& is, double& d) { +// is >> d; +// if (!is) throw DataFormatError("Wrong number format"); +// return is; +// } + +// std::ostream& writeRelation(std::ostream& is, Relation& op) { +// char x, y; +// if (!is.get(x) || !(x == '<' || x == '=' || x == '>')) { +// throw DataFormatError("Wrong relation operator"); +// } +// if (!is.get(y) || y != '=') { +// throw DataFormatError("Wrong relation operator"); +// } +// switch (x) { +// case '<': op = LE; +// break; +// case '=': op = EQ; +// break; +// case '>': op = GE; +// break; +// } +// return is; +// } + +// static bool relationFirstChar(char c) { +// return c == '<' || c == '=' || c == '>'; +// } + +// static bool varFirstChar(char c) { +// return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); +// } + +// static bool numFirstChar(char c) { +// return (c >= '0' && c <= '9') || c == '.'; +// } + +// static bool varChar(char c) { +// return (c >= '0' && c <= '9') || +// (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); +// } + + +// void addConstraint(const LpSolverBase::Constr& constr) { +// if (constr.expr().size() != 1) { +// lp.addRow(constr); +// } else { +// Lp::Expr e = constr.expr(); +// LpSolverBase::Col col = e.begin()->first; +// double coeff = e.begin()->second; +// double lb = LpSolverBase::NaN; +// double ub = LpSolverBase::NaN; +// if (coeff > 0) { +// if (constr.upperBounded()) { +// lb = (constr.lowerBound() - e.constComp()) / coeff; +// } +// if (constr.lowerBounded()) { +// ub = (constr.upperBound() - e.constComp()) / coeff; +// } +// } else if (coeff < 0) { +// if (constr.upperBounded()) { +// lb = (constr.upperBound() - e.constComp()) / coeff; +// } +// if (constr.lowerBounded()) { +// ub = (constr.lowerBound() - e.constComp()) / coeff; +// } +// } else { +// lb = -LpSolverBase::INF; +// ub = LpSolverBase::INF; +// } +// lp.colLowerBound(col, lb); +// lp.colUpperBound(col, ub); +// } +// } + +// protected: + +// /// \brief Writer function of the section. +// /// +// /// It writes the content of the section. +// virtual void write(std::ostream& is) { +// std::string line; +// std::map vars; +// while (getline(is, line)) { +// std::istringstream ls(line); +// std::string sense; +// ls >> sense; +// if (sense == "min" || sense == "max") { +// LpSolverBase::Expr expr; +// ls >> std::ws; +// writeExpression(ls, expr); +// lp.setObj(expr); +// if (sense == "min") { +// lp.min(); +// } else { +// lp.max(); +// } +// } else { +// ls.str(line); +// LpSolverBase::Constr constr; +// ls >> std::ws; +// writeConstraint(ls, constr); +// addConstraint(constr); +// } +// } +// } + +// virtual void missing() { +// ErrorMessage msg; +// msg << "Lp section not found in file: @lp " << name; +// throw IoParameterError(msg.message()); +// } + +// private: + +// typedef std::map ColMap; + +// LpSolverBase& lp; +// std::string name; +// ColMap cols; +// }; + } #endif diff -r eb37b9774ef6 -r 2aabce558574 m4/lx_check_soplex.m4 --- a/m4/lx_check_soplex.m4 Thu Feb 15 13:06:23 2007 +0000 +++ b/m4/lx_check_soplex.m4 Thu Feb 15 14:22:08 2007 +0000 @@ -18,9 +18,9 @@ AC_MSG_CHECKING([for SOPLEX]) if test x"$with_soplex_includedir" != x"no"; then - SOPLEX_CFLAGS="-I$with_soplex_includedir" + SOPLEX_CXXFLAGS="-I$with_soplex_includedir" elif test x"$with_soplex" != x"yes"; then - SOPLEX_CFLAGS="-I$with_soplex/include" + SOPLEX_CXXFLAGS="-I$with_soplex/include" fi if test x"$with_soplex_libdir" != x"no"; then @@ -33,7 +33,7 @@ lx_save_cxxflags="$CXXFLAGS" lx_save_ldflags="$LDFLAGS" lx_save_libs="$LIBS" - CXXFLAGS="$SOPLEX_CFLAGS" + CXXFLAGS="$SOPLEX_CXXFLAGS" LDFLAGS="$SOPLEX_LDFLAGS" LIBS="$SOPLEX_LIBS" @@ -58,14 +58,14 @@ AC_DEFINE([HAVE_SOPLEX], [1], [Define to 1 if you have SOPLEX.]) AC_MSG_RESULT([yes]) else - SOPLEX_CFLAGS="" + SOPLEX_CXXFLAGS="" SOPLEX_LDFLAGS="" SOPLEX_LIBS="" AC_MSG_RESULT([no]) fi fi SOPLEX_LIBS="$SOPLEX_LDFLAGS $SOPLEX_LIBS" - AC_SUBST(SOPLEX_CFLAGS) + AC_SUBST(SOPLEX_CXXFLAGS) AC_SUBST(SOPLEX_LIBS) AM_CONDITIONAL([HAVE_SOPLEX], [test x"$lx_soplex_found" = x"yes"]) ]) diff -r eb37b9774ef6 -r 2aabce558574 test/Makefile.am --- a/test/Makefile.am Thu Feb 15 13:06:23 2007 +0000 +++ b/test/Makefile.am Thu Feb 15 14:22:08 2007 +0000 @@ -49,7 +49,11 @@ else !HAVE_GLPK if HAVE_CPLEX check_PROGRAMS += test/lp_test test/mip_test -endif HAVE_CPLEX +else !HAVE_CPLEX +if HAVE_SOPLEX +check_PROGRAMS += test/lp_test +endif HAVE_SOPLEX +endif !HAVE_CPLEX endif !HAVE_GLPK TESTS += $(check_PROGRAMS) @@ -89,6 +93,6 @@ test_unionfind_test_SOURCES = test/unionfind_test.cc test_lp_test_SOURCES = test/lp_test.cc -test_lp_test_CXXFLAGS = $(GLPK_CFLAGS) $(CPLEX_CFLAGS) +test_lp_test_CXXFLAGS = $(GLPK_CFLAGS) $(CPLEX_CFLAGS) $(SOPLEX_CXXFLAGS) test_mip_test_SOURCES = test/mip_test.cc -test_mip_test_CXXFLAGS = $(GLPK_CFLAGS) $(CPLEX_CFLAGS) \ No newline at end of file +test_mip_test_CXXFLAGS = $(GLPK_CFLAGS) $(CPLEX_CFLAGS) $(SOPLEX_CXXFLAGS) \ No newline at end of file diff -r eb37b9774ef6 -r 2aabce558574 test/lp_test.cc --- a/test/lp_test.cc Thu Feb 15 13:06:23 2007 +0000 +++ b/test/lp_test.cc Thu Feb 15 14:22:08 2007 +0000 @@ -33,9 +33,9 @@ #include #endif -// #ifdef HAVE_SOPLEX -// #include -// #endif +#ifdef HAVE_SOPLEX +#include +#endif using namespace lemon; @@ -374,11 +374,11 @@ aTest(lp_cplex2); #endif -// #ifdef HAVE_SOPLEX -// LpSoplex lp_soplex1,lp_soplex2; -// lpTest(lp_soplex1); -// aTest(lp_soplex2); -// #endif +#ifdef HAVE_SOPLEX + LpSoplex lp_soplex1,lp_soplex2; + lpTest(lp_soplex1); + aTest(lp_soplex2); +#endif return 0; }