# HG changeset patch # User Balazs Dezso # Date 1239223768 -7200 # Node ID 745e182d01397d0fda77e4f76d031b11d7ad63aa # Parent 37216ca5b9c610a335e9dcdb941115003d1f3769 Unified message handling for LP and MIP solvers (#9) diff -r 37216ca5b9c6 -r 745e182d0139 lemon/cbc.cc --- a/lemon/cbc.cc Tue Apr 07 14:50:20 2009 +0100 +++ b/lemon/cbc.cc Wed Apr 08 22:49:28 2009 +0200 @@ -55,12 +55,15 @@ _prob->setProblemName("LEMON"); _osi_solver = 0; _cbc_model = 0; + messageLevel(MESSAGE_NOTHING); } CbcMip::CbcMip(const CbcMip& other) { _prob = new CoinModel(*other._prob); + _prob->setProblemName("LEMON"); _osi_solver = 0; _cbc_model = 0; + messageLevel(MESSAGE_NOTHING); } CbcMip::~CbcMip() { @@ -270,24 +273,8 @@ } _cbc_model= new CbcModel(*_osi_solver); - switch (_message_level) { - case MESSAGE_NO_OUTPUT: - _osi_solver->messageHandler()->setLogLevel(0); - _cbc_model->setLogLevel(0); - break; - case MESSAGE_ERROR_MESSAGE: - _osi_solver->messageHandler()->setLogLevel(1); - _cbc_model->setLogLevel(1); - break; - case MESSAGE_NORMAL_OUTPUT: - _osi_solver->messageHandler()->setLogLevel(2); - _cbc_model->setLogLevel(2); - break; - case MESSAGE_FULL_OUTPUT: - _osi_solver->messageHandler()->setLogLevel(3); - _cbc_model->setLogLevel(3); - break; - } + _osi_solver->messageHandler()->setLogLevel(_message_level); + _cbc_model->setLogLevel(_message_level); _cbc_model->initialSolve(); _cbc_model->solver()->setHintParam(OsiDoReducePrint, true, OsiHintTry); @@ -453,8 +440,24 @@ cols.clear(); } - void CbcMip::messageLevel(MessageLevel m) { - _message_level = m; + void CbcMip::_messageLevel(MessageLevel level) { + switch (level) { + case MESSAGE_NOTHING: + _message_level = 0; + break; + case MESSAGE_ERROR: + _message_level = 1; + break; + case MESSAGE_WARNING: + _message_level = 1; + break; + case MESSAGE_NORMAL: + _message_level = 2; + break; + case MESSAGE_VERBOSE: + _message_level = 3; + break; + } } } //END OF NAMESPACE LEMON diff -r 37216ca5b9c6 -r 745e182d0139 lemon/cbc.h --- a/lemon/cbc.h Tue Apr 07 14:50:20 2009 +0100 +++ b/lemon/cbc.h Wed Apr 08 22:49:28 2009 +0200 @@ -115,33 +115,12 @@ virtual void _clear(); - public: + virtual void _messageLevel(MessageLevel level); + void _applyMessageLevel(); - ///Enum for \c messageLevel() parameter - enum MessageLevel { - /// no output (default value) - MESSAGE_NO_OUTPUT = 0, - /// error messages only - MESSAGE_ERROR_MESSAGE = 1, - /// normal output - MESSAGE_NORMAL_OUTPUT = 2, - /// full output (includes informational messages) - MESSAGE_FULL_OUTPUT = 3 - }; + int _message_level; - private: - - MessageLevel _message_level; - - public: - - ///Set the verbosity of the messages - - ///Set the verbosity of the messages - /// - ///\param m is the level of the messages output by the solver routines. - void messageLevel(MessageLevel m); - + }; diff -r 37216ca5b9c6 -r 745e182d0139 lemon/clp.cc --- a/lemon/clp.cc Tue Apr 07 14:50:20 2009 +0100 +++ b/lemon/clp.cc Wed Apr 08 22:49:28 2009 +0200 @@ -24,7 +24,7 @@ ClpLp::ClpLp() { _prob = new ClpSimplex(); _init_temporals(); - messageLevel(MESSAGE_NO_OUTPUT); + messageLevel(MESSAGE_NOTHING); } ClpLp::ClpLp(const ClpLp& other) { @@ -32,7 +32,7 @@ rows = other.rows; cols = other.cols; _init_temporals(); - messageLevel(MESSAGE_NO_OUTPUT); + messageLevel(MESSAGE_NOTHING); } ClpLp::~ClpLp() { @@ -430,8 +430,24 @@ _clear_temporals(); } - void ClpLp::messageLevel(MessageLevel m) { - _prob->setLogLevel(static_cast(m)); + void ClpLp::_messageLevel(MessageLevel level) { + switch (level) { + case MESSAGE_NOTHING: + _prob->setLogLevel(0); + break; + case MESSAGE_ERROR: + _prob->setLogLevel(1); + break; + case MESSAGE_WARNING: + _prob->setLogLevel(2); + break; + case MESSAGE_NORMAL: + _prob->setLogLevel(3); + break; + case MESSAGE_VERBOSE: + _prob->setLogLevel(4); + break; + } } } //END OF NAMESPACE LEMON diff -r 37216ca5b9c6 -r 745e182d0139 lemon/clp.h --- a/lemon/clp.h Tue Apr 07 14:50:20 2009 +0100 +++ b/lemon/clp.h Wed Apr 08 22:49:28 2009 +0200 @@ -136,6 +136,8 @@ virtual void _clear(); + virtual void _messageLevel(MessageLevel); + public: ///Solves LP with primal simplex method. @@ -153,26 +155,6 @@ ///Returns the variable identifier understood by CLP. int clpCol(Col c) const { return cols(id(c)); } - ///Enum for \c messageLevel() parameter - enum MessageLevel { - /// no output (default value) - MESSAGE_NO_OUTPUT = 0, - /// print final solution - MESSAGE_FINAL_SOLUTION = 1, - /// print factorization - MESSAGE_FACTORIZATION = 2, - /// normal output - MESSAGE_NORMAL_OUTPUT = 3, - /// verbose output - MESSAGE_VERBOSE_OUTPUT = 4 - }; - ///Set the verbosity of the messages - - ///Set the verbosity of the messages - /// - ///\param m is the level of the messages output by the solver routines. - void messageLevel(MessageLevel m); - }; } //END OF NAMESPACE LEMON diff -r 37216ca5b9c6 -r 745e182d0139 lemon/cplex.cc --- a/lemon/cplex.cc Tue Apr 07 14:50:20 2009 +0100 +++ b/lemon/cplex.cc Wed Apr 08 22:49:28 2009 +0200 @@ -72,12 +72,14 @@ CplexBase::CplexBase() : LpBase() { int status; _prob = CPXcreateprob(cplexEnv(), &status, "Cplex problem"); + messageLevel(MESSAGE_NOTHING); } CplexBase::CplexBase(const CplexEnv& env) : LpBase(), _env(env) { int status; _prob = CPXcreateprob(cplexEnv(), &status, "Cplex problem"); + messageLevel(MESSAGE_NOTHING); } CplexBase::CplexBase(const CplexBase& cplex) @@ -86,6 +88,7 @@ _prob = CPXcloneprob(cplexEnv(), cplex._prob, &status); rows = cplex.rows; cols = cplex.cols; + messageLevel(MESSAGE_NOTHING); } CplexBase::~CplexBase() { @@ -438,6 +441,25 @@ cols.clear(); } + void CplexBase::_messageLevel(MessageLevel level) { + switch (level) { + case MESSAGE_NOTHING: + _message_enabled = false; + break; + case MESSAGE_ERROR: + case MESSAGE_WARNING: + case MESSAGE_NORMAL: + case MESSAGE_VERBOSE: + _message_enabled = true; + break; + } + } + + void CplexBase::_applyMessageLevel() { + CPXsetintparam(cplexEnv(), CPX_PARAM_SCRIND, + _message_enabled ? CPX_ON : CPX_OFF); + } + // CplexLp members CplexLp::CplexLp() @@ -507,21 +529,25 @@ CplexLp::SolveExitStatus CplexLp::_solve() { _clear_temporals(); + _applyMessageLevel(); return convertStatus(CPXlpopt(cplexEnv(), _prob)); } CplexLp::SolveExitStatus CplexLp::solvePrimal() { _clear_temporals(); + _applyMessageLevel(); return convertStatus(CPXprimopt(cplexEnv(), _prob)); } CplexLp::SolveExitStatus CplexLp::solveDual() { _clear_temporals(); + _applyMessageLevel(); return convertStatus(CPXdualopt(cplexEnv(), _prob)); } CplexLp::SolveExitStatus CplexLp::solveBarrier() { _clear_temporals(); + _applyMessageLevel(); return convertStatus(CPXbaropt(cplexEnv(), _prob)); } @@ -600,7 +626,7 @@ return _dual_ray[i]; } - //7.5-os cplex statusai (Vigyazat: a 9.0-asei masok!) + // Cplex 7.0 status values // This table lists the statuses, returned by the CPXgetstat() // routine, for solutions to LP problems or mixed integer problems. If // no solution exists, the return value is zero. @@ -647,7 +673,7 @@ // 20 CPX_PIVOT // User pivot used // - // Ezeket hova tegyem: + // Pending return values // ??case CPX_ABORT_DUAL_INFEAS // ??case CPX_ABORT_CROSSOVER // ??case CPX_INForUNBD @@ -718,7 +744,6 @@ #else statusSwitch(cplexEnv(),stat); //CPXgetstat(cplexEnv(), _prob); - //printf("A primal status: %d, CPX_OPTIMAL=%d \n",stat,CPX_OPTIMAL); switch (stat) { case 0: return UNDEFINED; //Undefined @@ -751,7 +776,7 @@ #endif } - //9.0-as cplex verzio statusai + // Cplex 9.0 status values // CPX_STAT_ABORT_DUAL_OBJ_LIM // CPX_STAT_ABORT_IT_LIM // CPX_STAT_ABORT_OBJ_LIM @@ -864,6 +889,7 @@ CplexMip::SolveExitStatus CplexMip::_solve() { int status; + _applyMessageLevel(); status = CPXmipopt (cplexEnv(), _prob); if (status==0) return SOLVED; diff -r 37216ca5b9c6 -r 745e182d0139 lemon/cplex.h --- a/lemon/cplex.h Tue Apr 07 14:50:20 2009 +0100 +++ b/lemon/cplex.h Wed Apr 08 22:49:28 2009 +0200 @@ -144,14 +144,29 @@ virtual void _clear(); + virtual void _messageLevel(MessageLevel level); + void _applyMessageLevel(); + + bool _message_enabled; + public: /// Returns the used \c CplexEnv instance const CplexEnv& env() const { return _env; } + + /// \brief Returns the const cpxenv pointer /// + /// \note The cpxenv might be destructed with the solver. const cpxenv* cplexEnv() const { return _env.cplexEnv(); } + /// \brief Returns the const cpxenv pointer + /// + /// \note The cpxenv might be destructed with the solver. + cpxenv* cplexEnv() { return _env.cplexEnv(); } + + /// Returns the cplex problem object cpxlp* cplexLp() { return _prob; } + /// Returns the cplex problem object const cpxlp* cplexLp() const { return _prob; } }; diff -r 37216ca5b9c6 -r 745e182d0139 lemon/glpk.cc --- a/lemon/glpk.cc Tue Apr 07 14:50:20 2009 +0100 +++ b/lemon/glpk.cc Wed Apr 08 22:49:28 2009 +0200 @@ -31,6 +31,7 @@ GlpkBase::GlpkBase() : LpBase() { lp = glp_create_prob(); glp_create_index(lp); + messageLevel(MESSAGE_NOTHING); } GlpkBase::GlpkBase(const GlpkBase &other) : LpBase() { @@ -39,6 +40,7 @@ glp_create_index(lp); rows = other.rows; cols = other.cols; + messageLevel(MESSAGE_NOTHING); } GlpkBase::~GlpkBase() { @@ -526,19 +528,37 @@ glp_free_env(); } + void GlpkBase::_messageLevel(MessageLevel level) { + switch (level) { + case MESSAGE_NOTHING: + _message_level = GLP_MSG_OFF; + break; + case MESSAGE_ERROR: + _message_level = GLP_MSG_ERR; + break; + case MESSAGE_WARNING: + _message_level = GLP_MSG_ERR; + break; + case MESSAGE_NORMAL: + _message_level = GLP_MSG_ON; + break; + case MESSAGE_VERBOSE: + _message_level = GLP_MSG_ALL; + break; + } + } + GlpkBase::FreeEnvHelper GlpkBase::freeEnvHelper; // GlpkLp members GlpkLp::GlpkLp() : LpBase(), LpSolver(), GlpkBase() { - messageLevel(MESSAGE_NO_OUTPUT); presolver(false); } GlpkLp::GlpkLp(const GlpkLp& other) : LpBase(other), LpSolver(other), GlpkBase(other) { - messageLevel(MESSAGE_NO_OUTPUT); presolver(false); } @@ -562,20 +582,7 @@ glp_smcp smcp; glp_init_smcp(&smcp); - switch (_message_level) { - case MESSAGE_NO_OUTPUT: - smcp.msg_lev = GLP_MSG_OFF; - break; - case MESSAGE_ERROR_MESSAGE: - smcp.msg_lev = GLP_MSG_ERR; - break; - case MESSAGE_NORMAL_OUTPUT: - smcp.msg_lev = GLP_MSG_ON; - break; - case MESSAGE_FULL_OUTPUT: - smcp.msg_lev = GLP_MSG_ALL; - break; - } + smcp.msg_lev = _message_level; smcp.presolve = _presolve; // If the basis is not valid we get an error return value. @@ -604,20 +611,7 @@ glp_smcp smcp; glp_init_smcp(&smcp); - switch (_message_level) { - case MESSAGE_NO_OUTPUT: - smcp.msg_lev = GLP_MSG_OFF; - break; - case MESSAGE_ERROR_MESSAGE: - smcp.msg_lev = GLP_MSG_ERR; - break; - case MESSAGE_NORMAL_OUTPUT: - smcp.msg_lev = GLP_MSG_ON; - break; - case MESSAGE_FULL_OUTPUT: - smcp.msg_lev = GLP_MSG_ALL; - break; - } + smcp.msg_lev = _message_level; smcp.meth = GLP_DUAL; smcp.presolve = _presolve; @@ -858,20 +852,14 @@ _presolve = presolve; } - void GlpkLp::messageLevel(MessageLevel m) { - _message_level = m; - } - // GlpkMip members GlpkMip::GlpkMip() : LpBase(), MipSolver(), GlpkBase() { - messageLevel(MESSAGE_NO_OUTPUT); } GlpkMip::GlpkMip(const GlpkMip& other) : LpBase(), MipSolver(), GlpkBase(other) { - messageLevel(MESSAGE_NO_OUTPUT); } void GlpkMip::_setColType(int i, GlpkMip::ColTypes col_type) { @@ -900,20 +888,7 @@ glp_smcp smcp; glp_init_smcp(&smcp); - switch (_message_level) { - case MESSAGE_NO_OUTPUT: - smcp.msg_lev = GLP_MSG_OFF; - break; - case MESSAGE_ERROR_MESSAGE: - smcp.msg_lev = GLP_MSG_ERR; - break; - case MESSAGE_NORMAL_OUTPUT: - smcp.msg_lev = GLP_MSG_ON; - break; - case MESSAGE_FULL_OUTPUT: - smcp.msg_lev = GLP_MSG_ALL; - break; - } + smcp.msg_lev = _message_level; smcp.meth = GLP_DUAL; // If the basis is not valid we get an error return value. @@ -938,20 +913,7 @@ glp_iocp iocp; glp_init_iocp(&iocp); - switch (_message_level) { - case MESSAGE_NO_OUTPUT: - iocp.msg_lev = GLP_MSG_OFF; - break; - case MESSAGE_ERROR_MESSAGE: - iocp.msg_lev = GLP_MSG_ERR; - break; - case MESSAGE_NORMAL_OUTPUT: - iocp.msg_lev = GLP_MSG_ON; - break; - case MESSAGE_FULL_OUTPUT: - iocp.msg_lev = GLP_MSG_ALL; - break; - } + iocp.msg_lev = _message_level; if (glp_intopt(lp, &iocp) != 0) return UNSOLVED; return SOLVED; @@ -1002,8 +964,4 @@ const char* GlpkMip::_solverName() const { return "GlpkMip"; } - void GlpkMip::messageLevel(MessageLevel m) { - _message_level = m; - } - } //END OF NAMESPACE LEMON diff -r 37216ca5b9c6 -r 745e182d0139 lemon/glpk.h --- a/lemon/glpk.h Tue Apr 07 14:50:20 2009 +0100 +++ b/lemon/glpk.h Wed Apr 08 22:49:28 2009 +0200 @@ -100,6 +100,8 @@ virtual void _clear(); + virtual void _messageLevel(MessageLevel level); + private: static void freeEnv(); @@ -111,6 +113,10 @@ }; static FreeEnvHelper freeEnvHelper; + + protected: + + int _message_level; public: @@ -191,30 +197,6 @@ ///The presolver is off by default. void presolver(bool presolve); - ///Enum for \c messageLevel() parameter - enum MessageLevel { - /// no output (default value) - MESSAGE_NO_OUTPUT = 0, - /// error messages only - MESSAGE_ERROR_MESSAGE = 1, - /// normal output - MESSAGE_NORMAL_OUTPUT = 2, - /// full output (includes informational messages) - MESSAGE_FULL_OUTPUT = 3 - }; - - private: - - MessageLevel _message_level; - - public: - - ///Set the verbosity of the messages - - ///Set the verbosity of the messages - /// - ///\param m is the level of the messages output by the solver routines. - void messageLevel(MessageLevel m); }; /// \brief Interface for the GLPK MIP solver @@ -244,30 +226,6 @@ virtual Value _getSol(int i) const; virtual Value _getSolValue() const; - ///Enum for \c messageLevel() parameter - enum MessageLevel { - /// no output (default value) - MESSAGE_NO_OUTPUT = 0, - /// error messages only - MESSAGE_ERROR_MESSAGE = 1, - /// normal output - MESSAGE_NORMAL_OUTPUT = 2, - /// full output (includes informational messages) - MESSAGE_FULL_OUTPUT = 3 - }; - - private: - - MessageLevel _message_level; - - public: - - ///Set the verbosity of the messages - - ///Set the verbosity of the messages - /// - ///\param m is the level of the messages output by the solver routines. - void messageLevel(MessageLevel m); }; diff -r 37216ca5b9c6 -r 745e182d0139 lemon/lp_base.h --- a/lemon/lp_base.h Tue Apr 07 14:50:20 2009 +0100 +++ b/lemon/lp_base.h Wed Apr 08 22:49:28 2009 +0200 @@ -69,6 +69,21 @@ MAX }; + ///Enum for \c messageLevel() parameter + enum MessageLevel { + /// no output (default value) + MESSAGE_NOTHING, + /// error messages only + MESSAGE_ERROR, + /// warnings + MESSAGE_WARNING, + /// normal output + MESSAGE_NORMAL, + /// verbose output + MESSAGE_VERBOSE + }; + + ///The floating point type used by the solver typedef double Value; ///The infinity constant @@ -973,6 +988,8 @@ virtual const char* _solverName() const = 0; + virtual void _messageLevel(MessageLevel level) = 0; + //Own protected stuff //Constant component of the objective function @@ -1527,6 +1544,9 @@ ///Clears the problem void clear() { _clear(); } + /// Sets the message level of the solver + void messageLevel(MessageLevel level) { _messageLevel(level); } + ///@} }; diff -r 37216ca5b9c6 -r 745e182d0139 lemon/lp_skeleton.cc --- a/lemon/lp_skeleton.cc Tue Apr 07 14:50:20 2009 +0100 +++ b/lemon/lp_skeleton.cc Wed Apr 08 22:49:28 2009 +0200 @@ -84,6 +84,8 @@ row_num = col_num = 0; } + void SkeletonSolverBase::_messageLevel(MessageLevel) {} + LpSkeleton::SolveExitStatus LpSkeleton::_solve() { return SOLVED; } LpSkeleton::Value LpSkeleton::_getPrimal(int) const { return 0; } diff -r 37216ca5b9c6 -r 745e182d0139 lemon/lp_skeleton.h --- a/lemon/lp_skeleton.h Tue Apr 07 14:50:20 2009 +0100 +++ b/lemon/lp_skeleton.h Wed Apr 08 22:49:28 2009 +0200 @@ -140,6 +140,8 @@ ///\e virtual void _clear(); + ///\e + virtual void _messageLevel(MessageLevel); }; /// \brief Skeleton class for an LP solver interface diff -r 37216ca5b9c6 -r 745e182d0139 lemon/soplex.cc --- a/lemon/soplex.cc Tue Apr 07 14:50:20 2009 +0100 +++ b/lemon/soplex.cc Wed Apr 08 22:49:28 2009 +0200 @@ -20,6 +20,7 @@ #include #include +#include ///\file @@ -28,6 +29,7 @@ SoplexLp::SoplexLp() { soplex = new soplex::SoPlex; + messageLevel(MESSAGE_NOTHING); } SoplexLp::~SoplexLp() { @@ -47,6 +49,7 @@ _row_names = lp._row_names; _row_names_ref = lp._row_names_ref; + messageLevel(MESSAGE_NOTHING); } void SoplexLp::_clear_temporals() { @@ -271,6 +274,8 @@ SoplexLp::SolveExitStatus SoplexLp::_solve() { _clear_temporals(); + + _applyMessageLevel(); soplex::SPxSolver::Status status = soplex->solve(); @@ -419,5 +424,29 @@ _clear_temporals(); } + void SoplexLp::_messageLevel(MessageLevel level) { + switch (level) { + case MESSAGE_NOTHING: + _message_level = -1; + break; + case MESSAGE_ERROR: + _message_level = soplex::SPxOut::ERROR; + break; + case MESSAGE_WARNING: + _message_level = soplex::SPxOut::WARNING; + break; + case MESSAGE_NORMAL: + _message_level = soplex::SPxOut::INFO2; + break; + case MESSAGE_VERBOSE: + _message_level = soplex::SPxOut::DEBUG; + break; + } + } + + void SoplexLp::_applyMessageLevel() { + soplex::Param::setVerbose(_message_level); + } + } //namespace lemon diff -r 37216ca5b9c6 -r 745e182d0139 lemon/soplex.h --- a/lemon/soplex.h Tue Apr 07 14:50:20 2009 +0100 +++ b/lemon/soplex.h Wed Apr 08 22:49:28 2009 +0200 @@ -144,6 +144,11 @@ virtual void _clear(); + void _messageLevel(MessageLevel m); + void _applyMessageLevel(); + + int _message_level; + }; } //END OF NAMESPACE LEMON