[Lemon-commits] deba: r3489 - in lemon/trunk: lemon test

Lemon SVN svn at lemon.cs.elte.hu
Tue Apr 8 18:01:30 CEST 2008


Author: deba
Date: Tue Apr  8 18:01:28 2008
New Revision: 3489

Modified:
   lemon/trunk/lemon/config.h.in
   lemon/trunk/lemon/lp_base.h
   lemon/trunk/lemon/lp_cplex.cc
   lemon/trunk/lemon/lp_cplex.h
   lemon/trunk/lemon/lp_glpk.cc
   lemon/trunk/lemon/lp_glpk.h
   lemon/trunk/lemon/lp_skeleton.cc
   lemon/trunk/lemon/lp_skeleton.h
   lemon/trunk/lemon/lp_soplex.cc
   lemon/trunk/lemon/lp_soplex.h
   lemon/trunk/test/lp_test.cc

Log:
Bug fixes in LP solvers
- the copyLp is clarified
- newLp and copyLp gives back pointers
- cplex gives back empty string for variables without name
- cplex row and column retrieval
- added macro for soplex



Modified: lemon/trunk/lemon/config.h.in
==============================================================================
--- lemon/trunk/lemon/config.h.in	(original)
+++ lemon/trunk/lemon/config.h.in	Tue Apr  8 18:01:28 2008
@@ -3,3 +3,6 @@
 
 /* Define to 1 if you have GLPK. */
 #undef HAVE_GLPK
+
+/* Define to 1 if you have SOPLEX. */
+#undef HAVE_SOPLEX

Modified: lemon/trunk/lemon/lp_base.h
==============================================================================
--- lemon/trunk/lemon/lp_base.h	(original)
+++ lemon/trunk/lemon/lp_base.h	Tue Apr  8 18:01:28 2008
@@ -371,25 +371,6 @@
 	return *this;
       }
 
-      //std::ostream &
-      void prettyPrint(std::ostream &os) {
-	//std::fmtflags os.flags();
-	//os.setf(std::ios::showpos);
-	Base::iterator j=Base::begin();
-	if (j!=Base::end())
-	  os<<j->second<<"*x["<<id(j->first)<<"]";
-	++j;
-	for (; j!=Base::end(); ++j){
-	  if (j->second>=0)
-	    os<<"+";
-	  os<<j->second<<"*x["<<id(j->first)<<"]";
-	}
-	//Nem valami korrekt, de nem talaltam meg, hogy kell
-	//os.unsetf(std::ios::showpos);
-
-	//return os;
-      }
-
     };
     
     ///Linear constraint
@@ -481,19 +462,6 @@
 	return isFinite(_ub);
       }
 
-      void prettyPrint(std::ostream &os) {
-	if (_lb==-LpSolverBase::INF||isNaN(_lb))
-	  os<<"-infty<=";
-	else
-	  os<<_lb<<"<=";
-	_expr.prettyPrint(os);
-	if (_ub==LpSolverBase::INF)
-	  os<<"<=infty";
-	else
-	  os<<"<="<<_ub;
-	//return os;
-      }
-
     };
     
     ///Linear expression of rows
@@ -735,15 +703,33 @@
     typedef MappedOutputIterator<DualExpr> ColIterator;
 
     //Abstract virtual functions
