Interface to the cplex MIP solver: it is little, a bit sour but it is ours.
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 }