Changes on the LP interface
authordeba
Thu, 15 Feb 2007 14:22:08 +0000
changeset 23632aabce558574
parent 2362 eb37b9774ef6
child 2364 3a5e67bd42d2
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
lemon/Makefile.am
lemon/bits/lp_id.h
lemon/lp_base.h
lemon/lp_cplex.cc
lemon/lp_glpk.cc
lemon/lp_skeleton.h
lemon/lp_soplex.cc
lemon/lp_soplex.h
lemon/lp_utils.h
m4/lx_check_soplex.m4
test/Makefile.am
test/lp_test.cc
     1.1 --- a/lemon/Makefile.am	Thu Feb 15 13:06:23 2007 +0000
     1.2 +++ b/lemon/Makefile.am	Thu Feb 15 14:22:08 2007 +0000
     1.3 @@ -15,8 +15,8 @@
     1.4  	lemon/bits/mingw32_time.cc \
     1.5  	lemon/random.cc
     1.6  
     1.7 -lemon_libemon_la_CXXFLAGS = $(GLPK_CFLAGS) $(CPLEX_CFLAGS) $(SOPLEX_CFLAGS)
     1.8 -lemon_libemon_la_LDFLAGS = $(GLPK_LIBS) $(CPLEX_LIBS) $(SOPLEX_CFLAGS)
     1.9 +lemon_libemon_la_CXXFLAGS = $(GLPK_CFLAGS) $(CPLEX_CFLAGS) $(SOPLEX_CXXFLAGS)
    1.10 +lemon_libemon_la_LDFLAGS = $(GLPK_LIBS) $(CPLEX_LIBS) $(SOPLEX_LIBS)
    1.11  
    1.12  if HAVE_GLPK
    1.13  lemon_libemon_la_SOURCES += lemon/lp_glpk.cc
    1.14 @@ -123,6 +123,7 @@
    1.15  	lemon/bits/invalid.h \
    1.16  	lemon/bits/item_reader.h \
    1.17  	lemon/bits/item_writer.h \
    1.18 +	lemon/bits/lp_id.h \
    1.19  	lemon/bits/map_extender.h \
    1.20  	lemon/bits/mingw32_time.h \
    1.21  	lemon/bits/path_dump.h \
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/lemon/bits/lp_id.h	Thu Feb 15 14:22:08 2007 +0000
     2.3 @@ -0,0 +1,146 @@
     2.4 +/* -*- C++ -*-
     2.5 + *
     2.6 + * This file is a part of LEMON, a generic C++ optimization library
     2.7 + *
     2.8 + * Copyright (C) 2003-2006
     2.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
    2.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
    2.11 + *
    2.12 + * Permission to use, modify and distribute this software is granted
    2.13 + * provided that this copyright notice appears in all copies. For
    2.14 + * precise terms see the accompanying LICENSE file.
    2.15 + *
    2.16 + * This software is provided "AS IS" with no warranty of any kind,
    2.17 + * express or implied, and with no claim as to its suitability for any
    2.18 + * purpose.
    2.19 + *
    2.20 + */
    2.21 +
    2.22 +#ifndef LEMON_BITS_LP_SOLVER_ID_H
    2.23 +#define LEMON_BITS_LP_SOLVER_ID_H
    2.24 +
    2.25 +namespace lemon {
    2.26 +  
    2.27 +  namespace _lp_bits {
    2.28 +
    2.29 +    struct LpIdImpl {
    2.30 +      std::vector<int> index;
    2.31 +      std::vector<int> cross;
    2.32 +      int first_index;
    2.33 +      int first_free;      
    2.34 +    };
    2.35 +
    2.36 +    class LpId {
    2.37 +    public:
    2.38 +      
    2.39 +      class IdHandler {
    2.40 +      public:
    2.41 +        virtual ~IdHandler() {}
    2.42 +        virtual int addId(LpIdImpl&) = 0;
    2.43 +        virtual void eraseId(LpIdImpl&, int xn) = 0;
    2.44 +      };
    2.45 +      
    2.46 +      LpId(int min_index = 0) {
    2.47 +        id_handler = 0;
    2.48 +        impl.first_free = -1;
    2.49 +        impl.first_index = min_index;
    2.50 +        impl.cross.resize(impl.first_index);
    2.51 +      }
    2.52 +
    2.53 +      void setIdHandler(IdHandler& ih) {
    2.54 +        id_handler = &ih;
    2.55 +      }
    2.56 +      
    2.57 +      int fixId(int fn) const {return impl.cross[fn];}
    2.58 +      int floatingId(int xn) const {return impl.index[xn];}
    2.59 +      
    2.60 +      int addId() {
    2.61 +        if (id_handler == 0) {
    2.62 +          int xn, fn = impl.cross.size();
    2.63 +          if (impl.first_free == -1) {
    2.64 +            xn = impl.index.size();
    2.65 +            impl.index.push_back(fn);
    2.66 +          } else {
    2.67 +            xn = impl.first_free;
    2.68 +            impl.first_free = impl.index[impl.first_free];
    2.69 +            impl.index[xn] = fn;
    2.70 +          }
    2.71 +          impl.cross.push_back(xn);
    2.72 +          return xn;
    2.73 +        } else {
    2.74 +          return id_handler->addId(impl);
    2.75 +        }
    2.76 +      }
    2.77 +
    2.78 +      void eraseId(int xn) {
    2.79 +        if (id_handler == 0) {
    2.80 +          int fn = impl.index[xn];
    2.81 +          impl.index[xn] = impl.first_free;
    2.82 +          impl.first_free = xn;
    2.83 +          for(int i = fn + 1; i < (int)impl.cross.size(); ++i) {
    2.84 +            impl.cross[i - 1] = impl.cross[i];
    2.85 +            impl.index[impl.cross[i]]--;
    2.86 +          }
    2.87 +          impl.cross.pop_back();
    2.88 +        } else {
    2.89 +          id_handler->eraseId(impl, xn);
    2.90 +        }
    2.91 +      }
    2.92 +
    2.93 +      void firstFloating(int& fn) const {
    2.94 +        fn = impl.first_index;
    2.95 +        if (fn == (int)impl.cross.size()) fn = -1;
    2.96 +      }
    2.97 +
    2.98 +      void nextFloating(int& fn) const {
    2.99 +        ++fn;
   2.100 +        if (fn == (int)impl.cross.size()) fn = -1;
   2.101 +      }
   2.102 +
   2.103 +      void firstFix(int& xn) const {
   2.104 +        int fn;
   2.105 +        firstFloating(fn);
   2.106 +        xn = fn != -1 ? fixId(fn) : -1;
   2.107 +      }
   2.108 +      
   2.109 +      void nextFix(int& xn) const {
   2.110 +        int fn = floatingId(xn);
   2.111 +        nextFloating(fn);
   2.112 +        xn = fn != -1 ? fixId(fn) : -1;    
   2.113 +      }
   2.114 +
   2.115 +    protected:
   2.116 +      LpIdImpl impl;
   2.117 +      IdHandler *id_handler;
   2.118 +    };
   2.119 +  
   2.120 +    class RelocateIdHandler : public LpId::IdHandler {
   2.121 +    public:
   2.122 +
   2.123 +      virtual int addId(LpIdImpl& impl) {
   2.124 +        int xn, fn = impl.cross.size();
   2.125 +        if (impl.first_free == -1) {
   2.126 +          xn = impl.index.size();
   2.127 +          impl.index.push_back(fn);
   2.128 +        } else {
   2.129 +          xn = impl.first_free;
   2.130 +          impl.first_free = impl.index[impl.first_free];
   2.131 +          impl.index[xn] = fn;
   2.132 +        }
   2.133 +        impl.cross.push_back(xn);
   2.134 +        return xn;
   2.135 +      }
   2.136 +
   2.137 +      virtual void eraseId(LpIdImpl& impl, int xn) {
   2.138 +        int fn = impl.index[xn];
   2.139 +        impl.index[xn] = impl.first_free;
   2.140 +        impl.first_free = xn;
   2.141 +        impl.cross[fn] = impl.cross.back();
   2.142 +        impl.index[impl.cross.back()] = fn;
   2.143 +        impl.cross.pop_back();
   2.144 +      }
   2.145 +    };
   2.146 +  }  
   2.147 +}
   2.148 +
   2.149 +#endif
     3.1 --- a/lemon/lp_base.h	Thu Feb 15 13:06:23 2007 +0000
     3.2 +++ b/lemon/lp_base.h	Thu Feb 15 14:22:08 2007 +0000
     3.3 @@ -27,93 +27,16 @@
     3.4  #include<limits>
     3.5  #include<cmath>
     3.6  
     3.7 -#include<lemon/bits/utility.h>
     3.8  #include<lemon/error.h>
     3.9  #include<lemon/bits/invalid.h>
    3.10 +#include<lemon/bits/utility.h>
    3.11 +#include<lemon/bits/lp_id.h>
    3.12  
    3.13  ///\file
    3.14  ///\brief The interface of the LP solver interface.
    3.15  ///\ingroup gen_opt_group
    3.16  namespace lemon {
    3.17  
    3.18 -
    3.19 -  ///Internal data structure to convert floating id's to fix one's
    3.20 -    
    3.21 -  ///\todo This might be implemented to be also usable in other places.
    3.22 -  class _FixId 
    3.23 -  {
    3.24 -  protected:
    3.25 -    int _first_index;
    3.26 -    int first_free;
    3.27 -  public:
    3.28 -    std::vector<int> index;
    3.29 -    std::vector<int> cross;
    3.30 -    _FixId() : _first_index(-1), first_free(-1) {};
    3.31 -    ///Convert a floating id to a fix one
    3.32 -
    3.33 -    ///\param n is a floating id
    3.34 -    ///\return the corresponding fix id
    3.35 -    int fixId(int n) const {return cross[n];}
    3.36 -    ///Convert a fix id to a floating one
    3.37 -
    3.38 -    ///\param n is a fix id
    3.39 -    ///\return the corresponding floating id
    3.40 -    int floatingId(int n) const { return index[n];}
    3.41 -    ///Add a new floating id.
    3.42 -
    3.43 -    ///\param n is a floating id
    3.44 -    ///\return the fix id of the new value
    3.45 -    ///\todo Multiple additions should also be handled.
    3.46 -    int insert(int n)
    3.47 -    {
    3.48 -      if(cross.empty()) _first_index=n;
    3.49 -      if(n>=int(cross.size())) {
    3.50 -	cross.resize(n+1);
    3.51 -	if(first_free==-1) {
    3.52 -	  cross[n]=index.size();
    3.53 -	  index.push_back(n);
    3.54 -	}
    3.55 -	else {
    3.56 -	  cross[n]=first_free;
    3.57 -	  int next=index[first_free];
    3.58 -	  index[first_free]=n;
    3.59 -	  first_free=next;
    3.60 -	}
    3.61 -	return cross[n];
    3.62 -      }
    3.63 -      else {
    3.64 -	///\todo Create an own exception type.
    3.65 -	throw LogicError(); //floatingId-s must form a continuous range;
    3.66 -      }
    3.67 -    }
    3.68 -    ///Remove a fix id.
    3.69 -
    3.70 -    ///\param n is a fix id
    3.71 -    ///
    3.72 -    void erase(int n) 
    3.73 -    {
    3.74 -      int fl=index[n];
    3.75 -      index[n]=first_free;
    3.76 -      first_free=n;
    3.77 -      for(int i=fl+1;i<int(cross.size());++i) {
    3.78 -	cross[i-1]=cross[i];
    3.79 -	index[cross[i]]--;
    3.80 -      }
    3.81 -      cross.pop_back();
    3.82 -    }
    3.83 -    ///An upper bound on the largest fix id.
    3.84 -
    3.85 -    ///\todo Do we need this?
    3.86 -    ///
    3.87 -    std::size_t maxFixId() { return cross.size()-1; }
    3.88 -  
    3.89 -    ///Returns the first (smallest) inserted index
    3.90 -
    3.91 -    ///Returns the first (smallest) inserted index
    3.92 -    ///or -1 if no index has been inserted before.
    3.93 -    int firstIndex() {return _first_index;}
    3.94 -  };
    3.95 -
    3.96    ///Common base class for LP solvers
    3.97    
    3.98    ///\todo Much more docs
    3.99 @@ -121,9 +44,10 @@
   3.100    class LpSolverBase {
   3.101  
   3.102    protected:
   3.103 -    _FixId rows;
   3.104 -    _FixId cols;
   3.105  
   3.106 +    _lp_bits::LpId rows;
   3.107 +    _lp_bits::LpId cols;
   3.108 +    
   3.109    public:
   3.110  
   3.111      ///Possible outcomes of an LP solving procedure
   3.112 @@ -215,14 +139,12 @@
   3.113        ColIt() {}
   3.114        ColIt(LpSolverBase &lp) : _lp(&lp)
   3.115        {
   3.116 -	id = _lp->cols.cross.empty()?-1:
   3.117 -	  _lp->cols.fixId(_lp->cols.firstIndex());
   3.118 +        _lp->cols.firstFix(id);
   3.119        }
   3.120        ColIt(const Invalid&) : Col(INVALID) {}
   3.121        ColIt &operator++() 
   3.122        {
   3.123 -	int fid = _lp->cols.floatingId(id)+1;
   3.124 -	id = unsigned(fid)<_lp->cols.cross.size() ? _lp->cols.fixId(fid) : -1;
   3.125 +        _lp->cols.nextFix(id);
   3.126  	return *this;
   3.127        }
   3.128      };
   3.129 @@ -746,8 +668,6 @@
   3.130      virtual Value _getColLowerBound(int i) = 0;
   3.131      virtual void _setColUpperBound(int i, Value value) = 0;
   3.132      virtual Value _getColUpperBound(int i) = 0;
   3.133 -//     virtual void _setRowLowerBound(int i, Value value) = 0;
   3.134 -//     virtual void _setRowUpperBound(int i, Value value) = 0;
   3.135      virtual void _setRowBounds(int i, Value lower, Value upper) = 0;
   3.136      virtual void _getRowBounds(int i, Value &lower, Value &upper)=0;
   3.137  
   3.138 @@ -795,7 +715,7 @@
   3.139      ///@{
   3.140  
   3.141      ///Add a new empty column (i.e a new variable) to the LP
   3.142 -    Col addCol() { Col c; c.id=cols.insert(_addCol()); return c;}
   3.143 +    Col addCol() { Col c; _addCol(); c.id = cols.addId(); return c;}
   3.144  
   3.145      ///\brief Adds several new columns
   3.146      ///(i.e a variables) at once
   3.147 @@ -887,7 +807,7 @@
   3.148  
   3.149      ///This function adds a new empty row (i.e a new constraint) to the LP.
   3.150      ///\return The created row
   3.151 -    Row addRow() { Row r; r.id=rows.insert(_addRow()); return r;}
   3.152 +    Row addRow() { Row r; _addRow(); r.id = rows.addId(); return r;}
   3.153  
   3.154      ///\brief Add several new rows
   3.155      ///(i.e a constraints) at once
   3.156 @@ -965,8 +885,6 @@
   3.157        e.simplify();
   3.158        _setRowCoeffs(_lpId(r), LpRowIterator(e.begin(), *this),
   3.159                      LpRowIterator(e.end(), *this));
   3.160 -//       _setRowLowerBound(_lpId(r),l-e.constComp());
   3.161 -//       _setRowUpperBound(_lpId(r),u-e.constComp());
   3.162         _setRowBounds(_lpId(r),l-e.constComp(),u-e.constComp());
   3.163      }
   3.164  
   3.165 @@ -1008,7 +926,7 @@
   3.166      ///\todo Please check this
   3.167      void eraseCol(Col c) {
   3.168        _eraseCol(_lpId(c));
   3.169 -      cols.erase(c.id);
   3.170 +      cols.eraseId(c.id);
   3.171      }
   3.172      ///Erase a  row (i.e a constraint) from the LP
   3.173  
   3.174 @@ -1016,7 +934,7 @@
   3.175      ///\todo Please check this
   3.176      void eraseRow(Row r) {
   3.177        _eraseRow(_lpId(r));
   3.178 -      rows.erase(r.id);
   3.179 +      rows.eraseId(r.id);
   3.180      }
   3.181  
   3.182      /// Get the name of a column
   3.183 @@ -1216,31 +1134,14 @@
   3.184      }
   3.185  #endif
   3.186      
   3.187 -//     /// Set the lower bound of a row (i.e a constraint)
   3.188 -
   3.189 -//     /// The lower bound of a linear expression (row) has to be given by an 
   3.190 -//     /// extended number of type Value, i.e. a finite number of type 
   3.191 -//     /// Value or -\ref INF.
   3.192 -//     void rowLowerBound(Row r, Value value) {
   3.193 -//       _setRowLowerBound(_lpId(r),value);
   3.194 -//     };
   3.195 -//     /// Set the upper bound of a row (i.e a constraint)
   3.196 -
   3.197 -//     /// The upper bound of a linear expression (row) has to be given by an 
   3.198 -//     /// extended number of type Value, i.e. a finite number of type 
   3.199 -//     /// Value or \ref INF.
   3.200 -//     void rowUpperBound(Row r, Value value) {
   3.201 -//       _setRowUpperBound(_lpId(r),value);
   3.202 -//     };
   3.203  
   3.204      /// Set the lower and the upper bounds of a row (i.e a constraint)
   3.205  
   3.206 -    /// The lower and the upper bound of
   3.207 -    /// a constraint (row) have to be given by an 
   3.208 -    /// extended number of type Value, i.e. a finite number of type 
   3.209 -    /// Value, -\ref INF or \ref INF. There is no separate function for the 
   3.210 -    /// lower and the upper bound because that would have been hard to implement 
   3.211 -    /// for CPLEX.
   3.212 +    /// The lower and the upper bound of a constraint (row) have to be
   3.213 +    /// given by an extended number of type Value, i.e. a finite
   3.214 +    /// number of type Value, -\ref INF or \ref INF. There is no
   3.215 +    /// separate function for the lower and the upper bound because
   3.216 +    /// that would have been hard to implement for CPLEX.
   3.217      void rowBounds(Row c, Value lower, Value upper) {
   3.218        _setRowBounds(_lpId(c),lower, upper);
   3.219      }
     4.1 --- a/lemon/lp_cplex.cc	Thu Feb 15 13:06:23 2007 +0000
     4.2 +++ b/lemon/lp_cplex.cc	Thu Feb 15 14:22:08 2007 +0000
     4.3 @@ -24,7 +24,6 @@
     4.4  namespace lemon {
     4.5    
     4.6    LpCplex::LpCplex() : LpSolverBase() {
     4.7 -
     4.8      //    env = CPXopenCPLEXdevelop(&status);     
     4.9      env = CPXopenCPLEX(&status);     
    4.10      lp = CPXcreateprob(env, &status, "LP problem");
     5.1 --- a/lemon/lp_glpk.cc	Thu Feb 15 13:06:23 2007 +0000
     5.2 +++ b/lemon/lp_glpk.cc	Thu Feb 15 14:22:08 2007 +0000
     5.3 @@ -24,16 +24,20 @@
     5.4  namespace lemon {
     5.5  
     5.6  
     5.7 -  LpGlpk::LpGlpk() : Parent(), 
     5.8 -		     lp(lpx_create_prob()) {
     5.9 -    ///\todo constrol function for this:
    5.10 +  LpGlpk::LpGlpk() : Parent() {
    5.11 +    rows = _lp_bits::LpId(1);
    5.12 +    cols = _lp_bits::LpId(1);
    5.13 +    lp = lpx_create_prob();
    5.14 +    ///\todo control function for this:
    5.15      lpx_set_int_parm(lp, LPX_K_DUAL, 1);
    5.16      messageLevel(0);
    5.17    }
    5.18    
    5.19 -  LpGlpk::LpGlpk(const LpGlpk &glp) : Parent(glp), 
    5.20 -				      lp(lpx_create_prob()) {
    5.21 -    ///\todo constrol function for this:
    5.22 +  LpGlpk::LpGlpk(const LpGlpk &glp) : Parent() {
    5.23 +    rows = _lp_bits::LpId(1);
    5.24 +    cols = _lp_bits::LpId(1);
    5.25 +    lp = lpx_create_prob();
    5.26 +    ///\todo control function for this:
    5.27      lpx_set_int_parm(lp, LPX_K_DUAL, 1);
    5.28      messageLevel(0);
    5.29      //Coefficient matrix, row bounds
    5.30 @@ -349,92 +353,6 @@
    5.31        }
    5.32    }
    5.33    
    5.34 -//   void LpGlpk::_setRowLowerBound(int i, Value lo)
    5.35 -//   {
    5.36 -//     if (lo==INF) {
    5.37 -//       //FIXME error
    5.38 -//     }
    5.39 -//     int b=lpx_get_row_type(lp, i);
    5.40 -//     double up=lpx_get_row_ub(lp, i);	
    5.41 -//     if (lo==-INF) {
    5.42 -//       switch (b) {
    5.43 -//       case LPX_FR:
    5.44 -//       case LPX_LO:
    5.45 -// 	lpx_set_row_bnds(lp, i, LPX_FR, lo, up);
    5.46 -// 	break;
    5.47 -//       case LPX_UP:
    5.48 -// 	break;
    5.49 -//       case LPX_DB:
    5.50 -//       case LPX_FX:
    5.51 -// 	lpx_set_row_bnds(lp, i, LPX_UP, lo, up);
    5.52 -// 	break;
    5.53 -//       default: ;
    5.54 -// 	//FIXME error
    5.55 -//       }
    5.56 -//     } else {
    5.57 -//       switch (b) {
    5.58 -//       case LPX_FR:
    5.59 -//       case LPX_LO:
    5.60 -// 	lpx_set_row_bnds(lp, i, LPX_LO, lo, up);
    5.61 -// 	break;
    5.62 -//       case LPX_UP:	  
    5.63 -//       case LPX_DB:
    5.64 -//       case LPX_FX:
    5.65 -// 	if (lo==up) 
    5.66 -// 	  lpx_set_row_bnds(lp, i, LPX_FX, lo, up);
    5.67 -// 	else 
    5.68 -// 	  lpx_set_row_bnds(lp, i, LPX_DB, lo, up);
    5.69 -// 	break;
    5.70 -//       default: ;
    5.71 -// 	//FIXME error
    5.72 -//       }
    5.73 -//     }
    5.74 -//   }
    5.75 -  
    5.76 -//   void LpGlpk::_setRowUpperBound(int i, Value up)
    5.77 -//   {
    5.78 -//     if (up==-INF) {
    5.79 -//       //FIXME error
    5.80 -//     }
    5.81 -//     int b=lpx_get_row_type(lp, i);
    5.82 -//     double lo=lpx_get_row_lb(lp, i);
    5.83 -//     if (up==INF) {
    5.84 -//       switch (b) {
    5.85 -//       case LPX_FR:
    5.86 -//       case LPX_LO:
    5.87 -// 	break;
    5.88 -//       case LPX_UP:
    5.89 -// 	lpx_set_row_bnds(lp, i, LPX_FR, lo, up);
    5.90 -// 	break;
    5.91 -//       case LPX_DB:
    5.92 -//       case LPX_FX:
    5.93 -// 	lpx_set_row_bnds(lp, i, LPX_LO, lo, up);
    5.94 -// 	break;
    5.95 -//       default: ;
    5.96 -// 	//FIXME error
    5.97 -//       }
    5.98 -//     } else {
    5.99 -//       switch (b) {
   5.100 -//       case LPX_FR:
   5.101 -// 	lpx_set_row_bnds(lp, i, LPX_UP, lo, up);
   5.102 -// 	break;
   5.103 -//       case LPX_UP:
   5.104 -// 	lpx_set_row_bnds(lp, i, LPX_UP, lo, up);
   5.105 -// 	break;
   5.106 -//       case LPX_LO:
   5.107 -//       case LPX_DB:
   5.108 -//       case LPX_FX:
   5.109 -// 	if (lo==up) 
   5.110 -// 	  lpx_set_row_bnds(lp, i, LPX_FX, lo, up);
   5.111 -// 	else 
   5.112 -// 	  lpx_set_row_bnds(lp, i, LPX_DB, lo, up);
   5.113 -// 	break;
   5.114 -//       default: ;
   5.115 -// 	//FIXME error
   5.116 -//       }
   5.117 -//     }
   5.118 -//   }
   5.119 -
   5.120    void LpGlpk::_setRowBounds(int i, Value lb, Value ub)
   5.121    {
   5.122      //Bad parameter
   5.123 @@ -508,29 +426,15 @@
   5.124        lpx_set_obj_coef(lp, i, 0);
   5.125      }
   5.126    }
   5.127 -//   void LpGlpk::_setObj(int length,
   5.128 -// 		       int  const * indices, 
   5.129 -// 		       Value  const * values )
   5.130 -//   {
   5.131 -//     Value new_values[1+lpx_num_cols()];
   5.132 -//     for (i=0;i<=lpx_num_cols();++i){
   5.133 -//       new_values[i]=0;
   5.134 -//     }
   5.135 -//     for (i=1;i<=length;++i){
   5.136 -//       new_values[indices[i]]=values[i];
   5.137 -//     }
   5.138 -    
   5.139 -//     for (i=0;i<=lpx_num_cols();++i){
   5.140 -//       lpx_set_obj_coef(lp, i, new_values[i]);
   5.141 -//     }
   5.142 -//   }
   5.143  
   5.144    LpGlpk::SolveExitStatus LpGlpk::_solve()
   5.145    {
   5.146      // A way to check the problem to be solved
   5.147      //lpx_write_cpxlp(lp,"naittvan.cpx");    
   5.148  
   5.149 +    lpx_std_basis(lp);
   5.150      int i =  lpx_simplex(lp);
   5.151 +    
   5.152      switch (i) {
   5.153      case LPX_E_OK: 
   5.154        return SOLVED;
     6.1 --- a/lemon/lp_skeleton.h	Thu Feb 15 13:06:23 2007 +0000
     6.2 +++ b/lemon/lp_skeleton.h	Thu Feb 15 14:22:08 2007 +0000
     6.3 @@ -30,6 +30,7 @@
     6.4      int col_num,row_num;
     6.5      
     6.6    protected:
     6.7 +
     6.8      ///\e
     6.9      virtual LpSolverBase &_newLp();
    6.10      ///\e
     7.1 --- a/lemon/lp_soplex.cc	Thu Feb 15 13:06:23 2007 +0000
     7.2 +++ b/lemon/lp_soplex.cc	Thu Feb 15 14:22:08 2007 +0000
     7.3 @@ -27,7 +27,10 @@
     7.4  namespace lemon {
     7.5    
     7.6    LpSoplex::LpSoplex() : LpSolverBase() {
     7.7 +    rows.setIdHandler(relocateIdHandler);
     7.8 +    cols.setIdHandler(relocateIdHandler);
     7.9      soplex = new soplex::SoPlex;
    7.10 +    solved = false;
    7.11    }
    7.12    
    7.13    LpSoplex::~LpSoplex() {
    7.14 @@ -47,19 +50,25 @@
    7.15  
    7.16    int LpSoplex::_addCol() {
    7.17      soplex::LPCol col;
    7.18 +    col.setLower(-soplex::infinity);
    7.19 +    col.setUpper(soplex::infinity);
    7.20      soplex->addCol(col);
    7.21  
    7.22      colNames.push_back(std::string());
    7.23 -    primal.push_back(0.0);
    7.24 +    primal_value.push_back(0.0);
    7.25 +    solved = false;
    7.26  
    7.27      return soplex->nCols() - 1;
    7.28    }
    7.29  
    7.30    int LpSoplex::_addRow() {
    7.31      soplex::LPRow row;
    7.32 +    row.setLhs(-soplex::infinity);
    7.33 +    row.setRhs(soplex::infinity);
    7.34      soplex->addRow(row);
    7.35  
    7.36 -    dual.push_back(0.0);
    7.37 +    dual_value.push_back(0.0);
    7.38 +    solved = false;
    7.39  
    7.40      return soplex->nRows() - 1;
    7.41    }
    7.42 @@ -67,14 +76,18 @@
    7.43  
    7.44    void LpSoplex::_eraseCol(int i) {
    7.45      soplex->removeCol(i);
    7.46 -    primal[i] = primal.back();
    7.47 -    primal.pop_back();
    7.48 +    colNames[i] = colNames.back();
    7.49 +    colNames.pop_back();
    7.50 +    primal_value[i] = primal_value.back();
    7.51 +    primal_value.pop_back();
    7.52 +    solved = false;
    7.53    }
    7.54    
    7.55    void LpSoplex::_eraseRow(int i) {
    7.56      soplex->removeRow(i);
    7.57 -    dual[i] = dual.back();
    7.58 -    dual.pop_back();
    7.59 +    dual_value[i] = dual_value.back();
    7.60 +    dual_value.pop_back();
    7.61 +    solved = false;
    7.62    }
    7.63    
    7.64    void LpSoplex::_getColName(int col, std::string &name) {
    7.65 @@ -93,6 +106,7 @@
    7.66      for(LpRowIterator it = b; it != e; ++it) {
    7.67        soplex->changeElement(i, it->first, it->second);
    7.68      }
    7.69 +    solved = false;
    7.70    }
    7.71    
    7.72    void LpSoplex::_setColCoeffs(int j, LpColIterator b, LpColIterator e) {
    7.73 @@ -102,47 +116,80 @@
    7.74      for(LpColIterator it = b; it != e; ++it) {
    7.75        soplex->changeElement(it->first, j, it->second);
    7.76      }
    7.77 +    solved = false;
    7.78    }
    7.79    
    7.80 -  void LpSoplex::_setCoeff(int row, int col, Value value) {
    7.81 -    soplex->changeElement(row, col, value);
    7.82 +  void LpSoplex::_setCoeff(int i, int j, Value value) {
    7.83 +    soplex->changeElement(i, j, value);
    7.84 +    solved = false;
    7.85 +  }
    7.86 +
    7.87 +  LpSoplex::Value LpSoplex::_getCoeff(int i, int j) {
    7.88 +    return soplex->rowVector(i)[j];
    7.89    }
    7.90  
    7.91    void LpSoplex::_setColLowerBound(int i, Value value) {
    7.92 -    soplex->changeLower(i, value); 
    7.93 +    soplex->changeLower(i, value != -INF ? value : -soplex::infinity); 
    7.94 +    solved = false;
    7.95    }
    7.96    
    7.97 +  LpSoplex::Value LpSoplex::_getColLowerBound(int i) {
    7.98 +    double value = soplex->lower(i);
    7.99 +    return value != -soplex::infinity ? value : -INF;
   7.100 +  }
   7.101 +
   7.102    void LpSoplex::_setColUpperBound(int i, Value value) {
   7.103 -    soplex->changeUpper(i, value); 
   7.104 +    soplex->changeUpper(i, value != INF ? value : soplex::infinity); 
   7.105 +    solved = false;
   7.106 +  }
   7.107 +
   7.108 +  LpSoplex::Value LpSoplex::_getColUpperBound(int i) {
   7.109 +    double value = soplex->upper(i);
   7.110 +    return value != soplex::infinity ? value : INF;
   7.111    }
   7.112  
   7.113    void LpSoplex::_setRowBounds(int i, Value lb, Value ub) {
   7.114 -    soplex->changeRange(i, lb, ub);
   7.115 +    soplex->changeRange(i, lb != -INF ? lb : -soplex::infinity,
   7.116 +                        ub != INF ? ub : soplex::infinity);
   7.117 +    solved = false;
   7.118 +  }
   7.119 +  void LpSoplex::_getRowBounds(int i, Value &lower, Value &upper) {
   7.120 +    lower = soplex->lhs(i);
   7.121 +    if (lower == -soplex::infinity) lower = -INF;
   7.122 +    upper = soplex->rhs(i);
   7.123 +    if (upper == -soplex::infinity) upper = INF;
   7.124    }
   7.125  
   7.126    void LpSoplex::_setObjCoeff(int i, Value obj_coef) {
   7.127      soplex->changeObj(i, obj_coef);
   7.128 +    solved = false;
   7.129 +  }
   7.130 +
   7.131 +  LpSoplex::Value LpSoplex::_getObjCoeff(int i) {
   7.132 +    return soplex->obj(i);
   7.133    }
   7.134  
   7.135    void LpSoplex::_clearObj() {
   7.136      for (int i = 0; i < soplex->nCols(); ++i) {
   7.137        soplex->changeObj(i, 0.0);
   7.138      }
   7.139 +    solved = false;
   7.140    }
   7.141  
   7.142    LpSoplex::SolveExitStatus LpSoplex::_solve() {
   7.143      soplex::SPxSolver::Status status = soplex->solve();
   7.144  
   7.145 -    soplex::Vector pv(primal.size(), &primal[0]);
   7.146 +    soplex::Vector pv(primal_value.size(), &primal_value[0]);
   7.147      soplex->getPrimal(pv);
   7.148  
   7.149 -    soplex::Vector dv(dual.size(), &dual[0]);
   7.150 +    soplex::Vector dv(dual_value.size(), &dual_value[0]);
   7.151      soplex->getDual(dv);
   7.152  
   7.153      switch (status) {
   7.154      case soplex::SPxSolver::OPTIMAL:
   7.155      case soplex::SPxSolver::INFEASIBLE:
   7.156      case soplex::SPxSolver::UNBOUNDED:
   7.157 +      solved = true;
   7.158        return SOLVED;
   7.159      default:
   7.160        return UNSOLVED;
   7.161 @@ -150,11 +197,11 @@
   7.162    }
   7.163  
   7.164    LpSoplex::Value LpSoplex::_getPrimal(int i) {
   7.165 -    return primal[i];
   7.166 +    return primal_value[i];
   7.167    }
   7.168  
   7.169    LpSoplex::Value LpSoplex::_getDual(int i) {
   7.170 -    return dual[i];
   7.171 +    return dual_value[i];
   7.172    }
   7.173    
   7.174    LpSoplex::Value LpSoplex::_getPrimalValue() {
   7.175 @@ -166,6 +213,7 @@
   7.176    }  
   7.177  
   7.178    LpSoplex::SolutionStatus LpSoplex::_getPrimalStatus() {
   7.179 +    if (!solved) return UNDEFINED;
   7.180      switch (soplex->status()) {
   7.181      case soplex::SPxSolver::OPTIMAL:
   7.182        return OPTIMAL;
   7.183 @@ -179,30 +227,41 @@
   7.184    }
   7.185  
   7.186    LpSoplex::SolutionStatus LpSoplex::_getDualStatus() {
   7.187 -    switch (0) {
   7.188 -    case 0:
   7.189 -      return UNDEFINED;
   7.190 +    if (!solved) return UNDEFINED;
   7.191 +    switch (soplex->status()) {
   7.192 +    case soplex::SPxSolver::OPTIMAL:
   7.193        return OPTIMAL;
   7.194 +    case soplex::SPxSolver::UNBOUNDED:
   7.195        return INFEASIBLE;
   7.196 +    default:
   7.197        return UNDEFINED;
   7.198      }
   7.199    }
   7.200  
   7.201    LpSoplex::ProblemTypes LpSoplex::_getProblemType() {
   7.202 -    switch (0) {
   7.203 -    case 0:
   7.204 +    if (!solved) return UNKNOWN;
   7.205 +    switch (soplex->status()) {
   7.206 +    case soplex::SPxSolver::OPTIMAL:
   7.207        return PRIMAL_DUAL_FEASIBLE;
   7.208 +    case soplex::SPxSolver::UNBOUNDED:
   7.209        return PRIMAL_FEASIBLE_DUAL_INFEASIBLE;
   7.210 +    default:
   7.211        return UNKNOWN;
   7.212      }
   7.213    }
   7.214  
   7.215    void LpSoplex::_setMax() {
   7.216      soplex->changeSense(soplex::SPxSolver::MAXIMIZE);
   7.217 +    solved = false;
   7.218    }
   7.219    void LpSoplex::_setMin() {
   7.220      soplex->changeSense(soplex::SPxSolver::MINIMIZE);
   7.221 +    solved = false;
   7.222    }
   7.223 +  bool LpSoplex::_isMax() {
   7.224 +    return soplex->spxSense() == soplex::SPxSolver::MAXIMIZE;
   7.225 +  }
   7.226 +
   7.227    
   7.228  } //namespace lemon
   7.229  
     8.1 --- a/lemon/lp_soplex.h	Thu Feb 15 13:06:23 2007 +0000
     8.2 +++ b/lemon/lp_soplex.h	Thu Feb 15 14:22:08 2007 +0000
     8.3 @@ -40,12 +40,15 @@
     8.4    class LpSoplex :virtual public LpSolverBase {
     8.5    protected:
     8.6  
     8.7 +    _lp_bits::RelocateIdHandler relocateIdHandler;
     8.8 +
     8.9      soplex::SoPlex* soplex;
    8.10 +    bool solved;
    8.11  
    8.12      std::vector<std::string> colNames;
    8.13  
    8.14 -    std::vector<Value> primal;
    8.15 -    std::vector<Value> dual;
    8.16 +    std::vector<Value> primal_value;
    8.17 +    std::vector<Value> dual_value;
    8.18  
    8.19  
    8.20    public:
    8.21 @@ -67,15 +70,20 @@
    8.22      virtual int _addRow();
    8.23      virtual void _eraseCol(int i);
    8.24      virtual void _eraseRow(int i);
    8.25 -    virtual void _getColName(int col,       std::string & name);
    8.26 +    virtual void _getColName(int col, std::string & name);
    8.27      virtual void _setColName(int col, const std::string & name);
    8.28      virtual void _setRowCoeffs(int i, LpRowIterator b, LpRowIterator e);
    8.29      virtual void _setColCoeffs(int i, LpColIterator b, LpColIterator e);
    8.30      virtual void _setCoeff(int row, int col, Value value);
    8.31 +    virtual Value _getCoeff(int row, int col);
    8.32      virtual void _setColLowerBound(int i, Value value);
    8.33 +    virtual Value _getColLowerBound(int i);
    8.34      virtual void _setColUpperBound(int i, Value value);
    8.35 +    virtual Value _getColUpperBound(int i);
    8.36      virtual void _setRowBounds(int i, Value lower, Value upper);
    8.37 +    virtual void _getRowBounds(int i, Value &lower, Value &upper);
    8.38      virtual void _setObjCoeff(int i, Value obj_coef);
    8.39 +    virtual Value _getObjCoeff(int i);
    8.40      virtual void _clearObj();
    8.41      
    8.42      virtual SolveExitStatus _solve();
    8.43 @@ -91,6 +99,7 @@
    8.44      
    8.45      virtual void _setMax();
    8.46      virtual void _setMin();
    8.47 +    virtual bool _isMax();
    8.48  
    8.49    };
    8.50  } //END OF NAMESPACE LEMON
     9.1 --- a/lemon/lp_utils.h	Thu Feb 15 13:06:23 2007 +0000
     9.2 +++ b/lemon/lp_utils.h	Thu Feb 15 14:22:08 2007 +0000
     9.3 @@ -22,6 +22,7 @@
     9.4  #include <lemon/lp_base.h>
     9.5  
     9.6  #include <lemon/lemon_reader.h>
     9.7 +#include <lemon/lemon_writer.h>
     9.8  
     9.9  namespace lemon {
    9.10  
    9.11 @@ -319,7 +320,6 @@
    9.12      /// It reads the content of the section.
    9.13      virtual void read(std::istream& is) {
    9.14        std::string line;
    9.15 -      std::map<std::string, LpSolverBase::Col> vars;
    9.16        while (getline(is, line)) {
    9.17          std::istringstream ls(line);
    9.18          std::string sense;
    9.19 @@ -359,6 +359,336 @@
    9.20      ColMap cols;
    9.21    };
    9.22  
    9.23 +
    9.24 +//   class LpWriter : public LemonWriter::SectionWriter {
    9.25 +//     typedef LemonWriter::SectionWriter Parent;
    9.26 +//   public:
    9.27 +
    9.28 +
    9.29 +//     /// \brief Constructor.
    9.30 +//     ///
    9.31 +//     /// Constructor for LpWriter. It creates the LpWriter and attach
    9.32 +//     /// it into the given LemonWriter. The lp writer will add
    9.33 +//     /// variables, constraints and objective function to the
    9.34 +//     /// given lp solver.
    9.35 +//     LpWriter(LemonWriter& _writer, LpSolverBase& _lp, 
    9.36 +//              const std::string& _name = std::string())
    9.37 +//       : Parent(_writer), lp(_lp), name(_name) {} 
    9.38 +
    9.39 +
    9.40 +//     /// \brief Destructor.
    9.41 +//     ///
    9.42 +//     /// Destructor for NodeSetWriter.
    9.43 +//     virtual ~LpWriter() {}
    9.44 +
    9.45 +//   private:
    9.46 +//     LpWriter(const LpWriter&);
    9.47 +//     void operator=(const LpWriter&);
    9.48 +  
    9.49 +//   protected:
    9.50 +
    9.51 +//     /// \brief Gives back true when the SectionWriter can process 
    9.52 +//     /// the section with the given header line.
    9.53 +//     ///
    9.54 +//     /// It gives back the header line of the \c \@lp section.
    9.55 +//     virtual std::string header() {
    9.56 +//       std::ostringstream ls(line);
    9.57 +//       ls << "@lp " << name;
    9.58 +//       return ls.str();
    9.59 +//     }
    9.60 +
    9.61 +//   private:
    9.62 +
    9.63 +//     std::ostream& writeConstraint(std::ostream& is, LpSolverBase::Constr& c) {
    9.64 +//       char x;
    9.65 +
    9.66 +      
    9.67 +//       LpSolverBase::Expr e1, e2;
    9.68 +//       Relation op1;
    9.69 +//       is >> std::ws;
    9.70 +//       writexpression(is, e1);
    9.71 +//       is >> std::ws;
    9.72 +//       writeRelation(is, op1);
    9.73 +//       is >> std::ws;
    9.74 +//       writexpression(is, e2);
    9.75 +//       if (!is.get(x)) {
    9.76 +//         if (op1 == LE) {
    9.77 +//           c = e1 <= e2;
    9.78 +//         } else if (op1 == GE) {
    9.79 +//           c = e1 >= e2;
    9.80 +//         } else {
    9.81 +//           c = e1 == e2;
    9.82 +//         }
    9.83 +//       } else {
    9.84 +//         is.putback(x);
    9.85 +//         LpSolverBase::Expr e3;
    9.86 +//         Relation op2;
    9.87 +//         writeRelation(is, op2);
    9.88 +//         is >> std::ws;
    9.89 +//         writexpression(is, e3);
    9.90 +//         if (!e1.empty() || !e3.empty()) {
    9.91 +//           throw DataFormatError("Wrong range format");
    9.92 +//         }
    9.93 +//         if (op2 != op1 || op1 == EQ) {
    9.94 +//           throw DataFormatError("Wrong range format");
    9.95 +//         }
    9.96 +//         if (op1 == LE) {
    9.97 +//           c = e1.constComp() <= e2 <= e3.constComp();
    9.98 +//         } else {
    9.99 +//           c = e1.constComp() >= e2 >= e3.constComp();
   9.100 +//         }
   9.101 +//       }
   9.102 +//     }
   9.103 +
   9.104 +//     std::ostream& writexpression(std::ostream& is, LpSolverBase::Expr& e) {
   9.105 +//       LpSolverBase::Col c;
   9.106 +//       double d;
   9.107 +//       char x;
   9.108 +//       writelement(is, c, d);
   9.109 +//       if (c != INVALID) {
   9.110 +//         e += d * c;
   9.111 +//       } else {
   9.112 +//         e += d;
   9.113 +//       }
   9.114 +//       is >> std::ws;
   9.115 +//       while (is.get(x) && (x == '+' || x == '-')) {
   9.116 +//         is >> std::ws;
   9.117 +//         writelement(is, c, d);
   9.118 +//         if (c != INVALID) {
   9.119 +//           e += (x == '+' ? d : -d) * c;
   9.120 +//         } else {
   9.121 +//           e += (x == '+' ? d : -d);
   9.122 +//         }
   9.123 +//         is >> std::ws;
   9.124 +//       }
   9.125 +//       if (!is) {
   9.126 +//         is.clear();
   9.127 +//       } else {
   9.128 +//         is.putback(x);
   9.129 +//       }
   9.130 +//       return is;
   9.131 +//     }
   9.132 +
   9.133 +//     std::ostream& writelement(std::ostream& is, 
   9.134 +//                               LpSolverBase::Col& c, double& d) { 
   9.135 +//       d = 1.0;
   9.136 +//       c = INVALID;
   9.137 +//       char x, y;
   9.138 +//       if (!is.get(x)) throw DataFormatError("Cannot find lp element");
   9.139 +//       if (x == '+' || x == '-') {
   9.140 +//         is >> std::ws;
   9.141 +//         d *= x == '-' ? -1 : 1;
   9.142 +//         while (is.get(x) && (x == '+' || x == '-')) {
   9.143 +//           d *= x == '-' ? -1 : 1;
   9.144 +//           is >> std::ws;
   9.145 +//         }
   9.146 +//         if (!is) throw DataFormatError("Cannot find lp element");
   9.147 +//       }
   9.148 +//       if (numFirstChar(x)) {
   9.149 +//         is.putback(x);
   9.150 +//         double e;
   9.151 +//         writeNum(is, e);
   9.152 +//         d *= e;
   9.153 +//       } else if (varFirstChar(x)) {
   9.154 +//         is.putback(x);
   9.155 +//         LpSolverBase::Col f;
   9.156 +//         writeCol(is, f);
   9.157 +//         c = f;
   9.158 +//       } else {
   9.159 +//         throw DataFormatError("Invalid expression format");          
   9.160 +//       }
   9.161 +//       is >> std::ws;
   9.162 +//       while (is.get(y) && (y == '*' || y == '/')) {
   9.163 +//         is >> std::ws;
   9.164 +//         if (!is.get(x)) throw DataFormatError("Cannot find lp element");
   9.165 +//         if (x == '+' || x == '-') {
   9.166 +//           is >> std::ws;
   9.167 +//           d *= x == '-' ? -1 : 1;
   9.168 +//           while (is.get(x) && (x == '+' || x == '-')) {
   9.169 +//             d *= x == '-' ? -1 : 1;
   9.170 +//             is >> std::ws;
   9.171 +//           }
   9.172 +//           if (!is) throw DataFormatError("Cannot find lp element");
   9.173 +//         }
   9.174 +//         if (numFirstChar(x)) {
   9.175 +//           is.putback(x);
   9.176 +//           double e;
   9.177 +//           writeNum(is, e);
   9.178 +//           if (y == '*') {
   9.179 +//             d *= e;
   9.180 +//           } else {
   9.181 +//             d /= e;
   9.182 +//           }
   9.183 +//         } else if (varFirstChar(x)) {
   9.184 +//           is.putback(x);
   9.185 +//           LpSolverBase::Col f;
   9.186 +//           writeCol(is, f);
   9.187 +//           if (y == '*') {
   9.188 +//             if (c == INVALID) {
   9.189 +//               c = f;
   9.190 +//             } else {
   9.191 +//               throw DataFormatError("Quadratic element in expression");
   9.192 +//             }
   9.193 +//           } else {
   9.194 +//             throw DataFormatError("Division by variable");
   9.195 +//           }
   9.196 +//         } else {
   9.197 +//           throw DataFormatError("Invalid expression format");          
   9.198 +//         }
   9.199 +//         is >> std::ws;
   9.200 +//       }
   9.201 +//       if (!is) {
   9.202 +//         is.clear();
   9.203 +//       } else {
   9.204 +//         is.putback(y);
   9.205 +//       }
   9.206 +//       return is;
   9.207 +//     }
   9.208 +
   9.209 +//     std::ostream& writeCol(std::ostream& is, LpSolverBase::Col& c) {
   9.210 +//       char x;
   9.211 +//       std::string var;
   9.212 +//       while (is.get(x) && varChar(x)) {
   9.213 +//         var += x;
   9.214 +//       }
   9.215 +//       if (!is) {
   9.216 +//         is.clear();
   9.217 +//       } else {
   9.218 +//         is.putback(x);
   9.219 +//       }
   9.220 +//       ColMap::const_iterator it = cols.find(var);
   9.221 +//       if (cols.find(var) != cols.end()) {
   9.222 +//         c = it->second;
   9.223 +//       } else {
   9.224 +//         c = lp.addCol();
   9.225 +//         cols.insert(std::make_pair(var, c));
   9.226 +//         lp.colName(c, var);
   9.227 +//       }
   9.228 +//       return is;
   9.229 +//     }
   9.230 +
   9.231 +//     std::ostream& writeNum(std::ostream& is, double& d) {
   9.232 +//       is >> d;
   9.233 +//       if (!is) throw DataFormatError("Wrong number format");
   9.234 +//       return is;
   9.235 +//     }
   9.236 +
   9.237 +//     std::ostream& writeRelation(std::ostream& is, Relation& op) {
   9.238 +//       char x, y;
   9.239 +//       if (!is.get(x) || !(x == '<' || x == '=' || x == '>')) {
   9.240 +//         throw DataFormatError("Wrong relation operator");
   9.241 +//       }
   9.242 +//       if (!is.get(y) || y != '=') {
   9.243 +//         throw DataFormatError("Wrong relation operator");
   9.244 +//       }
   9.245 +//       switch (x) {
   9.246 +//       case '<': op = LE; 
   9.247 +//         break;
   9.248 +//       case '=': op = EQ; 
   9.249 +//         break;
   9.250 +//       case '>': op = GE; 
   9.251 +//         break;
   9.252 +//       }
   9.253 +//       return is;
   9.254 +//     }
   9.255 +
   9.256 +//     static bool relationFirstChar(char c) {
   9.257 +//       return c == '<' || c == '=' || c == '>';
   9.258 +//     }
   9.259 +
   9.260 +//     static bool varFirstChar(char c) {
   9.261 +//       return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
   9.262 +//     }
   9.263 +
   9.264 +//     static bool numFirstChar(char c) {
   9.265 +//       return (c >= '0' && c <= '9') || c == '.';
   9.266 +//     }
   9.267 +
   9.268 +//     static bool varChar(char c) {
   9.269 +//       return (c >= '0' && c <= '9') || 
   9.270 +//         (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
   9.271 +//     }
   9.272 +
   9.273 +
   9.274 +//     void addConstraint(const LpSolverBase::Constr& constr) {
   9.275 +//       if (constr.expr().size() != 1) {
   9.276 +//         lp.addRow(constr);
   9.277 +//       } else {
   9.278 +//         Lp::Expr e = constr.expr();
   9.279 +//         LpSolverBase::Col col = e.begin()->first;
   9.280 +//         double coeff = e.begin()->second;
   9.281 +//         double lb = LpSolverBase::NaN;
   9.282 +//         double ub = LpSolverBase::NaN;
   9.283 +//         if (coeff > 0) {
   9.284 +//           if (constr.upperBounded()) {
   9.285 +//             lb = (constr.lowerBound() - e.constComp()) / coeff;
   9.286 +//           }
   9.287 +//           if (constr.lowerBounded()) {
   9.288 +//             ub = (constr.upperBound() - e.constComp()) / coeff;
   9.289 +//           }
   9.290 +//         } else if (coeff < 0) {
   9.291 +//           if (constr.upperBounded()) {
   9.292 +//             lb = (constr.upperBound() - e.constComp()) / coeff;
   9.293 +//           }
   9.294 +//           if (constr.lowerBounded()) {
   9.295 +//             ub = (constr.lowerBound() - e.constComp()) / coeff;
   9.296 +//           }
   9.297 +//         } else {
   9.298 +//           lb = -LpSolverBase::INF;
   9.299 +//           ub = LpSolverBase::INF;
   9.300 +//         }
   9.301 +//         lp.colLowerBound(col, lb);
   9.302 +//         lp.colUpperBound(col, ub);
   9.303 +//       }
   9.304 +//     }
   9.305 +    
   9.306 +//   protected:
   9.307 +
   9.308 +//     /// \brief Writer function of the section.
   9.309 +//     ///
   9.310 +//     /// It writes the content of the section.
   9.311 +//     virtual void write(std::ostream& is) {
   9.312 +//       std::string line;
   9.313 +//       std::map<std::string, LpSolverBase::Col> vars;
   9.314 +//       while (getline(is, line)) {
   9.315 +//         std::istringstream ls(line);
   9.316 +//         std::string sense;
   9.317 +//         ls >> sense;
   9.318 +//         if (sense == "min" || sense == "max") {
   9.319 +//           LpSolverBase::Expr expr;
   9.320 +//           ls >> std::ws;
   9.321 +//           writeExpression(ls, expr);
   9.322 +//           lp.setObj(expr);
   9.323 +//           if (sense == "min") {
   9.324 +//             lp.min();
   9.325 +//           } else {
   9.326 +//             lp.max();
   9.327 +//           }
   9.328 +//         } else {
   9.329 +//           ls.str(line);
   9.330 +//           LpSolverBase::Constr constr;
   9.331 +//           ls >> std::ws;
   9.332 +//           writeConstraint(ls, constr);
   9.333 +//           addConstraint(constr);
   9.334 +//         }        
   9.335 +//       }
   9.336 +//     }
   9.337 +      
   9.338 +//     virtual void missing() {
   9.339 +//       ErrorMessage msg;
   9.340 +//       msg << "Lp section not found in file: @lp " << name;
   9.341 +//       throw IoParameterError(msg.message());
   9.342 +//     }
   9.343 +
   9.344 +//   private:
   9.345 +
   9.346 +//     typedef std::map<std::string, LpSolverBase::Col> ColMap;
   9.347 +      
   9.348 +//     LpSolverBase& lp;
   9.349 +//     std::string name;
   9.350 +//     ColMap cols;
   9.351 +//   };
   9.352 +
   9.353  }
   9.354  
   9.355  #endif
    10.1 --- a/m4/lx_check_soplex.m4	Thu Feb 15 13:06:23 2007 +0000
    10.2 +++ b/m4/lx_check_soplex.m4	Thu Feb 15 14:22:08 2007 +0000
    10.3 @@ -18,9 +18,9 @@
    10.4      AC_MSG_CHECKING([for SOPLEX])
    10.5  
    10.6      if test x"$with_soplex_includedir" != x"no"; then
    10.7 -      SOPLEX_CFLAGS="-I$with_soplex_includedir"
    10.8 +      SOPLEX_CXXFLAGS="-I$with_soplex_includedir"
    10.9      elif test x"$with_soplex" != x"yes"; then
   10.10 -      SOPLEX_CFLAGS="-I$with_soplex/include"
   10.11 +      SOPLEX_CXXFLAGS="-I$with_soplex/include"
   10.12      fi
   10.13  
   10.14      if test x"$with_soplex_libdir" != x"no"; then
   10.15 @@ -33,7 +33,7 @@
   10.16      lx_save_cxxflags="$CXXFLAGS"
   10.17      lx_save_ldflags="$LDFLAGS"
   10.18      lx_save_libs="$LIBS"
   10.19 -    CXXFLAGS="$SOPLEX_CFLAGS"
   10.20 +    CXXFLAGS="$SOPLEX_CXXFLAGS"
   10.21      LDFLAGS="$SOPLEX_LDFLAGS"
   10.22      LIBS="$SOPLEX_LIBS"
   10.23  
   10.24 @@ -58,14 +58,14 @@
   10.25        AC_DEFINE([HAVE_SOPLEX], [1], [Define to 1 if you have SOPLEX.])
   10.26        AC_MSG_RESULT([yes])
   10.27      else
   10.28 -      SOPLEX_CFLAGS=""
   10.29 +      SOPLEX_CXXFLAGS=""
   10.30        SOPLEX_LDFLAGS=""
   10.31        SOPLEX_LIBS=""
   10.32        AC_MSG_RESULT([no])
   10.33      fi
   10.34    fi
   10.35    SOPLEX_LIBS="$SOPLEX_LDFLAGS $SOPLEX_LIBS"
   10.36 -  AC_SUBST(SOPLEX_CFLAGS)
   10.37 +  AC_SUBST(SOPLEX_CXXFLAGS)
   10.38    AC_SUBST(SOPLEX_LIBS)
   10.39    AM_CONDITIONAL([HAVE_SOPLEX], [test x"$lx_soplex_found" = x"yes"])
   10.40  ])
    11.1 --- a/test/Makefile.am	Thu Feb 15 13:06:23 2007 +0000
    11.2 +++ b/test/Makefile.am	Thu Feb 15 14:22:08 2007 +0000
    11.3 @@ -49,7 +49,11 @@
    11.4  else !HAVE_GLPK
    11.5  if HAVE_CPLEX
    11.6  check_PROGRAMS += test/lp_test test/mip_test
    11.7 -endif HAVE_CPLEX
    11.8 +else !HAVE_CPLEX
    11.9 +if HAVE_SOPLEX
   11.10 +check_PROGRAMS += test/lp_test
   11.11 +endif HAVE_SOPLEX
   11.12 +endif !HAVE_CPLEX
   11.13  endif !HAVE_GLPK
   11.14  
   11.15  TESTS += $(check_PROGRAMS)
   11.16 @@ -89,6 +93,6 @@
   11.17  test_unionfind_test_SOURCES = test/unionfind_test.cc
   11.18  
   11.19  test_lp_test_SOURCES = test/lp_test.cc
   11.20 -test_lp_test_CXXFLAGS = $(GLPK_CFLAGS) $(CPLEX_CFLAGS)
   11.21 +test_lp_test_CXXFLAGS = $(GLPK_CFLAGS) $(CPLEX_CFLAGS) $(SOPLEX_CXXFLAGS)
   11.22  test_mip_test_SOURCES = test/mip_test.cc
   11.23 -test_mip_test_CXXFLAGS = $(GLPK_CFLAGS) $(CPLEX_CFLAGS)
   11.24 \ No newline at end of file
   11.25 +test_mip_test_CXXFLAGS = $(GLPK_CFLAGS) $(CPLEX_CFLAGS) $(SOPLEX_CXXFLAGS)
   11.26 \ No newline at end of file
    12.1 --- a/test/lp_test.cc	Thu Feb 15 13:06:23 2007 +0000
    12.2 +++ b/test/lp_test.cc	Thu Feb 15 14:22:08 2007 +0000
    12.3 @@ -33,9 +33,9 @@
    12.4  #include <lemon/lp_cplex.h>
    12.5  #endif
    12.6  
    12.7 -// #ifdef HAVE_SOPLEX
    12.8 -// #include <lemon/lp_soplex.h>
    12.9 -// #endif
   12.10 +#ifdef HAVE_SOPLEX
   12.11 +#include <lemon/lp_soplex.h>
   12.12 +#endif
   12.13  
   12.14  using namespace lemon;
   12.15  
   12.16 @@ -374,11 +374,11 @@
   12.17    aTest(lp_cplex2);
   12.18  #endif
   12.19  
   12.20 -// #ifdef HAVE_SOPLEX
   12.21 -//   LpSoplex lp_soplex1,lp_soplex2;
   12.22 -//   lpTest(lp_soplex1);
   12.23 -//   aTest(lp_soplex2);
   12.24 -// #endif
   12.25 +#ifdef HAVE_SOPLEX
   12.26 +  LpSoplex lp_soplex1,lp_soplex2;
   12.27 +  lpTest(lp_soplex1);
   12.28 +  aTest(lp_soplex2);
   12.29 +#endif
   12.30  
   12.31    return 0;
   12.32  }