-    virtual LpSolverBase &_newLp() = 0;
-    virtual LpSolverBase &_copyLp(){
-      ///\todo This should be implemented here, too, when we have
-      ///problem retrieving routines. It can be overriden.
+    virtual LpSolverBase* _newLp() = 0;
+    virtual LpSolverBase* _copyLp(){
+      LpSolverBase* newlp = _newLp();
+
+      std::map<Col, Col> ref;
+      for (LpSolverBase::ColIt it(*this); it != INVALID; ++it) {
+	Col ccol = newlp->addCol();
+	ref[it] = ccol;
+	newlp->colName(ccol, colName(it));
+	newlp->colLowerBound(ccol, colLowerBound(it));
+	newlp->colUpperBound(ccol, colUpperBound(it));
+      }
+
+      for (LpSolverBase::RowIt it(*this); it != INVALID; ++it) {
+	Expr e = row(it), ce;
+	for (Expr::iterator jt = e.begin(); jt != e.end(); ++jt) {
+	  ce[ref[jt->first]] = jt->second;
+	}
+	ce += e.constComp();
+	Row r = newlp->addRow(ce);
+
+        double lower, upper;
+        getRowBounds(it, lower, upper);
+	newlp->rowBounds(r, lower, upper);
+      }
 
-      //Starting:
-      LpSolverBase & newlp(_newLp());
       return newlp;
-      //return *(LpSolverBase*)0;
     };
 
     virtual int _addCol() = 0;
@@ -804,9 +790,9 @@
     virtual ~LpSolverBase() {}
 
     ///Creates a new LP problem
-    LpSolverBase &newLp() {return _newLp();}
+    LpSolverBase* newLp() {return _newLp();}
     ///Makes a copy of the LP problem
-    LpSolverBase &copyLp() {return _copyLp();}
+    LpSolverBase* copyLp() {return _copyLp();}
     
     ///\name Build up and modify the LP
 

Modified: lemon/trunk/lemon/lp_cplex.cc
==============================================================================
--- lemon/trunk/lemon/lp_cplex.cc	(original)
+++ lemon/trunk/lemon/lp_cplex.cc	Tue Apr  8 18:01:28 2008
@@ -17,47 +17,47 @@
  */
 
 #include <iostream>
+#include <vector>
 #include<lemon/lp_cplex.h>
 
 ///\file
 ///\brief Implementation of the LEMON-CPLEX lp solver interface.
 namespace lemon {
   
-  LpCplex::LpCplex() : LpSolverBase() {
+  LpCplex::LpCplex() {
     //    env = CPXopenCPLEXdevelop(&status);     
     env = CPXopenCPLEX(&status);     
     lp = CPXcreateprob(env, &status, "LP problem");
   }
+
+  LpCplex::LpCplex(const LpCplex& cplex) : LpSolverBase() {
+    env = CPXopenCPLEX(&status);     
+    lp = CPXcloneprob(env, cplex.lp, &status);
+    rows = cplex.rows;
+    cols = cplex.cols;
+  }
   
   LpCplex::~LpCplex() {
-    CPXfreeprob(env,&lp); 
-    CPXcloseCPLEX(&env); 
+    CPXfreeprob(env,&lp);
+    CPXcloseCPLEX(&env);
   }
   
-  LpSolverBase &LpCplex::_newLp() 
+  LpSolverBase* LpCplex::_newLp() 
   {
     //The first approach opens a new environment
-    LpCplex* newlp=new LpCplex();
-    return *newlp;
+    return new LpCplex();
   }
 
-  LpSolverBase &LpCplex::_copyLp() {
-    ///\bug FixID data is not copied!
-    //The first approach opens a new environment
-    LpCplex* newlp=new LpCplex();
-    //The routine CPXcloneprob can be used to create a new CPLEX problem 
-    //object and copy all the problem data from an existing problem 
-    //object to it. Solution and starting information is not copied.
-    newlp->lp = CPXcloneprob(env, lp, &status);
-    return *newlp;
+  LpSolverBase* LpCplex::_copyLp() {
+    return new LpCplex(*this);
   }
 
   int LpCplex::_addCol()
   {
     int i = CPXgetnumcols(env, lp);
     Value lb[1],ub[1];
-    lb[0]=-INF;//-CPX_INFBOUND;
-    ub[0]=INF;//CPX_INFBOUND;
+    lb[0]=-INF;
+    ub[0]=INF;
     status = CPXnewcols(env, lp, 1, NULL, lb, ub, NULL, NULL);
     return i;
   }
@@ -89,7 +89,11 @@
     ///\bug Untested
     int storespace;
     CPXgetcolname(env, lp, 0, 0, 0, &storespace, col, col);
-
+    if (storespace == 0) {
+      name.clear();
+      return;
+    }
+    
     storespace *= -1;
     std::vector<char> buf(storespace);
     char *names[1];
@@ -136,6 +140,21 @@
   }
 
   void LpCplex::_getRowCoeffs(int i, RowIterator b) const {
+    int tmp1, tmp2, tmp3, length;
+    CPXgetrows(env, lp, &tmp1, &tmp2, 0, 0, 0, &length, i, i);
+    
+    length = -length;
+    std::vector<int> indices(length);
+    std::vector<double> values(length);
+
+    CPXgetrows(env, lp, &tmp1, &tmp2, &indices[0], &values[0], 
+	       length, &tmp3, i, i);
+    
+    for (int i = 0; i < length; ++i) {
+      *b = std::make_pair(indices[i], values[i]);
+      ++b;
+    }
+    
     /// \todo implement
   }
   
@@ -156,7 +175,22 @@
   }
 
   void LpCplex::_getColCoeffs(int i, ColIterator b) const {
-    /// \todo implement
+
+    int tmp1, tmp2, tmp3, length;
+    CPXgetcols(env, lp, &tmp1, &tmp2, 0, 0, 0, &length, i, i);
+    
+    length = -length;
+    std::vector<int> indices(length);
+    std::vector<double> values(length);
+
+    CPXgetcols(env, lp, &tmp1, &tmp2, &indices[0], &values[0], 
+	       length, &tmp3, i, i);
+    
+    for (int i = 0; i < length; ++i) {
+      *b = std::make_pair(indices[i], values[i]);
+      ++b;
+    }
+    
   }
   
   void LpCplex::_setCoeff(int row, int col, Value value) 
@@ -187,6 +221,7 @@
   {
     LpCplex::Value x;
     CPXgetlb (env, lp, &x, i, i);
+    if (x <= -CPX_INFBOUND) x = -INF;
     return x;
   }
   
@@ -205,6 +240,7 @@
   {
     LpCplex::Value x;
     CPXgetub (env, lp, &x, i, i);
+    if (x >= CPX_INFBOUND) x = INF;
     return x;
   }
 
@@ -469,8 +505,8 @@
 // Default: 0 
 // Description: Method for linear optimization. 
 // Determines which algorithm is used when CPXlpopt() (or "optimize" in the Interactive Optimizer) is called. Currently the behavior of the "Automatic" setting is that CPLEX simply invokes the dual simplex method, but this capability may be expanded in the future so that CPLEX chooses the method based on problem characteristics 
-  void statusSwitch(CPXENVptr env,int& stat){
 #if CPX_VERSION < 900
+  void statusSwitch(CPXENVptr env,int& stat){
     int lpmethod;
     CPXgetintparam (env,CPX_PARAM_LPMETHOD,&lpmethod);
     if (lpmethod==2){
@@ -482,8 +518,10 @@
 	  stat=CPX_UNBOUNDED;
       }
     }
-#endif
   }
+#else
+  void statusSwitch(CPXENVptr,int&){}
+#endif
 
   LpCplex::SolutionStatus LpCplex::_getPrimalStatus() const
   {

Modified: lemon/trunk/lemon/lp_cplex.h
==============================================================================
--- lemon/trunk/lemon/lp_cplex.h	(original)
+++ lemon/trunk/lemon/lp_cplex.h	Tue Apr  8 18:01:28 2008
@@ -49,11 +49,13 @@
     /// \e
     LpCplex();
     /// \e
+    LpCplex(const LpCplex&);
+    /// \e
     ~LpCplex();
 
   protected:
-    virtual LpSolverBase &_newLp();
-    virtual LpSolverBase &_copyLp();
+    virtual LpSolverBase* _newLp();
+    virtual LpSolverBase* _copyLp();
 
 
     virtual int _addCol();
@@ -100,6 +102,11 @@
 
     virtual bool _isMax() const;
 
+  public:
+
+    CPXENVptr cplexEnv() { return env; } 
+    CPXLPptr cplexLp() { return lp; }
+
   };
 } //END OF NAMESPACE LEMON
 

Modified: lemon/trunk/lemon/lp_glpk.cc
==============================================================================
--- lemon/trunk/lemon/lp_glpk.cc	(original)
+++ lemon/trunk/lemon/lp_glpk.cc	Tue Apr  8 18:01:28 2008
@@ -89,6 +89,8 @@
 				LEMON_glp(get_col_lb)(glp.lp,i),
 				LEMON_glp(get_col_ub)(glp.lp,i));
       }
