# HG changeset patch # User alpar # Date 1114192021 0 # Node ID 998e8def9676c2fc03199c560b2c4a5a4993f011 # Parent cb2891afe526cc3db01706fe236126bbabbb3e8e - lp_cplex.h, lp_cplex.cc added - lp_demo.cc and lp_maxflow_demo.cc uses GLPK is it is found CPLEX otherwise diff -r cb2891afe526 -r 998e8def9676 src/demo/Makefile.am --- a/src/demo/Makefile.am Fri Apr 22 16:20:12 2005 +0000 +++ b/src/demo/Makefile.am Fri Apr 22 17:47:01 2005 +0000 @@ -1,6 +1,17 @@ AM_CPPFLAGS = -I$(top_srcdir)/src LDADD = $(top_builddir)/src/lemon/libemon.la +if HAVE_GLPK +LP_CFLAGS = $(GLPK_CFLAGS) -DHAVE_GLPK +LP_LIBS = $(GLPK_LIBS) +else !HAVE_GLPK +if HAVE_CPLEX +LP_CFLAGS = $(CPLEX_CFLAGS) -DHAVE_CPLEX +LP_LIBS = $(CPLEX_LIBS) +endif HAVE_CPLEX +endif !HAVE_GLPK + + EXTRA_DIST = sub_graph_wrapper_demo.dim noinst_PROGRAMS = \ @@ -12,7 +23,12 @@ if HAVE_GLPK noinst_PROGRAMS += lp_demo lp_maxflow_demo -endif +else !HAVE_GLPK +if HAVE_CPLEX +noinst_PROGRAMS += lp_demo lp_maxflow_demo +endif HAVE_CPLEX +endif !HAVE_GLPK + dim_to_dot_SOURCES = dim_to_dot.cc @@ -27,9 +43,9 @@ tight_edge_filter_map.h lp_demo_SOURCES = lp_demo.cc -lp_demo_CXXFLAGS = $(GLPK_CFLAGS) -lp_demo_LDFLAGS = $(GLPK_LIBS) +lp_demo_CXXFLAGS = $(LP_CFLAGS) +lp_demo_LDFLAGS = $(LP_LIBS) lp_maxflow_demo_SOURCES = lp_maxflow_demo.cc -lp_maxflow_demo_CXXFLAGS = $(GLPK_CFLAGS) -lp_maxflow_demo_LDFLAGS = $(GLPK_LIBS) +lp_maxflow_demo_CXXFLAGS = $(LP_CFLAGS) +lp_maxflow_demo_LDFLAGS = $(LP_LIBS) diff -r cb2891afe526 -r 998e8def9676 src/demo/lp_demo.cc --- a/src/demo/lp_demo.cc Fri Apr 22 16:20:12 2005 +0000 +++ b/src/demo/lp_demo.cc Fri Apr 22 17:47:01 2005 +0000 @@ -1,14 +1,27 @@ #include + + +#ifdef HAVE_GLPK #include +#elif HAVE_CPLEX +#include +#endif + using namespace lemon; +#ifdef HAVE_GLPK +typedef LpGlpk LpDefault; +#elif HAVE_CPLEX +typedef LpCplex LpDefault; +#endif + int main() { //The following example is taken from the documentation of the GLPK library. //See it in the GLPK reference manual and among the GLPK sample files (sample.c) - LpGlpk lp; - typedef LpGlpk::Row Row; - typedef LpGlpk::Col Col; + LpDefault lp; + typedef LpDefault::Row Row; + typedef LpDefault::Col Col; lp.max(); diff -r cb2891afe526 -r 998e8def9676 src/demo/lp_maxflow_demo.cc --- a/src/demo/lp_maxflow_demo.cc Fri Apr 22 16:20:12 2005 +0000 +++ b/src/demo/lp_maxflow_demo.cc Fri Apr 22 17:47:01 2005 +0000 @@ -1,13 +1,26 @@ -#include #include #include + +#ifdef HAVE_GLPK +#include +#elif HAVE_CPLEX +#include +#endif + using namespace lemon; +#ifdef HAVE_GLPK +typedef LpGlpk LpDefault; +#elif HAVE_CPLEX +typedef LpCplex LpDefault; +#endif + + template double maxFlow(const G &g,const C &cap,typename G::Node s,typename G::Node t) { - LpGlpk lp; + LpDefault lp; typedef G Graph; typedef typename G::Node Node; @@ -17,7 +30,7 @@ typedef typename G::OutEdgeIt OutEdgeIt; typedef typename G::InEdgeIt InEdgeIt; - typename G::template EdgeMap x(g); + typename G::template EdgeMap x(g); lp.addColSet(x); for(EdgeIt e(g);e!=INVALID;++e) { @@ -26,22 +39,23 @@ } for(NodeIt n(g);n!=INVALID;++n) if(n!=s&&n!=t) { - LpGlpk::Expr ex; + LpDefault::Expr ex; for(InEdgeIt e(g,n);e!=INVALID;++e) ex+=x[e]; for(OutEdgeIt e(g,n);e!=INVALID;++e) ex-=x[e]; lp.addRow(ex==0); } { - LpGlpk::Expr ex; + LpDefault::Expr ex; for(InEdgeIt e(g,t);e!=INVALID;++e) ex+=x[e]; for(OutEdgeIt e(g,t);e!=INVALID;++e) ex-=x[e]; lp.setObj(ex); } lp.max(); +#ifdef HAVE_GLPK lp.presolver(true); - lp.messageLevel(3); +#endif lp.solve(); diff -r cb2891afe526 -r 998e8def9676 src/lemon/Makefile.am --- a/src/lemon/Makefile.am Fri Apr 22 16:20:12 2005 +0000 +++ b/src/lemon/Makefile.am Fri Apr 22 17:47:01 2005 +0000 @@ -15,6 +15,12 @@ libemon_la_LDFLAGS = $(GLPK_LIBS) endif +if HAVE_CPLEX +libemon_la_SOURCES += lp_cplex.cc +libemon_la_CXXFLAGS = $(CPLEX_CFLAGS) +libemon_la_LDFLAGS = $(CPLEX_LIBS) +endif + nobase_pkginclude_HEADERS = \ bezier.h \ bfs.h \ @@ -32,6 +38,7 @@ kruskal.h \ list_graph.h \ lp_base.h \ + lp_cplex.h \ lp_glpk.h \ lp_skeleton.h \ maps.h \ diff -r cb2891afe526 -r 998e8def9676 src/lemon/lp_base.h --- a/src/lemon/lp_base.h Fri Apr 22 16:20:12 2005 +0000 +++ b/src/lemon/lp_base.h Fri Apr 22 17:47:01 2005 +0000 @@ -464,7 +464,7 @@ ///Creates a new LP problem LpSolverBase &newLp() {return _newLp();} - ///Make a copy of the LP problem + ///Makes a copy of the LP problem LpSolverBase ©Lp() {return _copyLp();} ///\name Build up and modify of the LP diff -r cb2891afe526 -r 998e8def9676 src/lemon/lp_cplex.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lemon/lp_cplex.cc Fri Apr 22 17:47:01 2005 +0000 @@ -0,0 +1,309 @@ +/* -*- C++ -*- + * src/lemon/lp_cplex.cc + * - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 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. + * + */ + +#include"lp_cplex.h" + +///\file +///\brief Implementation of the LEMON-CPLEX lp solver interface. +namespace lemon { + + LpCplex::LpCplex() : LpSolverBase() { + env = NULL; + lp = NULL; + env = CPXopenCPLEXdevelop(&status); +// if (Env == NULL) +// { +// fprintf(stderr,"A CPLEX környezet megnyitása sikertelen.\n"); +// CPXgeterrorstring(Env, Status, ErrorMsg); +// fprintf(stderr,"%s",ErrorMsg); +// goto Terminate; +// } + + // *** A problema létrehozása *** + lp = CPXcreateprob(env, &status, "LP problem"); + + // if (Problem == NULL) +// { +// fprintf(stderr,"Az LP létrehozása sikertelen"); +// goto Terminate; +// } + + } + + LpCplex::~LpCplex() { + status = CPXfreeprob(env,&lp); + // if (Status != 0) + // { +// fprintf(stderr,"A CPLEX feladat törlése sikertelen.\n"); +// CPXgeterrorstring(Env, Status, ErrorMsg); +// fprintf(stderr,"%s",ErrorMsg); +// goto Terminate; +// } + + status = CPXcloseCPLEX(&env); + // if (Status != 0) + // { + // fprintf(stderr,"A CPLEX környezet bezárása sikertelen.\n"); +// CPXgeterrorstring(Env, Status, ErrorMsg); +// fprintf(stderr,"%s",ErrorMsg); +// goto Terminate; +// } + + } + + LpSolverBase &LpCplex::_newLp() {return *(LpSolverBase*)0;} + LpSolverBase &LpCplex::_copyLp() {return *(LpSolverBase*)0;} + + int LpCplex::_addCol() + { + int i = CPXgetnumcols (env, lp); + Value lb[1],ub[1]; + lb[0]=-INF;//-CPX_INFBOUND; + ub[0]=INF;//CPX_INFBOUND; + status = CPXnewcols (env, lp, 1, NULL, lb, ub, NULL, NULL); + return i; + } + + int LpCplex::_addRow() + { + //We want a row that is not constrained + char sense[1]; + sense[0]='L';//<= constraint + Value rhs[1]; + rhs[0]=INF; + int i = CPXgetnumrows (env, lp); + status = CPXnewrows (env, lp, 1, rhs, sense, NULL, NULL); + return i; + } + + ///\warning Data at index 0 is ignored in the arrays. + void LpCplex::_setRowCoeffs(int i, + int length, + int const * indices, + Value const * values ) + { + int rowlist[length+1]; + int* p=rowlist; + for (int k=1;k<=length;++k){ + rowlist[k]=i; + } + status = CPXchgcoeflist(env, lp, + length, + p+1, + const_cast(indices+1), + const_cast(values+1)); + } + + void LpCplex::_setColCoeffs(int i, + int length, + int const * indices, + Value const * values) + { + int collist[length+1]; + int* p=collist; + for (int k=1;k<=length;++k){ + collist[k]=i; + } + status = CPXchgcoeflist(env, lp, + length, + const_cast(indices+1), + p+1, + const_cast(values+1)); + } + + void LpCplex::_setColLowerBound(int i, Value value) + { + int indices[1]; + indices[0]=i; + char lu[1]; + lu[0]='L'; + Value bd[1]; + bd[0]=value; + status = CPXchgbds (env, lp, 1, indices, lu, bd); + + } + + void LpCplex::_setColUpperBound(int i, Value value) + { + int indices[1]; + indices[0]=i; + char lu[1]; + lu[0]='U'; + Value bd[1]; + bd[0]=value; + status = CPXchgbds (env, lp, 1, indices, lu, bd); + } + + //This will be easier to implement + void LpCplex::_setRowBounds(int i, Value lb, Value ub) + { + //Bad parameter + if (lb==INF || ub==-INF) { + //FIXME error + } + + int cnt=1; + int indices[1]; + indices[0]=i; + char sense[1]; + + if (lb==-INF){ + sense[0]='L'; + CPXchgsense (env, lp, cnt, indices, sense); + CPXchgcoef (env, lp, i, -1, ub); + } + else{ + if (ub==INF){ + sense[0]='G'; + CPXchgsense (env, lp, cnt, indices, sense); + CPXchgcoef (env, lp, i, -1, lb); + } + else{ + if (lb == ub){ + sense[0]='E'; + CPXchgsense (env, lp, cnt, indices, sense); + CPXchgcoef (env, lp, i, -1, lb); + } + else{ + sense[0]='R'; + CPXchgsense (env, lp, cnt, indices, sense); + CPXchgcoef (env, lp, i, -1, lb); + CPXchgcoef (env, lp, i, -2, ub-lb); + } + } + } + } + + void LpCplex::_setRowLowerBound(int i, Value value) + { + //Not implemented, obsolete + } + + void LpCplex::_setRowUpperBound(int i, Value value) + { + //Not implemented, obsolete +// //TODO Ezt kell meg megirni +// //type of the problem +// char sense[1]; +// status = CPXgetsense (env, lp, sense, i, i); +// Value rhs[1]; +// status = CPXgetrhs (env, lp, rhs, i, i); + +// switch (sense[0]) { +// case 'L'://<= constraint +// break; +// case 'E'://= constraint +// break; +// case 'G'://>= constraint +// break; +// case 'R'://ranged constraint +// break; +// default: ; +// //FIXME error +// } + +// status = CPXchgcoef (env, lp, i, -2, value_rng); + } + + void LpCplex::_setObjCoeff(int i, Value obj_coef) + { + CPXchgcoef (env, lp, -1, i, obj_coef); + } + + void LpCplex::_clearObj() + { + for (int i=0;i< CPXgetnumcols (env, lp);++i){ + CPXchgcoef (env, lp, -1, i, 0); + } + + } + + LpCplex::SolveExitStatus LpCplex::_solve() + { + + status = CPXlpopt (env, lp); + if (status == 0){ + return SOLVED; + } + else{ + return UNSOLVED; + } +// int i= lpx_simplex(lp); +// switch (i) { +// case LPX_E_OK: +// return SOLVED; +// break; +// default: +// return UNSOLVED; +// } + } + + LpCplex::SolutionStatus LpCplex::_getPrimalStatus() + { + //Unimplemented + return OPTIMAL; +// int stat= lpx_get_status(lp); +// switch (stat) { +// case LPX_UNDEF://Undefined (no solve has been run yet) +// return UNDEFINED; +// break; +// case LPX_NOFEAS://There is no feasible solution (primal, I guess) +// case LPX_INFEAS://Infeasible +// return INFEASIBLE; +// break; +// case LPX_UNBND://Unbounded +// return INFINITE; +// break; +// case LPX_FEAS://Feasible +// return FEASIBLE; +// break; +// case LPX_OPT://Feasible +// return OPTIMAL; +// break; +// default: +// return UNDEFINED; //to avoid gcc warning +// //FIXME error +// } + } + + LpCplex::Value LpCplex::_getPrimal(int i) + { + Value x; + CPXgetx (env, lp, &x, i, i); + return x; + } + + LpCplex::Value LpCplex::_getPrimalValue() + { + //Unimplemented + return 0; + } + + + + + void LpCplex::_setMax() + { + CPXchgobjsen (env, lp, CPX_MAX); + } + void LpCplex::_setMin() + { + CPXchgobjsen (env, lp, CPX_MIN); + } + +} //namespace lemon + diff -r cb2891afe526 -r 998e8def9676 src/lemon/lp_cplex.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lemon/lp_cplex.h Fri Apr 22 17:47:01 2005 +0000 @@ -0,0 +1,108 @@ +/* -*- C++ -*- + * src/lemon/lp_cplex.h - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 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_LP_CPLEX_H +#define LEMON_LP_CPLEX_H + +///\file +///\brief Header of the LEMON-CPLEX lp solver interface. + +#include +extern "C" { +#include +} + +namespace lemon { + + + /// \brief Wrapper for GLPK solver + /// + /// This class implements a lemon wrapper for GLPK. + class LpCplex : public LpSolverBase { + + public: + + typedef LpSolverBase Parent; + + /// \e + int status; + CPXENVptr env; + CPXLPptr lp; + + + /// \e + LpCplex(); + /// \e + ~LpCplex(); + + protected: + virtual LpSolverBase &_newLp(); + virtual LpSolverBase &_copyLp(); + + virtual int _addCol(); + virtual int _addRow(); + virtual void _setRowCoeffs(int i, + int length, + const int * indices, + const Value * values ); + virtual void _setColCoeffs(int i, + int length, + const int * indices, + const Value * values); + virtual void _setColLowerBound(int i, Value value); + virtual void _setColUpperBound(int i, Value value); + virtual void _setRowLowerBound(int i, Value value); + virtual void _setRowUpperBound(int i, Value value); + virtual void _setRowBounds(int i, Value lower, Value upper); + virtual void _setObjCoeff(int i, Value obj_coef); + virtual void _clearObj(); + ///\e + + ///\bug Unimplemented + /// + virtual SolveExitStatus _solve(); + ///\e + + ///\bug Unimplemented + /// + virtual Value _getPrimal(int i); + ///\e + + ///\bug Unimplemented + /// + virtual Value _getPrimalValue(); + ///\e + + ///\bug Unimplemented + /// + virtual SolutionStatus _getPrimalStatus(); + + ///\e + + ///\bug Unimplemented + /// + virtual void _setMax(); + ///\e + + ///\bug Unimplemented + /// + virtual void _setMin(); + + }; +} //END OF NAMESPACE LEMON + +#endif //LEMON_LP_CPLEX_H +