[Lemon-commits] deba: r3174 - in hugo/trunk: lemon lemon/bits m4 test
Lemon SVN
svn at lemon.cs.elte.hu
Thu Feb 15 15:22:09 CET 2007
Author: deba
Date: Thu Feb 15 15:22:08 2007
New Revision: 3174
Added:
hugo/trunk/lemon/bits/lp_id.h
Modified:
hugo/trunk/lemon/Makefile.am
hugo/trunk/lemon/lp_base.h
hugo/trunk/lemon/lp_cplex.cc
hugo/trunk/lemon/lp_glpk.cc
hugo/trunk/lemon/lp_skeleton.h
hugo/trunk/lemon/lp_soplex.cc
hugo/trunk/lemon/lp_soplex.h
hugo/trunk/lemon/lp_utils.h
hugo/trunk/m4/lx_check_soplex.m4
hugo/trunk/test/Makefile.am
hugo/trunk/test/lp_test.cc
Log:
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
Modified: hugo/trunk/lemon/Makefile.am
==============================================================================
--- hugo/trunk/lemon/Makefile.am (original)
+++ hugo/trunk/lemon/Makefile.am Thu Feb 15 15:22:08 2007
@@ -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 \
Added: hugo/trunk/lemon/bits/lp_id.h
==============================================================================
--- (empty file)
+++ hugo/trunk/lemon/bits/lp_id.h Thu Feb 15 15:22:08 2007
@@ -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<int> index;
+ std::vector<int> 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
Modified: hugo/trunk/lemon/lp_base.h
==============================================================================
--- hugo/trunk/lemon/lp_base.h (original)
+++ hugo/trunk/lemon/lp_base.h Thu Feb 15 15:22:08 2007
@@ -27,93 +27,16 @@
#include<limits>
#include<cmath>
-#include<lemon/bits/utility.h>
#include<lemon/error.h>
#include<lemon/bits/invalid.h>
+#include<lemon/bits/utility.h>
+#include<lemon/bits/lp_id.h>
///\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<int> index;
- std::vector<int> 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;i<int(cross.size());++i) {
- cross[i-1]=cross[i];
- index[cross[i]]--;
- }
- cross.pop_back();
- }
- ///An upper bound on the largest fix id.
-
- ///\todo Do we need this?
- ///
- std::size_t maxFixId() { return cross.size()-1; }
-
- ///Returns the first (smallest) inserted index
-
- ///Returns the first (smallest) inserted index
- ///or -1 if no index has been inserted before.
- int firstIndex() {return _first_index;}
- };
-
///Common base class for LP solvers
///\todo Much more docs
@@ -121,9 +44,10 @@
class LpSolverBase {
protected:
- _FixId rows;
- _FixId cols;
+ _lp_bits::LpId rows;
+ _lp_bits::LpId cols;
+
public:
///Possible outcomes of an LP solving procedure
@@ -215,14 +139,12 @@
ColIt() {}
ColIt(LpSolverBase &lp) : _lp(&lp)
{
- id = _lp->cols.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);
}
Modified: hugo/trunk/lemon/lp_cplex.cc
==============================================================================
--- hugo/trunk/lemon/lp_cplex.cc (original)
+++ hugo/trunk/lemon/lp_cplex.cc Thu Feb 15 15:22:08 2007
@@ -24,7 +24,6 @@
namespace lemon {
LpCplex::LpCplex() : LpSolverBase() {
-
// env = CPXopenCPLEXdevelop(&status);
env = CPXopenCPLEX(&status);
lp = CPXcreateprob(env, &status, "LP problem");
Modified: hugo/trunk/lemon/lp_glpk.cc
==============================================================================
--- hugo/trunk/lemon/lp_glpk.cc (original)
+++ hugo/trunk/lemon/lp_glpk.cc Thu Feb 15 15:22:08 2007
@@ -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;
Modified: hugo/trunk/lemon/lp_skeleton.h
==============================================================================
--- hugo/trunk/lemon/lp_skeleton.h (original)
+++ hugo/trunk/lemon/lp_skeleton.h Thu Feb 15 15:22:08 2007
@@ -30,6 +30,7 @@
int col_num,row_num;
protected:
+
///\e
virtual LpSolverBase &_newLp();
///\e
Modified: hugo/trunk/lemon/lp_soplex.cc
==============================================================================
--- hugo/trunk/lemon/lp_soplex.cc (original)
+++ hugo/trunk/lemon/lp_soplex.cc Thu Feb 15 15:22:08 2007
@@ -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
Modified: hugo/trunk/lemon/lp_soplex.h
==============================================================================
--- hugo/trunk/lemon/lp_soplex.h (original)
+++ hugo/trunk/lemon/lp_soplex.h Thu Feb 15 15:22:08 2007
@@ -40,12 +40,15 @@
class LpSoplex :virtual public LpSolverBase {
protected:
+ _lp_bits::RelocateIdHandler relocateIdHandler;
+
soplex::SoPlex* soplex;
+ bool solved;
std::vector<std::string> colNames;
- std::vector<Value> primal;
- std::vector<Value> dual;
+ std::vector<Value> primal_value;
+ std::vector<Value> 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
Modified: hugo/trunk/lemon/lp_utils.h
==============================================================================
--- hugo/trunk/lemon/lp_utils.h (original)
+++ hugo/trunk/lemon/lp_utils.h Thu Feb 15 15:22:08 2007
@@ -22,6 +22,7 @@
#include <lemon/lp_base.h>
#include <lemon/lemon_reader.h>
+#include <lemon/lemon_writer.h>
namespace lemon {
@@ -319,7 +320,6 @@
/// It reads the content of the section.
virtual void read(std::istream& is) {
std::string line;
- std::map<std::string, LpSolverBase::Col> 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<std::string, LpSolverBase::Col> 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<std::string, LpSolverBase::Col> ColMap;
+
+// LpSolverBase& lp;
+// std::string name;
+// ColMap cols;
+// };
+
}
#endif
Modified: hugo/trunk/m4/lx_check_soplex.m4
==============================================================================
--- hugo/trunk/m4/lx_check_soplex.m4 (original)
+++ hugo/trunk/m4/lx_check_soplex.m4 Thu Feb 15 15:22:08 2007
@@ -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"])
])
Modified: hugo/trunk/test/Makefile.am
==============================================================================
--- hugo/trunk/test/Makefile.am (original)
+++ hugo/trunk/test/Makefile.am Thu Feb 15 15:22:08 2007
@@ -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
Modified: hugo/trunk/test/lp_test.cc
==============================================================================
--- hugo/trunk/test/lp_test.cc (original)
+++ hugo/trunk/test/lp_test.cc Thu Feb 15 15:22:08 2007
@@ -33,9 +33,9 @@
#include <lemon/lp_cplex.h>
#endif
-// #ifdef HAVE_SOPLEX
-// #include <lemon/lp_soplex.h>
-// #endif
+#ifdef HAVE_SOPLEX
+#include <lemon/lp_soplex.h>
+#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;
}
More information about the Lemon-commits
mailing list