+    rows = glp.rows;
+    cols = glp.cols;
   }
   
   LpGlpk::~LpGlpk() {
@@ -105,18 +107,18 @@
   ///\e
 
 
-  LpSolverBase &LpGlpk::_newLp()
+  LpSolverBase* LpGlpk::_newLp()
   {
-    LpGlpk* newlp=new LpGlpk;
-    return *newlp;
+    LpGlpk* newlp = new LpGlpk;
+    return newlp;
   }
   
   ///\e
 
-  LpSolverBase &LpGlpk::_copyLp()
+  LpSolverBase* LpGlpk::_copyLp()
   {
-    LpGlpk* newlp=new LpGlpk(*this);
-    return *newlp;
+    LpGlpk *newlp = new LpGlpk(*this);
+    return newlp;
   }
 
   int LpGlpk::_addRow() { 

Modified: lemon/trunk/lemon/lp_glpk.h
==============================================================================
--- lemon/trunk/lemon/lp_glpk.h	(original)
+++ lemon/trunk/lemon/lp_glpk.h	Tue Apr  8 18:01:28 2008
@@ -49,8 +49,8 @@
     ~LpGlpk();
     
   protected:
-    virtual LpSolverBase &_newLp();
-    virtual LpSolverBase &_copyLp();
+    virtual LpSolverBase* _newLp();
+    virtual LpSolverBase* _copyLp();
 
     virtual int _addCol();
     virtual int _addRow();
@@ -120,6 +120,12 @@
 
     ///Pointer to the underlying GLPK data structure.
     LPX *lpx() {return lp;}
+
+    ///Returns the constraint identifier understood by GLPK.
+    int lpxRow(Row r) { return _lpId(r); }
+
+    ///Returns the variable identifier understood by GLPK.
+    int lpxCol(Col c) { return _lpId(c); }
   };
 } //END OF NAMESPACE LEMON
 

