Interface to the cplex MIP solver: it is little, a bit sour but it is ours.
authorathos
Thu, 21 Sep 2006 14:46:28 +0000
changeset 221850f1a780a5ff
parent 2217 4a10a45d55f6
child 2219 c263168e0964
Interface to the cplex MIP solver: it is little, a bit sour but it is ours.
lemon/Makefile.am
lemon/lp.h
lemon/lp_base.h
lemon/lp_cplex.cc
lemon/lp_cplex.h
lemon/mip_glpk.cc
lemon/mip_glpk.h
test/mip_test.cc
     1.1 --- a/lemon/Makefile.am	Thu Sep 14 19:58:29 2006 +0000
     1.2 +++ b/lemon/Makefile.am	Thu Sep 21 14:46:28 2006 +0000
     1.3 @@ -25,6 +25,7 @@
     1.4  
     1.5  if HAVE_CPLEX
     1.6  lemon_libemon_la_SOURCES += lemon/lp_cplex.cc
     1.7 +lemon_libemon_la_SOURCES += lemon/mip_cplex.cc
     1.8  endif
     1.9  
    1.10  lemon_HEADERS += \
    1.11 @@ -78,6 +79,7 @@
    1.12  	lemon/min_cost_flow.h \
    1.13  	lemon/min_cut.h \
    1.14  	lemon/mip_glpk.h \
    1.15 +	lemon/mip_cplex.h \
    1.16  	lemon/path.h \
    1.17  	lemon/polynomial.h \
    1.18  	lemon/preflow.h \
     2.1 --- a/lemon/lp.h	Thu Sep 14 19:58:29 2006 +0000
     2.2 +++ b/lemon/lp.h	Thu Sep 21 14:46:28 2006 +0000
     2.3 @@ -21,18 +21,20 @@
     2.4  
     2.5  #include<lemon/config.h>
     2.6  
     2.7 +
     2.8  #ifdef HAVE_GLPK
     2.9  #include <lemon/lp_glpk.h>
    2.10  #include <lemon/mip_glpk.h>
    2.11  #elif HAVE_CPLEX
    2.12  #include <lemon/lp_cplex.h>
    2.13 +#include <lemon/mip_cplex.h>
    2.14  #endif
    2.15  
    2.16  ///\file
    2.17  ///\brief Defines a default LP solver
    2.18  ///\ingroup gen_opt_group
    2.19  namespace lemon {
    2.20 - 
    2.21 +
    2.22  #ifdef DOXYGEN
    2.23    ///The default LP solver identifier
    2.24  
    2.25 @@ -72,6 +74,7 @@
    2.26  #elif HAVE_CPLEX
    2.27  #define DEFAULT_LP CPLEX
    2.28    typedef LpCplex Lp;
    2.29 +  typedef MipCplex Mip;
    2.30    const char default_solver_name[]="CPLEX";
    2.31  #endif
    2.32  #endif
     3.1 --- a/lemon/lp_base.h	Thu Sep 14 19:58:29 2006 +0000
     3.2 +++ b/lemon/lp_base.h	Thu Sep 21 14:46:28 2006 +0000
     3.3 @@ -75,8 +75,10 @@
     3.4  	}
     3.5  	return cross[n];
     3.6        }
     3.7 -      ///\todo Create an own exception type.
     3.8 -      else throw LogicError(); //floatingId-s must form a continuous range;
     3.9 +      else {
    3.10 +	///\todo Create an own exception type.
    3.11 +	throw LogicError(); //floatingId-s must form a continuous range;
    3.12 +      }
    3.13      }
    3.14      ///Remove a fix id.
    3.15  
    3.16 @@ -1169,7 +1171,10 @@
    3.17        ///Continuous variable
    3.18        REAL = 0,
    3.19        ///Integer variable
    3.20 -      INTEGER = 1
    3.21 +
    3.22 +      ///Unfortunately, cplex 7.5 somewhere writes something like
    3.23 +      ///#define INTEGER 'I'
    3.24 +      LEMON_INTEGER = 1
    3.25        ///\todo No support for other types yet.
    3.26      };
    3.27  
    3.28 @@ -1192,7 +1197,7 @@
    3.29      ///Sets the type of the given Col to integer or remove that property.
    3.30      void integer(Col c, bool enable) {
    3.31        if (enable)
    3.32 -	colType(c,INTEGER);
    3.33 +	colType(c,LEMON_INTEGER);
    3.34        else
    3.35  	colType(c,REAL);
    3.36      }
    3.37 @@ -1202,7 +1207,7 @@
    3.38      ///Gives back the type of the column.
    3.39      ///\return true if the column has integer type and false if not.
    3.40      bool integer(Col c){
    3.41 -      return (colType(c)==INTEGER);
    3.42 +      return (colType(c)==LEMON_INTEGER);
    3.43      }
    3.44  
    3.45      /// The status of the MIP problem
     4.1 --- a/lemon/lp_cplex.cc	Thu Sep 14 19:58:29 2006 +0000
     4.2 +++ b/lemon/lp_cplex.cc	Thu Sep 21 14:46:28 2006 +0000
     4.3 @@ -269,7 +269,7 @@
     4.4      //CPX_PARAM_LPMETHOD 
     4.5      status = CPXlpopt(env, lp);
     4.6      //status = CPXprimopt(env, lp);
     4.7 -#if CPX_VERSION >= 900
     4.8 +#if CPX_VERSION >= 800
     4.9      if (status)
    4.10      {
    4.11        return UNSOLVED;
    4.12 @@ -416,8 +416,23 @@
    4.13  
    4.14    LpCplex::SolutionStatus LpCplex::_getPrimalStatus()
    4.15    {
    4.16 +    //Unboundedness not treated well: the following is from cplex 9.0 doc
    4.17 +    // About Unboundedness
    4.18 +
    4.19 +    // The treatment of models that are unbounded involves a few
    4.20 +    // subtleties. Specifically, a declaration of unboundedness means that
    4.21 +    // ILOG CPLEX has determined that the model has an unbounded
    4.22 +    // ray. Given any feasible solution x with objective z, a multiple of
    4.23 +    // the unbounded ray can be added to x to give a feasible solution
    4.24 +    // with objective z-1 (or z+1 for maximization models). Thus, if a
    4.25 +    // feasible solution exists, then the optimal objective is
    4.26 +    // unbounded. Note that ILOG CPLEX has not necessarily concluded that
    4.27 +    // a feasible solution exists. Users can call the routine CPXsolninfo
    4.28 +    // to determine whether ILOG CPLEX has also concluded that the model
    4.29 +    // has a feasible solution.
    4.30 +
    4.31      int stat = CPXgetstat(env, lp);
    4.32 -#if CPX_VERSION >= 900
    4.33 +#if CPX_VERSION >= 800
    4.34      switch (stat)
    4.35      {
    4.36        case CPX_STAT_OPTIMAL:
    4.37 @@ -485,7 +500,7 @@
    4.38    LpCplex::SolutionStatus LpCplex::_getDualStatus()
    4.39    {
    4.40      int stat = CPXgetstat(env, lp);
    4.41 -#if CPX_VERSION >= 900
    4.42 +#if CPX_VERSION >= 800
    4.43      switch (stat)
    4.44      {
    4.45        case CPX_STAT_OPTIMAL:
    4.46 @@ -514,7 +529,7 @@
    4.47    LpCplex::ProblemTypes LpCplex::_getProblemType()
    4.48    {
    4.49      int stat = CPXgetstat(env, lp);
    4.50 -#if CPX_VERSION >= 900
    4.51 +#if CPX_VERSION >= 800
    4.52      switch (stat)
    4.53      {
    4.54        case CPX_STAT_OPTIMAL:
     5.1 --- a/lemon/lp_cplex.h	Thu Sep 14 19:58:29 2006 +0000
     5.2 +++ b/lemon/lp_cplex.h	Thu Sep 21 14:46:28 2006 +0000
     5.3 @@ -34,7 +34,7 @@
     5.4    /// \brief Interface for the CPLEX solver
     5.5    /// 
     5.6    /// This class implements an interface for the CPLEX LP solver.
     5.7 -  class LpCplex : public LpSolverBase {
     5.8 +  class LpCplex :virtual public LpSolverBase {
     5.9  
    5.10    public:
    5.11  
     6.1 --- a/lemon/mip_glpk.cc	Thu Sep 14 19:58:29 2006 +0000
     6.2 +++ b/lemon/mip_glpk.cc	Thu Sep 21 14:46:28 2006 +0000
     6.3 @@ -16,11 +16,11 @@
     6.4   *
     6.5   */
     6.6  
     6.7 -#ifndef LEMON_ILP_GLPK_CC
     6.8 -#define LEMON_ILP_GLPK_CC
     6.9 +#ifndef LEMON_MIP_GLPK_CC
    6.10 +#define LEMON_MIP_GLPK_CC
    6.11  
    6.12  ///\file
    6.13 -///\brief Implementation of the LEMON-GLPK lp solver interface.
    6.14 +///\brief Implementation of the LEMON-GLPK mip solver interface.
    6.15  
    6.16  #include <lemon/mip_glpk.h>
    6.17  
    6.18 @@ -32,7 +32,7 @@
    6.19  
    6.20    void MipGlpk::_colType(int i, MipGlpk::ColTypes col_type){
    6.21      switch (col_type){
    6.22 -      case INTEGER:
    6.23 +      case LEMON_INTEGER:
    6.24  	lpx_set_col_kind(lp,i,LPX_IV);
    6.25  	break;
    6.26        case REAL:
    6.27 @@ -46,7 +46,7 @@
    6.28    MipGlpk::ColTypes MipGlpk::_colType(int i){
    6.29      switch (lpx_get_col_kind(lp,i)){
    6.30      case LPX_IV:
    6.31 -      return INTEGER;//Or binary
    6.32 +      return LEMON_INTEGER;//Or binary
    6.33      case LPX_CV:
    6.34        return REAL;
    6.35      default:
    6.36 @@ -110,6 +110,6 @@
    6.37    MipGlpk::Value MipGlpk::_getPrimalValue(){
    6.38      return lpx_mip_obj_val(lp);
    6.39    }
    6.40 -} //END OG NAMESPACE LEMON
    6.41 +} //END OF NAMESPACE LEMON
    6.42  
    6.43 -#endif
    6.44 +#endif //END OF MIP_GLPK_CC
     7.1 --- a/lemon/mip_glpk.h	Thu Sep 14 19:58:29 2006 +0000
     7.2 +++ b/lemon/mip_glpk.h	Thu Sep 21 14:46:28 2006 +0000
     7.3 @@ -16,20 +16,20 @@
     7.4   *
     7.5   */
     7.6  
     7.7 -#ifndef LEMON_ILP_GLPK_H
     7.8 -#define LEMON_ILP_GLPK_H
     7.9 +#ifndef LEMON_MIP_GLPK_H
    7.10 +#define LEMON_MIP_GLPK_H
    7.11  
    7.12  ///\file
    7.13 -///\brief Header of the LEMON-GLPK lp solver interface.
    7.14 +///\brief Header of the LEMON-GLPK mip solver interface.
    7.15  ///\ingroup gen_opt_group
    7.16  
    7.17  
    7.18  #include <lemon/lp_glpk.h>
    7.19  
    7.20  namespace lemon {
    7.21 -  /// \brief Interface for the GLPK ILP solver
    7.22 +  /// \brief Interface for the GLPK MIP solver
    7.23    /// 
    7.24 -  /// This class implements an interface for the GLPK ILP solver.
    7.25 +  /// This class implements an interface for the GLPK MIP solver.
    7.26    ///\ingroup gen_opt_group
    7.27    class MipGlpk : public MipSolverBase, public LpGlpk{
    7.28    
    7.29 @@ -56,4 +56,4 @@
    7.30  
    7.31  } //END OF NAMESPACE LEMON
    7.32  
    7.33 -#endif // END OF LEMON_ILP_GLPK_H
    7.34 +#endif // END OF LEMON_MIP_GLPK_H
     8.1 --- a/test/mip_test.cc	Thu Sep 14 19:58:29 2006 +0000
     8.2 +++ b/test/mip_test.cc	Thu Sep 21 14:46:28 2006 +0000
     8.3 @@ -1,20 +1,26 @@
     8.4 -#include <lemon/lp.h>
     8.5  #include "test_tools.h"
     8.6  
     8.7 +
     8.8 +#include <lemon/mip_cplex.h>
     8.9 +#include <lemon/mip_glpk.h>
    8.10 +#include<lemon/config.h>
    8.11 +
    8.12  using namespace lemon;
    8.13  
    8.14 -void solveAndCheck(Mip& lp, LpSolverBase::SolutionStatus stat, 
    8.15 +void solveAndCheck(MipSolverBase& lp, MipSolverBase::SolutionStatus stat, 
    8.16  		   double exp_opt) {
    8.17    using std::string;
    8.18 +
    8.19    lp.solve();
    8.20    //int decimal,sign;
    8.21    std::ostringstream buf;
    8.22    buf << "Primalstatus should be: " << int(stat)<<" and it is "<<int(lp.primalStatus());
    8.23  
    8.24 +
    8.25    //  itoa(stat,buf1, 10);
    8.26    check(lp.mipStatus()==stat, buf.str());
    8.27  
    8.28 -  if (stat ==  LpSolverBase::OPTIMAL) {
    8.29 +  if (stat ==  MipSolverBase::OPTIMAL) {
    8.30      std::ostringstream buf;
    8.31      buf << "Wrong optimal value: the right optimum is " << exp_opt; 
    8.32      check(std::abs(lp.primalValue()-exp_opt) < 1e-3, buf.str());
    8.33 @@ -22,22 +28,20 @@
    8.34    }
    8.35  }
    8.36  
    8.37 -void aTest(Mip& mip)
    8.38 +void aTest(MipSolverBase& mip)
    8.39  {
    8.40   //The following example is very simple
    8.41  
    8.42 -  typedef Mip::Row Row;
    8.43 -  typedef Mip::Col Col;
    8.44 +
    8.45 +  typedef MipSolverBase::Row Row;
    8.46 +  typedef MipSolverBase::Col Col;
    8.47 +
    8.48  
    8.49  
    8.50    Col x1 = mip.addCol();
    8.51    Col x2 = mip.addCol();
    8.52  
    8.53  
    8.54 -
    8.55 -
    8.56 -
    8.57 -
    8.58    //Objective function
    8.59    mip.setObj(x1);
    8.60  
    8.61 @@ -60,18 +64,18 @@
    8.62    //Maximization of x1
    8.63    //over the triangle with vertices 
    8.64    double expected_opt=4.0/5.0;
    8.65 -  solveAndCheck(mip, Mip::OPTIMAL, expected_opt);
    8.66 +  solveAndCheck(mip, MipSolverBase::OPTIMAL, expected_opt);
    8.67  
    8.68    //Restrict x2 to integer
    8.69 -  mip.colType(x2,Mip::INTEGER);  
    8.70 +  mip.colType(x2,MipSolverBase::LEMON_INTEGER);  
    8.71    expected_opt=1.0/2.0;
    8.72 -  solveAndCheck(mip, Mip::OPTIMAL, expected_opt);
    8.73 +  solveAndCheck(mip, MipSolverBase::OPTIMAL, expected_opt);
    8.74  
    8.75  
    8.76    //Restrict both to integer
    8.77 -  mip.colType(x1,Mip::INTEGER);  
    8.78 +  mip.colType(x1,MipSolverBase::LEMON_INTEGER);  
    8.79    expected_opt=0;
    8.80 -  solveAndCheck(mip, Mip::OPTIMAL, expected_opt);
    8.81 +  solveAndCheck(mip, MipSolverBase::OPTIMAL, expected_opt);
    8.82  
    8.83   
    8.84  
    8.85 @@ -86,6 +90,14 @@
    8.86    aTest(mip1);
    8.87  #endif
    8.88  
    8.89 +
    8.90 +
    8.91 +#ifdef HAVE_CPLEX
    8.92 +  //std::cout<<ATTILA<<INTEGER;
    8.93 +  MipCplex mip2;
    8.94 +  aTest(mip2);
    8.95 +#endif
    8.96 +
    8.97    return 0;
    8.98  
    8.99  }