Modified: lemon/trunk/lemon/lp_skeleton.cc
==============================================================================
--- lemon/trunk/lemon/lp_skeleton.cc	(original)
+++ lemon/trunk/lemon/lp_skeleton.cc	Tue Apr  8 18:01:28 2008
@@ -22,16 +22,16 @@
 ///\brief A skeleton file to implement LP solver interfaces
 namespace lemon {
   
-  LpSolverBase &LpSkeleton::_newLp()
+  LpSolverBase* LpSkeleton::_newLp()
   {
     LpSolverBase *tmp=0;
-    return *tmp;
+    return tmp;
   }
   
-  LpSolverBase &LpSkeleton::_copyLp()
+  LpSolverBase* LpSkeleton::_copyLp()
   {
     LpSolverBase *tmp=0;
-    return *tmp;
+    return tmp;
   }
 
   int LpSkeleton::_addCol()

Modified: lemon/trunk/lemon/lp_skeleton.h
==============================================================================
--- lemon/trunk/lemon/lp_skeleton.h	(original)
+++ lemon/trunk/lemon/lp_skeleton.h	Tue Apr  8 18:01:28 2008
@@ -32,9 +32,9 @@
   protected:
 
     ///\e
-    virtual LpSolverBase &_newLp();
+    virtual LpSolverBase* _newLp();
     ///\e
-    virtual LpSolverBase &_copyLp();
+    virtual LpSolverBase* _copyLp();
     /// \e
     virtual int _addCol();
     /// \e

Modified: lemon/trunk/lemon/lp_soplex.cc
==============================================================================
--- lemon/trunk/lemon/lp_soplex.cc	(original)
+++ lemon/trunk/lemon/lp_soplex.cc	Tue Apr  8 18:01:28 2008
@@ -36,16 +36,33 @@
   LpSoplex::~LpSoplex() {
     delete soplex;
   }
+
+  LpSoplex::LpSoplex(const LpSoplex& lp) : LpSolverBase() {
+    rows = lp.rows;
+    rows.setIdHandler(relocateIdHandler);
+
+    cols = lp.cols;
+    cols.setIdHandler(relocateIdHandler);
+
+    soplex = new soplex::SoPlex;
+    (*static_cast<soplex::SPxLP*>(soplex)) = *(lp.soplex);
+
+    colNames = lp.colNames;
+    invColNames = lp.invColNames;
+
+    primal_value = lp.primal_value;
+    dual_value = lp.dual_value;
+
+  }
   
-  LpSolverBase &LpSoplex::_newLp() {
+  LpSolverBase* LpSoplex::_newLp() {
     LpSoplex* newlp = new LpSoplex();
-    return *newlp;
+    return newlp;
   }
 
-  LpSolverBase &LpSoplex::_copyLp() {
-    LpSoplex* newlp = new LpSoplex();
-    (*static_cast<soplex::SPxLP*>(newlp->soplex)) = *soplex;
-    return *newlp;
+  LpSolverBase* LpSoplex::_copyLp() {
+    LpSoplex* newlp = new LpSoplex(*this);
+    return newlp;
   }
 
   int LpSoplex::_addCol() {

Modified: lemon/trunk/lemon/lp_soplex.h
==============================================================================
--- lemon/trunk/lemon/lp_soplex.h	(original)
+++ lemon/trunk/lemon/lp_soplex.h	Tue Apr  8 18:01:28 2008
@@ -66,12 +66,14 @@
     /// \e
     LpSoplex();
     /// \e
+    LpSoplex(const LpSoplex&);
+    /// \e
     ~LpSoplex();
 
   protected:
 
-    virtual LpSolverBase &_newLp();
-    virtual LpSolverBase &_copyLp();
+    virtual LpSolverBase* _newLp();
+    virtual LpSolverBase* _copyLp();
 
     virtual int _addCol();
     virtual int _addRow();

Modified: lemon/trunk/test/lp_test.cc
==============================================================================
--- lemon/trunk/test/lp_test.cc	(original)
+++ lemon/trunk/test/lp_test.cc	Tue Apr  8 18:01:28 2008
@@ -20,6 +20,7 @@
 #include <lemon/lp_skeleton.h>
 #include "test_tools.h"
 #include <lemon/tolerance.h>
+#include <lemon/lp_utils.h>
 
 #ifdef HAVE_CONFIG_H
 #include <lemon/config.h>
@@ -216,7 +217,8 @@
   
   {
     LP::DualExpr e,f,g;
-    LP::Row p1,p2,p3,p4,p5;
+    LP::Row p1 = INVALID, p2 = INVALID, p3 = INVALID, 
+      p4 = INVALID, p5 = INVALID;
     
     e[p1]=2;
     e[p1]+=2;
@@ -295,7 +297,6 @@
 
   lp.max();
 
-
   //Testing the problem retrieving routines
   check(lp.objCoeff(x1)==1,"First term should be 1 in the obj function!");
   check(lp.isMax(),"This is a maximization!");
@@ -307,7 +308,39 @@
   lp.getRowBounds(upright,lb,ub);
   check(  lb==-LpSolverBase::INF,"The lower bound for the first row should be -infty.");
   check(  ub==1,"The upper bound for the first row should be 1.");
+  LpSolverBase::Expr e = lp.row(upright);
+  check(  e.size() == 2, "The row retrieval gives back wrong expression.");
+  check(  e[x1] == 1, "The first coefficient should 1.");
+  check(  e[x2] == 1, "The second coefficient should 1.");
+
+  LpSolverBase::DualExpr de = lp.col(x1);
+  check(  de.size() == 4, "The col retrieval gives back wrong expression.");
+  check(  de[upright] == 1, "The first coefficient should 1.");
 
+  LpSolverBase* clp = lp.copyLp();
+
+  //Testing the problem retrieving routines
+  check(clp->objCoeff(x1)==1,"First term should be 1 in the obj function!");
+  check(clp->isMax(),"This is a maximization!");
+  check(clp->coeff(upright,x1)==1,"The coefficient in question is 1!");
+  //  std::cout<<lp.colLowerBound(x1)<<std::endl;
+  check(  clp->colLowerBound(x1)==0,"The lower bound for variable x1 should be 0.");
+  std::cerr << clp->colUpperBound(x1) << std::endl;
+  check(  clp->colUpperBound(x1)==LpSolverBase::INF,"The upper bound for variable x1 should be infty.");
+
+  clp->getRowBounds(upright,lb,ub);
+  check(  lb==-LpSolverBase::INF,"The lower bound for the first row should be -infty.");
+  check(  ub==1,"The upper bound for the first row should be 1.");
+  e = clp->row(upright);
+  check(  e.size() == 2, "The row retrieval gives back wrong expression.");
+  check(  e[x1] == 1, "The first coefficient should 1.");
+  check(  e[x2] == 1, "The second coefficient should 1.");
+
+  de = clp->col(x1);
+  check(  de.size() == 4, "The col retrieval gives back wrong expression.");
+  check(  de[upright] == 1, "The first coefficient should 1.");
+  
+  delete clp;
 
   //Maximization of x1+x2
   //over the triangle with vertices (0,0) (0,1) (1,0)
@@ -338,6 +371,7 @@
   lp.min();
   check(lp.primalStatus()==LpSolverBase::UNDEFINED,"Primalstatus should be UNDEFINED");
 
+
 //   lp.solve();
 //   if (lp.primalStatus()==LpSolverBase::OPTIMAL){
 //     std::cout<< "Z = "<<lp.primalValue()



More information about the Lemon-commits mailing list