1.1 --- a/configure.ac Tue Dec 02 21:40:33 2008 +0100
1.2 +++ b/configure.ac Tue Dec 02 22:48:28 2008 +0100
1.3 @@ -53,6 +53,7 @@
1.4 LX_CHECK_GLPK
1.5 LX_CHECK_CPLEX
1.6 LX_CHECK_SOPLEX
1.7 +LX_CHECK_CLP
1.8
1.9 AM_CONDITIONAL([HAVE_LP], [test x"$lx_lp_found" = x"yes"])
1.10 AM_CONDITIONAL([HAVE_MIP], [test x"$lx_mip_found" = x"yes"])
1.11 @@ -120,6 +121,7 @@
1.12 echo GLPK support.................. : $lx_glpk_found
1.13 echo CPLEX support................. : $lx_cplex_found
1.14 echo SOPLEX support................ : $lx_soplex_found
1.15 +echo CLP support................... : $lx_clp_found
1.16 echo
1.17 echo Build demo programs........... : $enable_demo
1.18 echo Build additional tools........ : $enable_tools
2.1 --- a/lemon/CMakeLists.txt Tue Dec 02 21:40:33 2008 +0100
2.2 +++ b/lemon/CMakeLists.txt Tue Dec 02 22:48:28 2008 +0100
2.3 @@ -4,9 +4,6 @@
2.4 arg_parser.cc
2.5 base.cc
2.6 color.cc
2.7 - lp_base.cc
2.8 - lp_skeleton.cc
2.9 - lp_utils.cc
2.10 random.cc)
2.11
2.12 INSTALL(
3.1 --- a/lemon/Makefile.am Tue Dec 02 21:40:33 2008 +0100
3.2 +++ b/lemon/Makefile.am Tue Dec 02 22:48:28 2008 +0100
3.3 @@ -18,25 +18,31 @@
3.4 lemon_libemon_la_CXXFLAGS = \
3.5 $(GLPK_CFLAGS) \
3.6 $(CPLEX_CFLAGS) \
3.7 - $(SOPLEX_CXXFLAGS)
3.8 + $(SOPLEX_CXXFLAGS) \
3.9 + $(CLP_CXXFLAGS)
3.10
3.11 lemon_libemon_la_LDFLAGS = \
3.12 $(GLPK_LIBS) \
3.13 $(CPLEX_LIBS) \
3.14 - $(SOPLEX_LIBS)
3.15 + $(SOPLEX_LIBS) \
3.16 + $(CLP_LIBS)
3.17
3.18 if HAVE_GLPK
3.19 -lemon_libemon_la_SOURCES += lemon/lp_glpk.cc lemon/mip_glpk.cc
3.20 +lemon_libemon_la_SOURCES += lemon/lp_glpk.cc
3.21 endif
3.22
3.23 if HAVE_CPLEX
3.24 -lemon_libemon_la_SOURCES += lemon/lp_cplex.cc lemon/mip_cplex.cc
3.25 +lemon_libemon_la_SOURCES += lemon/lp_cplex.cc
3.26 endif
3.27
3.28 if HAVE_SOPLEX
3.29 lemon_libemon_la_SOURCES += lemon/lp_soplex.cc
3.30 endif
3.31
3.32 +if HAVE_CLP
3.33 +lemon_libemon_la_SOURCES += lemon/lp_clp.cc
3.34 +endif
3.35 +
3.36 lemon_HEADERS += \
3.37 lemon/adaptors.h \
3.38 lemon/arg_parser.h \
3.39 @@ -65,12 +71,12 @@
3.40 lemon/list_graph.h \
3.41 lemon/lp.h \
3.42 lemon/lp_base.h \
3.43 + lemon/lp_clp.h \
3.44 lemon/lp_cplex.h \
3.45 lemon/lp_glpk.h \
3.46 lemon/lp_skeleton.h \
3.47 lemon/lp_soplex.h \
3.48 - lemon/mip_cplex.h \
3.49 - lemon/mip_glpk.h \
3.50 + lemon/list_graph.h \
3.51 lemon/maps.h \
3.52 lemon/math.h \
3.53 lemon/max_matching.h \
3.54 @@ -94,9 +100,9 @@
3.55 lemon/bits/enable_if.h \
3.56 lemon/bits/graph_adaptor_extender.h \
3.57 lemon/bits/graph_extender.h \
3.58 - lemon/bits/lp_id.h \
3.59 lemon/bits/map_extender.h \
3.60 lemon/bits/path_dump.h \
3.61 + lemon/bits/solver_bits.h \
3.62 lemon/bits/traits.h \
3.63 lemon/bits/variant.h \
3.64 lemon/bits/vector_map.h
4.1 --- a/lemon/bits/lp_id.h Tue Dec 02 21:40:33 2008 +0100
4.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
4.3 @@ -1,157 +0,0 @@
4.4 -/* -*- mode: C++; indent-tabs-mode: nil; -*-
4.5 - *
4.6 - * This file is a part of LEMON, a generic C++ optimization library.
4.7 - *
4.8 - * Copyright (C) 2003-2008
4.9 - * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
4.10 - * (Egervary Research Group on Combinatorial Optimization, EGRES).
4.11 - *
4.12 - * Permission to use, modify and distribute this software is granted
4.13 - * provided that this copyright notice appears in all copies. For
4.14 - * precise terms see the accompanying LICENSE file.
4.15 - *
4.16 - * This software is provided "AS IS" with no warranty of any kind,
4.17 - * express or implied, and with no claim as to its suitability for any
4.18 - * purpose.
4.19 - *
4.20 - */
4.21 -
4.22 -#ifndef LEMON_BITS_LP_SOLVER_ID_H
4.23 -#define LEMON_BITS_LP_SOLVER_ID_H
4.24 -
4.25 -namespace lemon {
4.26 -
4.27 - namespace _lp_bits {
4.28 -
4.29 - struct LpIdImpl {
4.30 - std::vector<int> index;
4.31 - std::vector<int> cross;
4.32 - int first_index;
4.33 - int first_free;
4.34 - };
4.35 -
4.36 - class LpId {
4.37 - public:
4.38 -
4.39 - class IdHandler {
4.40 - public:
4.41 - virtual ~IdHandler() {}
4.42 - virtual int addId(LpIdImpl&) = 0;
4.43 - virtual void eraseId(LpIdImpl&, int xn) = 0;
4.44 - };
4.45 -
4.46 - LpId(int min_index = 0) {
4.47 - id_handler = 0;
4.48 - impl.first_free = -1;
4.49 - impl.first_index = min_index;
4.50 - impl.cross.resize(impl.first_index);
4.51 - }
4.52 -
4.53 - LpId(const LpId& li) {
4.54 - id_handler = 0;
4.55 - impl = li.impl;
4.56 - }
4.57 -
4.58 - LpId& operator=(const LpId& li) {
4.59 - id_handler = 0;
4.60 - impl = li.impl;
4.61 - return *this;
4.62 - }
4.63 -
4.64 - void setIdHandler(IdHandler& ih) {
4.65 - id_handler = &ih;
4.66 - }
4.67 -
4.68 - int fixId(int fn) const {return impl.cross[fn];}
4.69 - int floatingId(int xn) const {return impl.index[xn];}
4.70 -
4.71 - int addId() {
4.72 - if (id_handler == 0) {
4.73 - int xn, fn = impl.cross.size();
4.74 - if (impl.first_free == -1) {
4.75 - xn = impl.index.size();
4.76 - impl.index.push_back(fn);
4.77 - } else {
4.78 - xn = impl.first_free;
4.79 - impl.first_free = impl.index[impl.first_free];
4.80 - impl.index[xn] = fn;
4.81 - }
4.82 - impl.cross.push_back(xn);
4.83 - return xn;
4.84 - } else {
4.85 - return id_handler->addId(impl);
4.86 - }
4.87 - }
4.88 -
4.89 - void eraseId(int xn) {
4.90 - if (id_handler == 0) {
4.91 - int fn = impl.index[xn];
4.92 - impl.index[xn] = impl.first_free;
4.93 - impl.first_free = xn;
4.94 - for(int i = fn + 1; i < int(impl.cross.size()); ++i) {
4.95 - impl.cross[i - 1] = impl.cross[i];
4.96 - impl.index[impl.cross[i]]--;
4.97 - }
4.98 - impl.cross.pop_back();
4.99 - } else {
4.100 - id_handler->eraseId(impl, xn);
4.101 - }
4.102 - }
4.103 -
4.104 - void firstFloating(int& fn) const {
4.105 - fn = impl.first_index;
4.106 - if (fn == int(impl.cross.size())) fn = -1;
4.107 - }
4.108 -
4.109 - void nextFloating(int& fn) const {
4.110 - ++fn;
4.111 - if (fn == int(impl.cross.size())) fn = -1;
4.112 - }
4.113 -
4.114 - void firstFix(int& xn) const {
4.115 - int fn;
4.116 - firstFloating(fn);
4.117 - xn = fn != -1 ? fixId(fn) : -1;
4.118 - }
4.119 -
4.120 - void nextFix(int& xn) const {
4.121 - int fn = floatingId(xn);
4.122 - nextFloating(fn);
4.123 - xn = fn != -1 ? fixId(fn) : -1;
4.124 - }
4.125 -
4.126 - protected:
4.127 - LpIdImpl impl;
4.128 - IdHandler *id_handler;
4.129 - };
4.130 -
4.131 - class RelocateIdHandler : public LpId::IdHandler {
4.132 - public:
4.133 -
4.134 - virtual int addId(LpIdImpl& impl) {
4.135 - int xn, fn = impl.cross.size();
4.136 - if (impl.first_free == -1) {
4.137 - xn = impl.index.size();
4.138 - impl.index.push_back(fn);
4.139 - } else {
4.140 - xn = impl.first_free;
4.141 - impl.first_free = impl.index[impl.first_free];
4.142 - impl.index[xn] = fn;
4.143 - }
4.144 - impl.cross.push_back(xn);
4.145 - return xn;
4.146 - }
4.147 -
4.148 - virtual void eraseId(LpIdImpl& impl, int xn) {
4.149 - int fn = impl.index[xn];
4.150 - impl.index[xn] = impl.first_free;
4.151 - impl.first_free = xn;
4.152 - impl.cross[fn] = impl.cross.back();
4.153 - impl.index[impl.cross.back()] = fn;
4.154 - impl.cross.pop_back();
4.155 - }
4.156 - };
4.157 - }
4.158 -}
4.159 -
4.160 -#endif
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/lemon/bits/solver_bits.h Tue Dec 02 22:48:28 2008 +0100
5.3 @@ -0,0 +1,191 @@
5.4 +/* -*- mode: C++; indent-tabs-mode: nil; -*-
5.5 + *
5.6 + * This file is a part of LEMON, a generic C++ optimization library.
5.7 + *
5.8 + * Copyright (C) 2003-2008
5.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
5.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
5.11 + *
5.12 + * Permission to use, modify and distribute this software is granted
5.13 + * provided that this copyright notice appears in all copies. For
5.14 + * precise terms see the accompanying LICENSE file.
5.15 + *
5.16 + * This software is provided "AS IS" with no warranty of any kind,
5.17 + * express or implied, and with no claim as to its suitability for any
5.18 + * purpose.
5.19 + *
5.20 + */
5.21 +
5.22 +#ifndef LEMON_BITS_SOLVER_BITS_H
5.23 +#define LEMON_BITS_SOLVER_BITS_H
5.24 +
5.25 +namespace lemon {
5.26 +
5.27 + namespace _solver_bits {
5.28 +
5.29 + class VarIndex {
5.30 + private:
5.31 + struct ItemT {
5.32 + int prev, next;
5.33 + int index;
5.34 + };
5.35 + std::vector<ItemT> items;
5.36 + int first_item, last_item, first_free_item;
5.37 +
5.38 + std::vector<int> cross;
5.39 +
5.40 + public:
5.41 +
5.42 + VarIndex()
5.43 + : first_item(-1), last_item(-1), first_free_item(-1) {
5.44 + }
5.45 +
5.46 + void clear() {
5.47 + first_item = -1;
5.48 + first_free_item = -1;
5.49 + items.clear();
5.50 + cross.clear();
5.51 + }
5.52 +
5.53 + int addIndex(int idx) {
5.54 + int n;
5.55 + if (first_free_item == -1) {
5.56 + n = items.size();
5.57 + items.push_back(ItemT());
5.58 + } else {
5.59 + n = first_free_item;
5.60 + first_free_item = items[n].next;
5.61 + if (first_free_item != -1) {
5.62 + items[first_free_item].prev = -1;
5.63 + }
5.64 + }
5.65 + items[n].index = idx;
5.66 + if (static_cast<int>(cross.size()) <= idx) {
5.67 + cross.resize(idx + 1, -1);
5.68 + }
5.69 + cross[idx] = n;
5.70 +
5.71 + items[n].prev = last_item;
5.72 + items[n].next = -1;
5.73 + if (last_item != -1) {
5.74 + items[last_item].next = n;
5.75 + } else {
5.76 + first_item = n;
5.77 + }
5.78 + last_item = n;
5.79 +
5.80 + return n;
5.81 + }
5.82 +
5.83 + int addIndex(int idx, int n) {
5.84 + while (n >= static_cast<int>(items.size())) {
5.85 + items.push_back(ItemT());
5.86 + items.back().prev = -1;
5.87 + items.back().next = first_free_item;
5.88 + if (first_free_item != -1) {
5.89 + items[first_free_item].prev = items.size() - 1;
5.90 + }
5.91 + first_free_item = items.size() - 1;
5.92 + }
5.93 + if (items[n].next != -1) {
5.94 + items[items[n].next].prev = items[n].prev;
5.95 + }
5.96 + if (items[n].prev != -1) {
5.97 + items[items[n].prev].next = items[n].next;
5.98 + } else {
5.99 + first_free_item = items[n].next;
5.100 + }
5.101 +
5.102 + items[n].index = idx;
5.103 + if (static_cast<int>(cross.size()) <= idx) {
5.104 + cross.resize(idx + 1, -1);
5.105 + }
5.106 + cross[idx] = n;
5.107 +
5.108 + items[n].prev = last_item;
5.109 + items[n].next = -1;
5.110 + if (last_item != -1) {
5.111 + items[last_item].next = n;
5.112 + } else {
5.113 + first_item = n;
5.114 + }
5.115 + last_item = n;
5.116 +
5.117 + return n;
5.118 + }
5.119 +
5.120 + void eraseIndex(int idx) {
5.121 + int n = cross[idx];
5.122 +
5.123 + if (items[n].prev != -1) {
5.124 + items[items[n].prev].next = items[n].next;
5.125 + } else {
5.126 + first_item = items[n].next;
5.127 + }
5.128 + if (items[n].next != -1) {
5.129 + items[items[n].next].prev = items[n].prev;
5.130 + } else {
5.131 + last_item = items[n].prev;
5.132 + }
5.133 +
5.134 + if (first_free_item != -1) {
5.135 + items[first_free_item].prev = n;
5.136 + }
5.137 + items[n].next = first_free_item;
5.138 + items[n].prev = -1;
5.139 + first_free_item = n;
5.140 +
5.141 + while (!cross.empty() && cross.back() == -1) {
5.142 + cross.pop_back();
5.143 + }
5.144 + }
5.145 +
5.146 + int maxIndex() const {
5.147 + return cross.size() - 1;
5.148 + }
5.149 +
5.150 + void shiftIndices(int idx) {
5.151 + for (int i = idx + 1; i < static_cast<int>(cross.size()); ++i) {
5.152 + cross[i - 1] = cross[i];
5.153 + if (cross[i] != -1) {
5.154 + --items[cross[i]].index;
5.155 + }
5.156 + }
5.157 + cross.back() = -1;
5.158 + cross.pop_back();
5.159 + while (!cross.empty() && cross.back() == -1) {
5.160 + cross.pop_back();
5.161 + }
5.162 + }
5.163 +
5.164 + void relocateIndex(int idx, int jdx) {
5.165 + cross[idx] = cross[jdx];
5.166 + items[cross[jdx]].index = idx;
5.167 + cross[jdx] = -1;
5.168 +
5.169 + while (!cross.empty() && cross.back() == -1) {
5.170 + cross.pop_back();
5.171 + }
5.172 + }
5.173 +
5.174 + int operator[](int idx) const {
5.175 + return cross[idx];
5.176 + }
5.177 +
5.178 + int operator()(int fdx) const {
5.179 + return items[fdx].index;
5.180 + }
5.181 +
5.182 + void firstItem(int& fdx) const {
5.183 + fdx = first_item;
5.184 + }
5.185 +
5.186 + void nextItem(int& fdx) const {
5.187 + fdx = items[fdx].next;
5.188 + }
5.189 +
5.190 + };
5.191 + }
5.192 +}
5.193 +
5.194 +#endif
6.1 --- a/lemon/config.h.in Tue Dec 02 21:40:33 2008 +0100
6.2 +++ b/lemon/config.h.in Tue Dec 02 22:48:28 2008 +0100
6.3 @@ -11,4 +11,7 @@
6.4 #undef HAVE_GLPK
6.5
6.6 /* Define to 1 if you have SOPLEX */
6.7 -#undef HAVE_SOPLEX
6.8 \ No newline at end of file
6.9 +#undef HAVE_SOPLEX
6.10 +
6.11 +/* Define to 1 if you have CLP */
6.12 +#undef HAVE_CLP
7.1 --- a/lemon/lp.h Tue Dec 02 21:40:33 2008 +0100
7.2 +++ b/lemon/lp.h Tue Dec 02 22:48:28 2008 +0100
7.3 @@ -24,12 +24,12 @@
7.4
7.5 #ifdef HAVE_GLPK
7.6 #include <lemon/lp_glpk.h>
7.7 -#include <lemon/mip_glpk.h>
7.8 #elif HAVE_CPLEX
7.9 #include <lemon/lp_cplex.h>
7.10 -#include <lemon/mip_cplex.h>
7.11 #elif HAVE_SOPLEX
7.12 #include <lemon/lp_soplex.h>
7.13 +#elif HAVE_CLP
7.14 +#include <lemon/lp_clp.h>
7.15 #endif
7.16
7.17 ///\file
7.18 @@ -43,45 +43,48 @@
7.19 ///The default LP solver identifier.
7.20 ///\ingroup lp_group
7.21 ///
7.22 - ///Currently, the possible values are \c GLPK or \c CPLEX
7.23 -#define DEFAULT_LP SOLVER
7.24 + ///Currently, the possible values are \c LP_GLPK, \c LP_CPLEX, \c
7.25 + ///LP_SOPLEX or \c LP_CLP
7.26 +#define LEMON_DEFAULT_LP SOLVER
7.27 ///The default LP solver
7.28
7.29 ///The default LP solver.
7.30 ///\ingroup lp_group
7.31 ///
7.32 - ///Currently, it is either \c LpGlpk or \c LpCplex
7.33 + ///Currently, it is either \c LpGlpk, \c LpCplex, \c LpSoplex or \c LpClp
7.34 typedef LpGlpk Lp;
7.35 - ///The default LP solver identifier string
7.36
7.37 - ///The default LP solver identifier string.
7.38 + ///The default MIP solver identifier
7.39 +
7.40 + ///The default MIP solver identifier.
7.41 ///\ingroup lp_group
7.42 ///
7.43 - ///Currently, the possible values are "GLPK" or "CPLEX"
7.44 - const char default_solver_name[]="SOLVER";
7.45 + ///Currently, the possible values are \c MIP_GLPK or \c MIP_CPLEX
7.46 +#define LEMON_DEFAULT_MIP SOLVER
7.47 + ///The default MIP solver.
7.48
7.49 - ///The default ILP solver.
7.50 -
7.51 - ///The default ILP solver.
7.52 + ///The default MIP solver.
7.53 ///\ingroup lp_group
7.54 ///
7.55 - ///Currently, it is either \c LpGlpk or \c LpCplex
7.56 + ///Currently, it is either \c MipGlpk or \c MipCplex
7.57 typedef MipGlpk Mip;
7.58 #else
7.59 #ifdef HAVE_GLPK
7.60 -#define DEFAULT_LP GLPK
7.61 +# define LEMON_DEFAULT_LP LP_GLPK
7.62 typedef LpGlpk Lp;
7.63 +# define LEMON_DEFAULT_MIP MIP_GLPK
7.64 typedef MipGlpk Mip;
7.65 - const char default_solver_name[]="GLPK";
7.66 #elif HAVE_CPLEX
7.67 -#define DEFAULT_LP CPLEX
7.68 +# define LEMON_DEFAULT_LP LP_CPLEX
7.69 typedef LpCplex Lp;
7.70 +# define LEMON_DEFAULT_MIP MIP_CPLEX
7.71 typedef MipCplex Mip;
7.72 - const char default_solver_name[]="CPLEX";
7.73 #elif HAVE_SOPLEX
7.74 -#define DEFAULT_LP SOPLEX
7.75 +# define DEFAULT_LP LP_SOPLEX
7.76 typedef LpSoplex Lp;
7.77 - const char default_solver_name[]="SOPLEX";
7.78 +#elif HAVE_CLP
7.79 +# define DEFAULT_LP LP_CLP
7.80 + typedef LpClp Lp;
7.81 #endif
7.82 #endif
7.83
8.1 --- a/lemon/lp_base.cc Tue Dec 02 21:40:33 2008 +0100
8.2 +++ b/lemon/lp_base.cc Tue Dec 02 22:48:28 2008 +0100
8.3 @@ -22,14 +22,7 @@
8.4 #include <lemon/lp_base.h>
8.5 namespace lemon {
8.6
8.7 - const LpSolverBase::Value
8.8 - LpSolverBase::INF = std::numeric_limits<Value>::infinity();
8.9 - const LpSolverBase::Value
8.10 - LpSolverBase::NaN = std::numeric_limits<Value>::quiet_NaN();
8.11 -
8.12 -// const LpSolverBase::Constr::Value
8.13 -// LpSolverBase::Constr::INF = std::numeric_limits<Value>::infinity();
8.14 -// const LpSolverBase::Constr::Value
8.15 -// LpSolverBase::Constr::NaN = std::numeric_limits<Value>::quiet_NaN();
8.16 + const LpBase::Value LpBase::INF = std::numeric_limits<Value>::infinity();
8.17 + const LpBase::Value LpBase::NaN = std::numeric_limits<Value>::quiet_NaN();
8.18
8.19 } //namespace lemon
9.1 --- a/lemon/lp_base.h Tue Dec 02 21:40:33 2008 +0100
9.2 +++ b/lemon/lp_base.h Tue Dec 02 22:48:28 2008 +0100
9.3 @@ -25,41 +25,28 @@
9.4 #include<limits>
9.5 #include<lemon/math.h>
9.6
9.7 +#include<lemon/error.h>
9.8 +#include<lemon/assert.h>
9.9 +
9.10 #include<lemon/core.h>
9.11 -#include<lemon/bits/lp_id.h>
9.12 +#include<lemon/bits/solver_bits.h>
9.13
9.14 ///\file
9.15 ///\brief The interface of the LP solver interface.
9.16 ///\ingroup lp_group
9.17 namespace lemon {
9.18
9.19 - /// Function to decide whether a floating point value is finite or not.
9.20 + ///Common base class for LP and MIP solvers
9.21
9.22 - /// Retruns true if the argument is not infinity, minus infinity or NaN.
9.23 - /// It does the same as the isfinite() function defined by C99.
9.24 - template <typename T>
9.25 - bool isFinite(T value)
9.26 - {
9.27 - typedef std::numeric_limits<T> Lim;
9.28 - if ((Lim::has_infinity && (value == Lim::infinity() || value ==
9.29 - -Lim::infinity())) ||
9.30 - ((Lim::has_quiet_NaN || Lim::has_signaling_NaN) && value != value))
9.31 - {
9.32 - return false;
9.33 - }
9.34 - return true;
9.35 - }
9.36 -
9.37 - ///Common base class for LP solvers
9.38 -
9.39 - ///\todo Much more docs
9.40 + ///Usually this class is not used directly, please use one of the concrete
9.41 + ///implementations of the solver interface.
9.42 ///\ingroup lp_group
9.43 - class LpSolverBase {
9.44 + class LpBase {
9.45
9.46 protected:
9.47
9.48 - _lp_bits::LpId rows;
9.49 - _lp_bits::LpId cols;
9.50 + _solver_bits::VarIndex rows;
9.51 + _solver_bits::VarIndex cols;
9.52
9.53 public:
9.54
9.55 @@ -74,38 +61,12 @@
9.56 UNSOLVED = 1
9.57 };
9.58
9.59 - ///\e
9.60 - enum SolutionStatus {
9.61 - ///Feasible solution hasn't been found (but may exist).
9.62 -
9.63 - ///\todo NOTFOUND might be a better name.
9.64 - ///
9.65 - UNDEFINED = 0,
9.66 - ///The problem has no feasible solution
9.67 - INFEASIBLE = 1,
9.68 - ///Feasible solution found
9.69 - FEASIBLE = 2,
9.70 - ///Optimal solution exists and found
9.71 - OPTIMAL = 3,
9.72 - ///The cost function is unbounded
9.73 -
9.74 - ///\todo Give a feasible solution and an infinite ray (and the
9.75 - ///corresponding bases)
9.76 - INFINITE = 4
9.77 - };
9.78 -
9.79 - ///\e The type of the investigated LP problem
9.80 - enum ProblemTypes {
9.81 - ///Primal-dual feasible
9.82 - PRIMAL_DUAL_FEASIBLE = 0,
9.83 - ///Primal feasible dual infeasible
9.84 - PRIMAL_FEASIBLE_DUAL_INFEASIBLE = 1,
9.85 - ///Primal infeasible dual feasible
9.86 - PRIMAL_INFEASIBLE_DUAL_FEASIBLE = 2,
9.87 - ///Primal-dual infeasible
9.88 - PRIMAL_DUAL_INFEASIBLE = 3,
9.89 - ///Could not determine so far
9.90 - UNKNOWN = 4
9.91 + ///Direction of the optimization
9.92 + enum Sense {
9.93 + /// Minimization
9.94 + MIN,
9.95 + /// Maximization
9.96 + MAX
9.97 };
9.98
9.99 ///The floating point type used by the solver
9.100 @@ -115,11 +76,10 @@
9.101 ///The not a number constant
9.102 static const Value NaN;
9.103
9.104 - static inline bool isNaN(const Value& v) { return v!=v; }
9.105 -
9.106 friend class Col;
9.107 friend class ColIt;
9.108 friend class Row;
9.109 + friend class RowIt;
9.110
9.111 ///Refer to a column of the LP.
9.112
9.113 @@ -128,43 +88,93 @@
9.114 ///Its value remains valid and correct even after the addition or erase of
9.115 ///other columns.
9.116 ///
9.117 - ///\todo Document what can one do with a Col (INVALID, comparing,
9.118 - ///it is similar to Node/Edge)
9.119 + ///\note This class is similar to other Item types in LEMON, like
9.120 + ///Node and Arc types in digraph.
9.121 class Col {
9.122 + friend class LpBase;
9.123 protected:
9.124 - int id;
9.125 - friend class LpSolverBase;
9.126 - friend class MipSolverBase;
9.127 - explicit Col(int _id) : id(_id) {}
9.128 + int _id;
9.129 + explicit Col(int id) : _id(id) {}
9.130 public:
9.131 typedef Value ExprValue;
9.132 - typedef True LpSolverCol;
9.133 + typedef True LpCol;
9.134 + /// Default constructor
9.135 +
9.136 + /// \warning The default constructor sets the Col to an
9.137 + /// undefined value.
9.138 Col() {}
9.139 - Col(const Invalid&) : id(-1) {}
9.140 - bool operator< (Col c) const {return id< c.id;}
9.141 - bool operator> (Col c) const {return id> c.id;}
9.142 - bool operator==(Col c) const {return id==c.id;}
9.143 - bool operator!=(Col c) const {return id!=c.id;}
9.144 + /// Invalid constructor \& conversion.
9.145 +
9.146 + /// This constructor initializes the Col to be invalid.
9.147 + /// \sa Invalid for more details.
9.148 + Col(const Invalid&) : _id(-1) {}
9.149 + /// Equality operator
9.150 +
9.151 + /// Two \ref Col "Col"s are equal if and only if they point to
9.152 + /// the same LP column or both are invalid.
9.153 + bool operator==(Col c) const {return _id == c._id;}
9.154 + /// Inequality operator
9.155 +
9.156 + /// \sa operator==(Col c)
9.157 + ///
9.158 + bool operator!=(Col c) const {return _id != c._id;}
9.159 + /// Artificial ordering operator.
9.160 +
9.161 + /// To allow the use of this object in std::map or similar
9.162 + /// associative container we require this.
9.163 + ///
9.164 + /// \note This operator only have to define some strict ordering of
9.165 + /// the items; this order has nothing to do with the iteration
9.166 + /// ordering of the items.
9.167 + bool operator<(Col c) const {return _id < c._id;}
9.168 };
9.169
9.170 + ///Iterator for iterate over the columns of an LP problem
9.171 +
9.172 + /// Its usage is quite simple, for example you can count the number
9.173 + /// of columns in an LP \c lp:
9.174 + ///\code
9.175 + /// int count=0;
9.176 + /// for (LpBase::ColIt c(lp); c!=INVALID; ++c) ++count;
9.177 + ///\endcode
9.178 class ColIt : public Col {
9.179 - const LpSolverBase *_lp;
9.180 + const LpBase *_solver;
9.181 public:
9.182 + /// Default constructor
9.183 +
9.184 + /// \warning The default constructor sets the iterator
9.185 + /// to an undefined value.
9.186 ColIt() {}
9.187 - ColIt(const LpSolverBase &lp) : _lp(&lp)
9.188 + /// Sets the iterator to the first Col
9.189 +
9.190 + /// Sets the iterator to the first Col.
9.191 + ///
9.192 + ColIt(const LpBase &solver) : _solver(&solver)
9.193 {
9.194 - _lp->cols.firstFix(id);
9.195 + _solver->cols.firstItem(_id);
9.196 }
9.197 + /// Invalid constructor \& conversion
9.198 +
9.199 + /// Initialize the iterator to be invalid.
9.200 + /// \sa Invalid for more details.
9.201 ColIt(const Invalid&) : Col(INVALID) {}
9.202 + /// Next column
9.203 +
9.204 + /// Assign the iterator to the next column.
9.205 + ///
9.206 ColIt &operator++()
9.207 {
9.208 - _lp->cols.nextFix(id);
9.209 + _solver->cols.nextItem(_id);
9.210 return *this;
9.211 }
9.212 };
9.213
9.214 - static int id(const Col& col) { return col.id; }
9.215 -
9.216 + /// \brief Returns the ID of the column.
9.217 + static int id(const Col& col) { return col._id; }
9.218 + /// \brief Returns the column with the given ID.
9.219 + ///
9.220 + /// \pre The argument should be a valid column ID in the LP problem.
9.221 + static Col colFromId(int id) { return Col(id); }
9.222
9.223 ///Refer to a row of the LP.
9.224
9.225 @@ -173,61 +183,93 @@
9.226 ///Its value remains valid and correct even after the addition or erase of
9.227 ///other rows.
9.228 ///
9.229 - ///\todo Document what can one do with a Row (INVALID, comparing,
9.230 - ///it is similar to Node/Edge)
9.231 + ///\note This class is similar to other Item types in LEMON, like
9.232 + ///Node and Arc types in digraph.
9.233 class Row {
9.234 + friend class LpBase;
9.235 protected:
9.236 - int id;
9.237 - friend class LpSolverBase;
9.238 - explicit Row(int _id) : id(_id) {}
9.239 + int _id;
9.240 + explicit Row(int id) : _id(id) {}
9.241 public:
9.242 typedef Value ExprValue;
9.243 - typedef True LpSolverRow;
9.244 + typedef True LpRow;
9.245 + /// Default constructor
9.246 +
9.247 + /// \warning The default constructor sets the Row to an
9.248 + /// undefined value.
9.249 Row() {}
9.250 - Row(const Invalid&) : id(-1) {}
9.251 + /// Invalid constructor \& conversion.
9.252 +
9.253 + /// This constructor initializes the Row to be invalid.
9.254 + /// \sa Invalid for more details.
9.255 + Row(const Invalid&) : _id(-1) {}
9.256 + /// Equality operator
9.257
9.258 - bool operator< (Row c) const {return id< c.id;}
9.259 - bool operator> (Row c) const {return id> c.id;}
9.260 - bool operator==(Row c) const {return id==c.id;}
9.261 - bool operator!=(Row c) const {return id!=c.id;}
9.262 + /// Two \ref Row "Row"s are equal if and only if they point to
9.263 + /// the same LP row or both are invalid.
9.264 + bool operator==(Row r) const {return _id == r._id;}
9.265 + /// Inequality operator
9.266 +
9.267 + /// \sa operator==(Row r)
9.268 + ///
9.269 + bool operator!=(Row r) const {return _id != r._id;}
9.270 + /// Artificial ordering operator.
9.271 +
9.272 + /// To allow the use of this object in std::map or similar
9.273 + /// associative container we require this.
9.274 + ///
9.275 + /// \note This operator only have to define some strict ordering of
9.276 + /// the items; this order has nothing to do with the iteration
9.277 + /// ordering of the items.
9.278 + bool operator<(Row r) const {return _id < r._id;}
9.279 };
9.280
9.281 + ///Iterator for iterate over the rows of an LP problem
9.282 +
9.283 + /// Its usage is quite simple, for example you can count the number
9.284 + /// of rows in an LP \c lp:
9.285 + ///\code
9.286 + /// int count=0;
9.287 + /// for (LpBase::RowIt c(lp); c!=INVALID; ++c) ++count;
9.288 + ///\endcode
9.289 class RowIt : public Row {
9.290 - const LpSolverBase *_lp;
9.291 + const LpBase *_solver;
9.292 public:
9.293 + /// Default constructor
9.294 +
9.295 + /// \warning The default constructor sets the iterator
9.296 + /// to an undefined value.
9.297 RowIt() {}
9.298 - RowIt(const LpSolverBase &lp) : _lp(&lp)
9.299 + /// Sets the iterator to the first Row
9.300 +
9.301 + /// Sets the iterator to the first Row.
9.302 + ///
9.303 + RowIt(const LpBase &solver) : _solver(&solver)
9.304 {
9.305 - _lp->rows.firstFix(id);
9.306 + _solver->rows.firstItem(_id);
9.307 }
9.308 + /// Invalid constructor \& conversion
9.309 +
9.310 + /// Initialize the iterator to be invalid.
9.311 + /// \sa Invalid for more details.
9.312 RowIt(const Invalid&) : Row(INVALID) {}
9.313 + /// Next row
9.314 +
9.315 + /// Assign the iterator to the next row.
9.316 + ///
9.317 RowIt &operator++()
9.318 {
9.319 - _lp->rows.nextFix(id);
9.320 + _solver->rows.nextItem(_id);
9.321 return *this;
9.322 }
9.323 };
9.324
9.325 - static int id(const Row& row) { return row.id; }
9.326 -
9.327 - protected:
9.328 -
9.329 - int _lpId(const Col& c) const {
9.330 - return cols.floatingId(id(c));
9.331 - }
9.332 -
9.333 - int _lpId(const Row& r) const {
9.334 - return rows.floatingId(id(r));
9.335 - }
9.336 -
9.337 - Col _item(int i, Col) const {
9.338 - return Col(cols.fixId(i));
9.339 - }
9.340 -
9.341 - Row _item(int i, Row) const {
9.342 - return Row(rows.fixId(i));
9.343 - }
9.344 -
9.345 + /// \brief Returns the ID of the row.
9.346 + static int id(const Row& row) { return row._id; }
9.347 + /// \brief Returns the row with the given ID.
9.348 + ///
9.349 + /// \pre The argument should be a valid row ID in the LP problem.
9.350 + static Row rowFromId(int id) { return Row(id); }
9.351
9.352 public:
9.353
9.354 @@ -238,10 +280,6 @@
9.355 ///
9.356 ///There are several ways to access and modify the contents of this
9.357 ///container.
9.358 - ///- Its it fully compatible with \c std::map<Col,double>, so for expamle
9.359 - ///if \c e is an Expr and \c v and \c w are of type \ref Col, then you can
9.360 - ///read and modify the coefficients like
9.361 - ///these.
9.362 ///\code
9.363 ///e[v]=5;
9.364 ///e[v]+=12;
9.365 @@ -250,10 +288,10 @@
9.366 ///or you can also iterate through its elements.
9.367 ///\code
9.368 ///double s=0;
9.369 - ///for(LpSolverBase::Expr::iterator i=e.begin();i!=e.end();++i)
9.370 - /// s+=i->second;
9.371 + ///for(LpBase::Expr::ConstCoeffIt i(e);i!=INVALID;++i)
9.372 + /// s+=*i * primal(i);
9.373 ///\endcode
9.374 - ///(This code computes the sum of all coefficients).
9.375 + ///(This code computes the primal value of the expression).
9.376 ///- Numbers (<tt>double</tt>'s)
9.377 ///and variables (\ref Col "Col"s) directly convert to an
9.378 ///\ref Expr and the usual linear operations are defined, so
9.379 @@ -262,7 +300,7 @@
9.380 ///2*v-3.12*(v-w/2)+2
9.381 ///v*2.1+(3*v+(v*12+w+6)*3)/2
9.382 ///\endcode
9.383 - ///are valid \ref Expr "Expr"essions.
9.384 + ///are valid expressions.
9.385 ///The usual assignment operations are also defined.
9.386 ///\code
9.387 ///e=v+w;
9.388 @@ -270,105 +308,218 @@
9.389 ///e*=3.4;
9.390 ///e/=5;
9.391 ///\endcode
9.392 - ///- The constant member can be set and read by \ref constComp()
9.393 + ///- The constant member can be set and read by dereference
9.394 + /// operator (unary *)
9.395 + ///
9.396 ///\code
9.397 - ///e.constComp()=12;
9.398 - ///double c=e.constComp();
9.399 + ///*e=12;
9.400 + ///double c=*e;
9.401 ///\endcode
9.402 ///
9.403 - ///\note \ref clear() not only sets all coefficients to 0 but also
9.404 - ///clears the constant components.
9.405 - ///
9.406 ///\sa Constr
9.407 - ///
9.408 - class Expr : public std::map<Col,Value>
9.409 - {
9.410 + class Expr {
9.411 + friend class LpBase;
9.412 public:
9.413 - typedef LpSolverBase::Col Key;
9.414 - typedef LpSolverBase::Value Value;
9.415 + /// The key type of the expression
9.416 + typedef LpBase::Col Key;
9.417 + /// The value type of the expression
9.418 + typedef LpBase::Value Value;
9.419
9.420 protected:
9.421 - typedef std::map<Col,Value> Base;
9.422 + Value const_comp;
9.423 + std::map<int, Value> comps;
9.424
9.425 - Value const_comp;
9.426 public:
9.427 - typedef True IsLinExpression;
9.428 - ///\e
9.429 - Expr() : Base(), const_comp(0) { }
9.430 - ///\e
9.431 - Expr(const Key &v) : const_comp(0) {
9.432 - Base::insert(std::make_pair(v, 1));
9.433 + typedef True SolverExpr;
9.434 + /// Default constructor
9.435 +
9.436 + /// Construct an empty expression, the coefficients and
9.437 + /// the constant component are initialized to zero.
9.438 + Expr() : const_comp(0) {}
9.439 + /// Construct an expression from a column
9.440 +
9.441 + /// Construct an expression, which has a term with \c c variable
9.442 + /// and 1.0 coefficient.
9.443 + Expr(const Col &c) : const_comp(0) {
9.444 + typedef std::map<int, Value>::value_type pair_type;
9.445 + comps.insert(pair_type(id(c), 1));
9.446 }
9.447 - ///\e
9.448 + /// Construct an expression from a constant
9.449 +
9.450 + /// Construct an expression, which's constant component is \c v.
9.451 + ///
9.452 Expr(const Value &v) : const_comp(v) {}
9.453 - ///\e
9.454 - void set(const Key &v,const Value &c) {
9.455 - Base::insert(std::make_pair(v, c));
9.456 - }
9.457 - ///\e
9.458 - Value &constComp() { return const_comp; }
9.459 - ///\e
9.460 - const Value &constComp() const { return const_comp; }
9.461 -
9.462 - ///Removes the components with zero coefficient.
9.463 - void simplify() {
9.464 - for (Base::iterator i=Base::begin(); i!=Base::end();) {
9.465 - Base::iterator j=i;
9.466 - ++j;
9.467 - if ((*i).second==0) Base::erase(i);
9.468 - i=j;
9.469 + /// Returns the coefficient of the column
9.470 + Value operator[](const Col& c) const {
9.471 + std::map<int, Value>::const_iterator it=comps.find(id(c));
9.472 + if (it != comps.end()) {
9.473 + return it->second;
9.474 + } else {
9.475 + return 0;
9.476 }
9.477 }
9.478 -
9.479 - void simplify() const {
9.480 - const_cast<Expr*>(this)->simplify();
9.481 + /// Returns the coefficient of the column
9.482 + Value& operator[](const Col& c) {
9.483 + return comps[id(c)];
9.484 + }
9.485 + /// Sets the coefficient of the column
9.486 + void set(const Col &c, const Value &v) {
9.487 + if (v != 0.0) {
9.488 + typedef std::map<int, Value>::value_type pair_type;
9.489 + comps.insert(pair_type(id(c), v));
9.490 + } else {
9.491 + comps.erase(id(c));
9.492 + }
9.493 + }
9.494 + /// Returns the constant component of the expression
9.495 + Value& operator*() { return const_comp; }
9.496 + /// Returns the constant component of the expression
9.497 + const Value& operator*() const { return const_comp; }
9.498 + /// \brief Removes the coefficients which's absolute value does
9.499 + /// not exceed \c epsilon. It also sets to zero the constant
9.500 + /// component, if it does not exceed epsilon in absolute value.
9.501 + void simplify(Value epsilon = 0.0) {
9.502 + std::map<int, Value>::iterator it=comps.begin();
9.503 + while (it != comps.end()) {
9.504 + std::map<int, Value>::iterator jt=it;
9.505 + ++jt;
9.506 + if (std::fabs((*it).second) <= epsilon) comps.erase(it);
9.507 + it=jt;
9.508 + }
9.509 + if (std::fabs(const_comp) <= epsilon) const_comp = 0;
9.510 }
9.511
9.512 - ///Removes the coefficients closer to zero than \c tolerance.
9.513 - void simplify(double &tolerance) {
9.514 - for (Base::iterator i=Base::begin(); i!=Base::end();) {
9.515 - Base::iterator j=i;
9.516 - ++j;
9.517 - if (std::fabs((*i).second)<tolerance) Base::erase(i);
9.518 - i=j;
9.519 - }
9.520 + void simplify(Value epsilon = 0.0) const {
9.521 + const_cast<Expr*>(this)->simplify(epsilon);
9.522 }
9.523
9.524 ///Sets all coefficients and the constant component to 0.
9.525 void clear() {
9.526 - Base::clear();
9.527 + comps.clear();
9.528 const_comp=0;
9.529 }
9.530
9.531 - ///\e
9.532 + ///Compound assignment
9.533 Expr &operator+=(const Expr &e) {
9.534 - for (Base::const_iterator j=e.begin(); j!=e.end(); ++j)
9.535 - (*this)[j->first]+=j->second;
9.536 + for (std::map<int, Value>::const_iterator it=e.comps.begin();
9.537 + it!=e.comps.end(); ++it)
9.538 + comps[it->first]+=it->second;
9.539 const_comp+=e.const_comp;
9.540 return *this;
9.541 }
9.542 - ///\e
9.543 + ///Compound assignment
9.544 Expr &operator-=(const Expr &e) {
9.545 - for (Base::const_iterator j=e.begin(); j!=e.end(); ++j)
9.546 - (*this)[j->first]-=j->second;
9.547 + for (std::map<int, Value>::const_iterator it=e.comps.begin();
9.548 + it!=e.comps.end(); ++it)
9.549 + comps[it->first]-=it->second;
9.550 const_comp-=e.const_comp;
9.551 return *this;
9.552 }
9.553 - ///\e
9.554 - Expr &operator*=(const Value &c) {
9.555 - for (Base::iterator j=Base::begin(); j!=Base::end(); ++j)
9.556 - j->second*=c;
9.557 - const_comp*=c;
9.558 + ///Multiply with a constant
9.559 + Expr &operator*=(const Value &v) {
9.560 + for (std::map<int, Value>::iterator it=comps.begin();
9.561 + it!=comps.end(); ++it)
9.562 + it->second*=v;
9.563 + const_comp*=v;
9.564 return *this;
9.565 }
9.566 - ///\e
9.567 + ///Division with a constant
9.568 Expr &operator/=(const Value &c) {
9.569 - for (Base::iterator j=Base::begin(); j!=Base::end(); ++j)
9.570 - j->second/=c;
9.571 + for (std::map<int, Value>::iterator it=comps.begin();
9.572 + it!=comps.end(); ++it)
9.573 + it->second/=c;
9.574 const_comp/=c;
9.575 return *this;
9.576 }
9.577
9.578 + ///Iterator over the expression
9.579 +
9.580 + ///The iterator iterates over the terms of the expression.
9.581 + ///
9.582 + ///\code
9.583 + ///double s=0;
9.584 + ///for(LpBase::Expr::CoeffIt i(e);i!=INVALID;++i)
9.585 + /// s+= *i * primal(i);
9.586 + ///\endcode
9.587 + class CoeffIt {
9.588 + private:
9.589 +
9.590 + std::map<int, Value>::iterator _it, _end;
9.591 +
9.592 + public:
9.593 +
9.594 + /// Sets the iterator to the first term
9.595 +
9.596 + /// Sets the iterator to the first term of the expression.
9.597 + ///
9.598 + CoeffIt(Expr& e)
9.599 + : _it(e.comps.begin()), _end(e.comps.end()){}
9.600 +
9.601 + /// Convert the iterator to the column of the term
9.602 + operator Col() const {
9.603 + return colFromId(_it->first);
9.604 + }
9.605 +
9.606 + /// Returns the coefficient of the term
9.607 + Value& operator*() { return _it->second; }
9.608 +
9.609 + /// Returns the coefficient of the term
9.610 + const Value& operator*() const { return _it->second; }
9.611 + /// Next term
9.612 +
9.613 + /// Assign the iterator to the next term.
9.614 + ///
9.615 + CoeffIt& operator++() { ++_it; return *this; }
9.616 +
9.617 + /// Equality operator
9.618 + bool operator==(Invalid) const { return _it == _end; }
9.619 + /// Inequality operator
9.620 + bool operator!=(Invalid) const { return _it != _end; }
9.621 + };
9.622 +
9.623 + /// Const iterator over the expression
9.624 +
9.625 + ///The iterator iterates over the terms of the expression.
9.626 + ///
9.627 + ///\code
9.628 + ///double s=0;
9.629 + ///for(LpBase::Expr::ConstCoeffIt i(e);i!=INVALID;++i)
9.630 + /// s+=*i * primal(i);
9.631 + ///\endcode
9.632 + class ConstCoeffIt {
9.633 + private:
9.634 +
9.635 + std::map<int, Value>::const_iterator _it, _end;
9.636 +
9.637 + public:
9.638 +
9.639 + /// Sets the iterator to the first term
9.640 +
9.641 + /// Sets the iterator to the first term of the expression.
9.642 + ///
9.643 + ConstCoeffIt(const Expr& e)
9.644 + : _it(e.comps.begin()), _end(e.comps.end()){}
9.645 +
9.646 + /// Convert the iterator to the column of the term
9.647 + operator Col() const {
9.648 + return colFromId(_it->first);
9.649 + }
9.650 +
9.651 + /// Returns the coefficient of the term
9.652 + const Value& operator*() const { return _it->second; }
9.653 +
9.654 + /// Next term
9.655 +
9.656 + /// Assign the iterator to the next term.
9.657 + ///
9.658 + ConstCoeffIt& operator++() { ++_it; return *this; }
9.659 +
9.660 + /// Equality operator
9.661 + bool operator==(Invalid) const { return _it == _end; }
9.662 + /// Inequality operator
9.663 + bool operator!=(Invalid) const { return _it != _end; }
9.664 + };
9.665 +
9.666 };
9.667
9.668 ///Linear constraint
9.669 @@ -394,13 +545,13 @@
9.670 /// s<=e<=t
9.671 /// e>=t
9.672 ///\endcode
9.673 - ///\warning The validity of a constraint is checked only at run time, so
9.674 - ///e.g. \ref addRow(<tt>x[1]\<=x[2]<=5</tt>) will compile, but will throw
9.675 - ///an assertion.
9.676 + ///\warning The validity of a constraint is checked only at run
9.677 + ///time, so e.g. \ref addRow(<tt>x[1]\<=x[2]<=5</tt>) will
9.678 + ///compile, but will fail an assertion.
9.679 class Constr
9.680 {
9.681 public:
9.682 - typedef LpSolverBase::Expr Expr;
9.683 + typedef LpBase::Expr Expr;
9.684 typedef Expr::Key Key;
9.685 typedef Expr::Value Value;
9.686
9.687 @@ -411,15 +562,8 @@
9.688 ///\e
9.689 Constr() : _expr(), _lb(NaN), _ub(NaN) {}
9.690 ///\e
9.691 - Constr(Value lb,const Expr &e,Value ub) :
9.692 + Constr(Value lb, const Expr &e, Value ub) :
9.693 _expr(e), _lb(lb), _ub(ub) {}
9.694 - ///\e
9.695 - Constr(const Expr &e,Value ub) :
9.696 - _expr(e), _lb(NaN), _ub(ub) {}
9.697 - ///\e
9.698 - Constr(Value lb,const Expr &e) :
9.699 - _expr(e), _lb(lb), _ub(NaN) {}
9.700 - ///\e
9.701 Constr(const Expr &e) :
9.702 _expr(e), _lb(NaN), _ub(NaN) {}
9.703 ///\e
9.704 @@ -453,11 +597,11 @@
9.705 const Value &upperBound() const { return _ub; }
9.706 ///Is the constraint lower bounded?
9.707 bool lowerBounded() const {
9.708 - return isFinite(_lb);
9.709 + return _lb != -INF && !std::isnan(_lb);
9.710 }
9.711 ///Is the constraint upper bounded?
9.712 bool upperBounded() const {
9.713 - return isFinite(_ub);
9.714 + return _ub != INF && !std::isnan(_ub);
9.715 }
9.716
9.717 };
9.718 @@ -470,11 +614,6 @@
9.719 ///
9.720 ///There are several ways to access and modify the contents of this
9.721 ///container.
9.722 - ///- Its it fully compatible with \c std::map<Row,double>, so for expamle
9.723 - ///if \c e is an DualExpr and \c v
9.724 - ///and \c w are of type \ref Row, then you can
9.725 - ///read and modify the coefficients like
9.726 - ///these.
9.727 ///\code
9.728 ///e[v]=5;
9.729 ///e[v]+=12;
9.730 @@ -483,8 +622,8 @@
9.731 ///or you can also iterate through its elements.
9.732 ///\code
9.733 ///double s=0;
9.734 - ///for(LpSolverBase::DualExpr::iterator i=e.begin();i!=e.end();++i)
9.735 - /// s+=i->second;
9.736 + ///for(LpBase::DualExpr::ConstCoeffIt i(e);i!=INVALID;++i)
9.737 + /// s+=*i;
9.738 ///\endcode
9.739 ///(This code computes the sum of all coefficients).
9.740 ///- Numbers (<tt>double</tt>'s)
9.741 @@ -495,7 +634,7 @@
9.742 ///2*v-3.12*(v-w/2)
9.743 ///v*2.1+(3*v+(v*12+w)*3)/2
9.744 ///\endcode
9.745 - ///are valid \ref DualExpr "DualExpr"essions.
9.746 + ///are valid \ref DualExpr dual expressions.
9.747 ///The usual assignment operations are also defined.
9.748 ///\code
9.749 ///e=v+w;
9.750 @@ -505,146 +644,237 @@
9.751 ///\endcode
9.752 ///
9.753 ///\sa Expr
9.754 - ///
9.755 - class DualExpr : public std::map<Row,Value>
9.756 - {
9.757 + class DualExpr {
9.758 + friend class LpBase;
9.759 public:
9.760 - typedef LpSolverBase::Row Key;
9.761 - typedef LpSolverBase::Value Value;
9.762 + /// The key type of the expression
9.763 + typedef LpBase::Row Key;
9.764 + /// The value type of the expression
9.765 + typedef LpBase::Value Value;
9.766
9.767 protected:
9.768 - typedef std::map<Row,Value> Base;
9.769 + std::map<int, Value> comps;
9.770
9.771 public:
9.772 - typedef True IsLinExpression;
9.773 - ///\e
9.774 - DualExpr() : Base() { }
9.775 - ///\e
9.776 - DualExpr(const Key &v) {
9.777 - Base::insert(std::make_pair(v, 1));
9.778 + typedef True SolverExpr;
9.779 + /// Default constructor
9.780 +
9.781 + /// Construct an empty expression, the coefficients are
9.782 + /// initialized to zero.
9.783 + DualExpr() {}
9.784 + /// Construct an expression from a row
9.785 +
9.786 + /// Construct an expression, which has a term with \c r dual
9.787 + /// variable and 1.0 coefficient.
9.788 + DualExpr(const Row &r) {
9.789 + typedef std::map<int, Value>::value_type pair_type;
9.790 + comps.insert(pair_type(id(r), 1));
9.791 }
9.792 - ///\e
9.793 - void set(const Key &v,const Value &c) {
9.794 - Base::insert(std::make_pair(v, c));
9.795 + /// Returns the coefficient of the row
9.796 + Value operator[](const Row& r) const {
9.797 + std::map<int, Value>::const_iterator it = comps.find(id(r));
9.798 + if (it != comps.end()) {
9.799 + return it->second;
9.800 + } else {
9.801 + return 0;
9.802 + }
9.803 }
9.804 -
9.805 - ///Removes the components with zero coefficient.
9.806 - void simplify() {
9.807 - for (Base::iterator i=Base::begin(); i!=Base::end();) {
9.808 - Base::iterator j=i;
9.809 - ++j;
9.810 - if ((*i).second==0) Base::erase(i);
9.811 - i=j;
9.812 + /// Returns the coefficient of the row
9.813 + Value& operator[](const Row& r) {
9.814 + return comps[id(r)];
9.815 + }
9.816 + /// Sets the coefficient of the row
9.817 + void set(const Row &r, const Value &v) {
9.818 + if (v != 0.0) {
9.819 + typedef std::map<int, Value>::value_type pair_type;
9.820 + comps.insert(pair_type(id(r), v));
9.821 + } else {
9.822 + comps.erase(id(r));
9.823 + }
9.824 + }
9.825 + /// \brief Removes the coefficients which's absolute value does
9.826 + /// not exceed \c epsilon.
9.827 + void simplify(Value epsilon = 0.0) {
9.828 + std::map<int, Value>::iterator it=comps.begin();
9.829 + while (it != comps.end()) {
9.830 + std::map<int, Value>::iterator jt=it;
9.831 + ++jt;
9.832 + if (std::fabs((*it).second) <= epsilon) comps.erase(it);
9.833 + it=jt;
9.834 }
9.835 }
9.836
9.837 - void simplify() const {
9.838 - const_cast<DualExpr*>(this)->simplify();
9.839 - }
9.840 -
9.841 - ///Removes the coefficients closer to zero than \c tolerance.
9.842 - void simplify(double &tolerance) {
9.843 - for (Base::iterator i=Base::begin(); i!=Base::end();) {
9.844 - Base::iterator j=i;
9.845 - ++j;
9.846 - if (std::fabs((*i).second)<tolerance) Base::erase(i);
9.847 - i=j;
9.848 - }
9.849 + void simplify(Value epsilon = 0.0) const {
9.850 + const_cast<DualExpr*>(this)->simplify(epsilon);
9.851 }
9.852
9.853 ///Sets all coefficients to 0.
9.854 void clear() {
9.855 - Base::clear();
9.856 + comps.clear();
9.857 + }
9.858 + ///Compound assignment
9.859 + DualExpr &operator+=(const DualExpr &e) {
9.860 + for (std::map<int, Value>::const_iterator it=e.comps.begin();
9.861 + it!=e.comps.end(); ++it)
9.862 + comps[it->first]+=it->second;
9.863 + return *this;
9.864 + }
9.865 + ///Compound assignment
9.866 + DualExpr &operator-=(const DualExpr &e) {
9.867 + for (std::map<int, Value>::const_iterator it=e.comps.begin();
9.868 + it!=e.comps.end(); ++it)
9.869 + comps[it->first]-=it->second;
9.870 + return *this;
9.871 + }
9.872 + ///Multiply with a constant
9.873 + DualExpr &operator*=(const Value &v) {
9.874 + for (std::map<int, Value>::iterator it=comps.begin();
9.875 + it!=comps.end(); ++it)
9.876 + it->second*=v;
9.877 + return *this;
9.878 + }
9.879 + ///Division with a constant
9.880 + DualExpr &operator/=(const Value &v) {
9.881 + for (std::map<int, Value>::iterator it=comps.begin();
9.882 + it!=comps.end(); ++it)
9.883 + it->second/=v;
9.884 + return *this;
9.885 }
9.886
9.887 - ///\e
9.888 - DualExpr &operator+=(const DualExpr &e) {
9.889 - for (Base::const_iterator j=e.begin(); j!=e.end(); ++j)
9.890 - (*this)[j->first]+=j->second;
9.891 - return *this;
9.892 - }
9.893 - ///\e
9.894 - DualExpr &operator-=(const DualExpr &e) {
9.895 - for (Base::const_iterator j=e.begin(); j!=e.end(); ++j)
9.896 - (*this)[j->first]-=j->second;
9.897 - return *this;
9.898 - }
9.899 - ///\e
9.900 - DualExpr &operator*=(const Value &c) {
9.901 - for (Base::iterator j=Base::begin(); j!=Base::end(); ++j)
9.902 - j->second*=c;
9.903 - return *this;
9.904 - }
9.905 - ///\e
9.906 - DualExpr &operator/=(const Value &c) {
9.907 - for (Base::iterator j=Base::begin(); j!=Base::end(); ++j)
9.908 - j->second/=c;
9.909 - return *this;
9.910 - }
9.911 + ///Iterator over the expression
9.912 +
9.913 + ///The iterator iterates over the terms of the expression.
9.914 + ///
9.915 + ///\code
9.916 + ///double s=0;
9.917 + ///for(LpBase::DualExpr::CoeffIt i(e);i!=INVALID;++i)
9.918 + /// s+= *i * dual(i);
9.919 + ///\endcode
9.920 + class CoeffIt {
9.921 + private:
9.922 +
9.923 + std::map<int, Value>::iterator _it, _end;
9.924 +
9.925 + public:
9.926 +
9.927 + /// Sets the iterator to the first term
9.928 +
9.929 + /// Sets the iterator to the first term of the expression.
9.930 + ///
9.931 + CoeffIt(DualExpr& e)
9.932 + : _it(e.comps.begin()), _end(e.comps.end()){}
9.933 +
9.934 + /// Convert the iterator to the row of the term
9.935 + operator Row() const {
9.936 + return rowFromId(_it->first);
9.937 + }
9.938 +
9.939 + /// Returns the coefficient of the term
9.940 + Value& operator*() { return _it->second; }
9.941 +
9.942 + /// Returns the coefficient of the term
9.943 + const Value& operator*() const { return _it->second; }
9.944 +
9.945 + /// Next term
9.946 +
9.947 + /// Assign the iterator to the next term.
9.948 + ///
9.949 + CoeffIt& operator++() { ++_it; return *this; }
9.950 +
9.951 + /// Equality operator
9.952 + bool operator==(Invalid) const { return _it == _end; }
9.953 + /// Inequality operator
9.954 + bool operator!=(Invalid) const { return _it != _end; }
9.955 + };
9.956 +
9.957 + ///Iterator over the expression
9.958 +
9.959 + ///The iterator iterates over the terms of the expression.
9.960 + ///
9.961 + ///\code
9.962 + ///double s=0;
9.963 + ///for(LpBase::DualExpr::ConstCoeffIt i(e);i!=INVALID;++i)
9.964 + /// s+= *i * dual(i);
9.965 + ///\endcode
9.966 + class ConstCoeffIt {
9.967 + private:
9.968 +
9.969 + std::map<int, Value>::const_iterator _it, _end;
9.970 +
9.971 + public:
9.972 +
9.973 + /// Sets the iterator to the first term
9.974 +
9.975 + /// Sets the iterator to the first term of the expression.
9.976 + ///
9.977 + ConstCoeffIt(const DualExpr& e)
9.978 + : _it(e.comps.begin()), _end(e.comps.end()){}
9.979 +
9.980 + /// Convert the iterator to the row of the term
9.981 + operator Row() const {
9.982 + return rowFromId(_it->first);
9.983 + }
9.984 +
9.985 + /// Returns the coefficient of the term
9.986 + const Value& operator*() const { return _it->second; }
9.987 +
9.988 + /// Next term
9.989 +
9.990 + /// Assign the iterator to the next term.
9.991 + ///
9.992 + ConstCoeffIt& operator++() { ++_it; return *this; }
9.993 +
9.994 + /// Equality operator
9.995 + bool operator==(Invalid) const { return _it == _end; }
9.996 + /// Inequality operator
9.997 + bool operator!=(Invalid) const { return _it != _end; }
9.998 + };
9.999 };
9.1000
9.1001
9.1002 - private:
9.1003 + protected:
9.1004
9.1005 - template <typename _Expr>
9.1006 - class MappedOutputIterator {
9.1007 + class InsertIterator {
9.1008 + private:
9.1009 +
9.1010 + std::map<int, Value>& _host;
9.1011 + const _solver_bits::VarIndex& _index;
9.1012 +
9.1013 public:
9.1014
9.1015 - typedef std::insert_iterator<_Expr> Base;
9.1016 -
9.1017 typedef std::output_iterator_tag iterator_category;
9.1018 typedef void difference_type;
9.1019 typedef void value_type;
9.1020 typedef void reference;
9.1021 typedef void pointer;
9.1022
9.1023 - MappedOutputIterator(const Base& _base, const LpSolverBase& _lp)
9.1024 - : base(_base), lp(_lp) {}
9.1025 + InsertIterator(std::map<int, Value>& host,
9.1026 + const _solver_bits::VarIndex& index)
9.1027 + : _host(host), _index(index) {}
9.1028
9.1029 - MappedOutputIterator& operator*() {
9.1030 + InsertIterator& operator=(const std::pair<int, Value>& value) {
9.1031 + typedef std::map<int, Value>::value_type pair_type;
9.1032 + _host.insert(pair_type(_index[value.first], value.second));
9.1033 return *this;
9.1034 }
9.1035
9.1036 - MappedOutputIterator& operator=(const std::pair<int, Value>& value) {
9.1037 - *base = std::make_pair(lp._item(value.first, typename _Expr::Key()),
9.1038 - value.second);
9.1039 - return *this;
9.1040 - }
9.1041 + InsertIterator& operator*() { return *this; }
9.1042 + InsertIterator& operator++() { return *this; }
9.1043 + InsertIterator operator++(int) { return *this; }
9.1044
9.1045 - MappedOutputIterator& operator++() {
9.1046 - ++base;
9.1047 - return *this;
9.1048 - }
9.1049 -
9.1050 - MappedOutputIterator operator++(int) {
9.1051 - MappedOutputIterator tmp(*this);
9.1052 - ++base;
9.1053 - return tmp;
9.1054 - }
9.1055 -
9.1056 - bool operator==(const MappedOutputIterator& it) const {
9.1057 - return base == it.base;
9.1058 - }
9.1059 -
9.1060 - bool operator!=(const MappedOutputIterator& it) const {
9.1061 - return base != it.base;
9.1062 - }
9.1063 -
9.1064 - private:
9.1065 - Base base;
9.1066 - const LpSolverBase& lp;
9.1067 };
9.1068
9.1069 - template <typename Expr>
9.1070 - class MappedInputIterator {
9.1071 + class ExprIterator {
9.1072 + private:
9.1073 + std::map<int, Value>::const_iterator _host_it;
9.1074 + const _solver_bits::VarIndex& _index;
9.1075 public:
9.1076
9.1077 - typedef typename Expr::const_iterator Base;
9.1078 -
9.1079 - typedef typename Base::iterator_category iterator_category;
9.1080 - typedef typename Base::difference_type difference_type;
9.1081 + typedef std::bidirectional_iterator_tag iterator_category;
9.1082 + typedef std::ptrdiff_t difference_type;
9.1083 typedef const std::pair<int, Value> value_type;
9.1084 typedef value_type reference;
9.1085 +
9.1086 class pointer {
9.1087 public:
9.1088 pointer(value_type& _value) : value(_value) {}
9.1089 @@ -653,82 +883,49 @@
9.1090 value_type value;
9.1091 };
9.1092
9.1093 - MappedInputIterator(const Base& _base, const LpSolverBase& _lp)
9.1094 - : base(_base), lp(_lp) {}
9.1095 + ExprIterator(const std::map<int, Value>::const_iterator& host_it,
9.1096 + const _solver_bits::VarIndex& index)
9.1097 + : _host_it(host_it), _index(index) {}
9.1098
9.1099 reference operator*() {
9.1100 - return std::make_pair(lp._lpId(base->first), base->second);
9.1101 + return std::make_pair(_index(_host_it->first), _host_it->second);
9.1102 }
9.1103
9.1104 pointer operator->() {
9.1105 return pointer(operator*());
9.1106 }
9.1107
9.1108 - MappedInputIterator& operator++() {
9.1109 - ++base;
9.1110 - return *this;
9.1111 + ExprIterator& operator++() { ++_host_it; return *this; }
9.1112 + ExprIterator operator++(int) {
9.1113 + ExprIterator tmp(*this); ++_host_it; return tmp;
9.1114 }
9.1115
9.1116 - MappedInputIterator operator++(int) {
9.1117 - MappedInputIterator tmp(*this);
9.1118 - ++base;
9.1119 - return tmp;
9.1120 + ExprIterator& operator--() { --_host_it; return *this; }
9.1121 + ExprIterator operator--(int) {
9.1122 + ExprIterator tmp(*this); --_host_it; return tmp;
9.1123 }
9.1124
9.1125 - bool operator==(const MappedInputIterator& it) const {
9.1126 - return base == it.base;
9.1127 + bool operator==(const ExprIterator& it) const {
9.1128 + return _host_it == it._host_it;
9.1129 }
9.1130
9.1131 - bool operator!=(const MappedInputIterator& it) const {
9.1132 - return base != it.base;
9.1133 + bool operator!=(const ExprIterator& it) const {
9.1134 + return _host_it != it._host_it;
9.1135 }
9.1136
9.1137 - private:
9.1138 - Base base;
9.1139 - const LpSolverBase& lp;
9.1140 };
9.1141
9.1142 protected:
9.1143
9.1144 - /// STL compatible iterator for lp col
9.1145 - typedef MappedInputIterator<Expr> ConstRowIterator;
9.1146 - /// STL compatible iterator for lp row
9.1147 - typedef MappedInputIterator<DualExpr> ConstColIterator;
9.1148 + //Abstract virtual functions
9.1149 + virtual LpBase* _newSolver() const = 0;
9.1150 + virtual LpBase* _cloneSolver() const = 0;
9.1151
9.1152 - /// STL compatible iterator for lp col
9.1153 - typedef MappedOutputIterator<Expr> RowIterator;
9.1154 - /// STL compatible iterator for lp row
9.1155 - typedef MappedOutputIterator<DualExpr> ColIterator;
9.1156 + virtual int _addColId(int col) { return cols.addIndex(col); }
9.1157 + virtual int _addRowId(int row) { return rows.addIndex(row); }
9.1158
9.1159 - //Abstract virtual functions
9.1160 - virtual LpSolverBase* _newLp() = 0;
9.1161 - virtual LpSolverBase* _copyLp(){
9.1162 - LpSolverBase* newlp = _newLp();
9.1163 -
9.1164 - std::map<Col, Col> ref;
9.1165 - for (LpSolverBase::ColIt it(*this); it != INVALID; ++it) {
9.1166 - Col ccol = newlp->addCol();
9.1167 - ref[it] = ccol;
9.1168 - newlp->colName(ccol, colName(it));
9.1169 - newlp->colLowerBound(ccol, colLowerBound(it));
9.1170 - newlp->colUpperBound(ccol, colUpperBound(it));
9.1171 - }
9.1172 -
9.1173 - for (LpSolverBase::RowIt it(*this); it != INVALID; ++it) {
9.1174 - Expr e = row(it), ce;
9.1175 - for (Expr::iterator jt = e.begin(); jt != e.end(); ++jt) {
9.1176 - ce[ref[jt->first]] = jt->second;
9.1177 - }
9.1178 - ce += e.constComp();
9.1179 - Row r = newlp->addRow(ce);
9.1180 -
9.1181 - double lower, upper;
9.1182 - getRowBounds(it, lower, upper);
9.1183 - newlp->rowBounds(r, lower, upper);
9.1184 - }
9.1185 -
9.1186 - return newlp;
9.1187 - };
9.1188 + virtual void _eraseColId(int col) { cols.eraseIndex(col); }
9.1189 + virtual void _eraseRowId(int row) { rows.eraseIndex(row); }
9.1190
9.1191 virtual int _addCol() = 0;
9.1192 virtual int _addRow() = 0;
9.1193 @@ -736,93 +933,95 @@
9.1194 virtual void _eraseCol(int col) = 0;
9.1195 virtual void _eraseRow(int row) = 0;
9.1196
9.1197 - virtual void _getColName(int col, std::string & name) const = 0;
9.1198 - virtual void _setColName(int col, const std::string & name) = 0;
9.1199 + virtual void _getColName(int col, std::string& name) const = 0;
9.1200 + virtual void _setColName(int col, const std::string& name) = 0;
9.1201 virtual int _colByName(const std::string& name) const = 0;
9.1202
9.1203 - virtual void _setRowCoeffs(int i, ConstRowIterator b,
9.1204 - ConstRowIterator e) = 0;
9.1205 - virtual void _getRowCoeffs(int i, RowIterator b) const = 0;
9.1206 - virtual void _setColCoeffs(int i, ConstColIterator b,
9.1207 - ConstColIterator e) = 0;
9.1208 - virtual void _getColCoeffs(int i, ColIterator b) const = 0;
9.1209 + virtual void _getRowName(int row, std::string& name) const = 0;
9.1210 + virtual void _setRowName(int row, const std::string& name) = 0;
9.1211 + virtual int _rowByName(const std::string& name) const = 0;
9.1212 +
9.1213 + virtual void _setRowCoeffs(int i, ExprIterator b, ExprIterator e) = 0;
9.1214 + virtual void _getRowCoeffs(int i, InsertIterator b) const = 0;
9.1215 +
9.1216 + virtual void _setColCoeffs(int i, ExprIterator b, ExprIterator e) = 0;
9.1217 + virtual void _getColCoeffs(int i, InsertIterator b) const = 0;
9.1218 +
9.1219 virtual void _setCoeff(int row, int col, Value value) = 0;
9.1220 virtual Value _getCoeff(int row, int col) const = 0;
9.1221 +
9.1222 virtual void _setColLowerBound(int i, Value value) = 0;
9.1223 virtual Value _getColLowerBound(int i) const = 0;
9.1224 +
9.1225 virtual void _setColUpperBound(int i, Value value) = 0;
9.1226 virtual Value _getColUpperBound(int i) const = 0;
9.1227 - virtual void _setRowBounds(int i, Value lower, Value upper) = 0;
9.1228 - virtual void _getRowBounds(int i, Value &lower, Value &upper) const = 0;
9.1229 +
9.1230 + virtual void _setRowLowerBound(int i, Value value) = 0;
9.1231 + virtual Value _getRowLowerBound(int i) const = 0;
9.1232 +
9.1233 + virtual void _setRowUpperBound(int i, Value value) = 0;
9.1234 + virtual Value _getRowUpperBound(int i) const = 0;
9.1235 +
9.1236 + virtual void _setObjCoeffs(ExprIterator b, ExprIterator e) = 0;
9.1237 + virtual void _getObjCoeffs(InsertIterator b) const = 0;
9.1238
9.1239 virtual void _setObjCoeff(int i, Value obj_coef) = 0;
9.1240 virtual Value _getObjCoeff(int i) const = 0;
9.1241 - virtual void _clearObj()=0;
9.1242
9.1243 - virtual SolveExitStatus _solve() = 0;
9.1244 - virtual Value _getPrimal(int i) const = 0;
9.1245 - virtual Value _getDual(int i) const = 0;
9.1246 - virtual Value _getPrimalValue() const = 0;
9.1247 - virtual bool _isBasicCol(int i) const = 0;
9.1248 - virtual SolutionStatus _getPrimalStatus() const = 0;
9.1249 - virtual SolutionStatus _getDualStatus() const = 0;
9.1250 - virtual ProblemTypes _getProblemType() const = 0;
9.1251 + virtual void _setSense(Sense) = 0;
9.1252 + virtual Sense _getSense() const = 0;
9.1253
9.1254 - virtual void _setMax() = 0;
9.1255 - virtual void _setMin() = 0;
9.1256 + virtual void _clear() = 0;
9.1257
9.1258 -
9.1259 - virtual bool _isMax() const = 0;
9.1260 + virtual const char* _solverName() const = 0;
9.1261
9.1262 //Own protected stuff
9.1263
9.1264 //Constant component of the objective function
9.1265 Value obj_const_comp;
9.1266
9.1267 + LpBase() : rows(), cols(), obj_const_comp(0) {}
9.1268 +
9.1269 public:
9.1270
9.1271 - ///\e
9.1272 - LpSolverBase() : obj_const_comp(0) {}
9.1273 -
9.1274 - ///\e
9.1275 - virtual ~LpSolverBase() {}
9.1276 + /// Virtual destructor
9.1277 + virtual ~LpBase() {}
9.1278
9.1279 ///Creates a new LP problem
9.1280 - LpSolverBase* newLp() {return _newLp();}
9.1281 + LpBase* newSolver() {return _newSolver();}
9.1282 ///Makes a copy of the LP problem
9.1283 - LpSolverBase* copyLp() {return _copyLp();}
9.1284 + LpBase* cloneSolver() {return _cloneSolver();}
9.1285 +
9.1286 + ///Gives back the name of the solver.
9.1287 + const char* solverName() const {return _solverName();}
9.1288
9.1289 ///\name Build up and modify the LP
9.1290
9.1291 ///@{
9.1292
9.1293 ///Add a new empty column (i.e a new variable) to the LP
9.1294 - Col addCol() { Col c; _addCol(); c.id = cols.addId(); return c;}
9.1295 + Col addCol() { Col c; c._id = _addColId(_addCol()); return c;}
9.1296
9.1297 - ///\brief Adds several new columns
9.1298 - ///(i.e a variables) at once
9.1299 + ///\brief Adds several new columns (i.e variables) at once
9.1300 ///
9.1301 - ///This magic function takes a container as its argument
9.1302 - ///and fills its elements
9.1303 - ///with new columns (i.e. variables)
9.1304 + ///This magic function takes a container as its argument and fills
9.1305 + ///its elements with new columns (i.e. variables)
9.1306 ///\param t can be
9.1307 ///- a standard STL compatible iterable container with
9.1308 - ///\ref Col as its \c values_type
9.1309 - ///like
9.1310 + ///\ref Col as its \c values_type like
9.1311 ///\code
9.1312 - ///std::vector<LpSolverBase::Col>
9.1313 - ///std::list<LpSolverBase::Col>
9.1314 + ///std::vector<LpBase::Col>
9.1315 + ///std::list<LpBase::Col>
9.1316 ///\endcode
9.1317 ///- a standard STL compatible iterable container with
9.1318 - ///\ref Col as its \c mapped_type
9.1319 - ///like
9.1320 + ///\ref Col as its \c mapped_type like
9.1321 ///\code
9.1322 - ///std::map<AnyType,LpSolverBase::Col>
9.1323 + ///std::map<AnyType,LpBase::Col>
9.1324 ///\endcode
9.1325 ///- an iterable lemon \ref concepts::WriteMap "write map" like
9.1326 ///\code
9.1327 - ///ListGraph::NodeMap<LpSolverBase::Col>
9.1328 - ///ListGraph::EdgeMap<LpSolverBase::Col>
9.1329 + ///ListGraph::NodeMap<LpBase::Col>
9.1330 + ///ListGraph::ArcMap<LpBase::Col>
9.1331 ///\endcode
9.1332 ///\return The number of the created column.
9.1333 #ifdef DOXYGEN
9.1334 @@ -830,14 +1029,14 @@
9.1335 int addColSet(T &t) { return 0;}
9.1336 #else
9.1337 template<class T>
9.1338 - typename enable_if<typename T::value_type::LpSolverCol,int>::type
9.1339 + typename enable_if<typename T::value_type::LpCol,int>::type
9.1340 addColSet(T &t,dummy<0> = 0) {
9.1341 int s=0;
9.1342 for(typename T::iterator i=t.begin();i!=t.end();++i) {*i=addCol();s++;}
9.1343 return s;
9.1344 }
9.1345 template<class T>
9.1346 - typename enable_if<typename T::value_type::second_type::LpSolverCol,
9.1347 + typename enable_if<typename T::value_type::second_type::LpCol,
9.1348 int>::type
9.1349 addColSet(T &t,dummy<1> = 1) {
9.1350 int s=0;
9.1351 @@ -848,7 +1047,7 @@
9.1352 return s;
9.1353 }
9.1354 template<class T>
9.1355 - typename enable_if<typename T::MapIt::Value::LpSolverCol,
9.1356 + typename enable_if<typename T::MapIt::Value::LpCol,
9.1357 int>::type
9.1358 addColSet(T &t,dummy<2> = 2) {
9.1359 int s=0;
9.1360 @@ -866,26 +1065,26 @@
9.1361 ///\param c is the column to be modified
9.1362 ///\param e is a dual linear expression (see \ref DualExpr)
9.1363 ///a better one.
9.1364 - void col(Col c,const DualExpr &e) {
9.1365 + void col(Col c, const DualExpr &e) {
9.1366 e.simplify();
9.1367 - _setColCoeffs(_lpId(c), ConstColIterator(e.begin(), *this),
9.1368 - ConstColIterator(e.end(), *this));
9.1369 + _setColCoeffs(cols(id(c)), ExprIterator(e.comps.begin(), cols),
9.1370 + ExprIterator(e.comps.end(), cols));
9.1371 }
9.1372
9.1373 ///Get a column (i.e a dual constraint) of the LP
9.1374
9.1375 - ///\param r is the column to get
9.1376 + ///\param c is the column to get
9.1377 ///\return the dual expression associated to the column
9.1378 DualExpr col(Col c) const {
9.1379 DualExpr e;
9.1380 - _getColCoeffs(_lpId(c), ColIterator(std::inserter(e, e.end()), *this));
9.1381 + _getColCoeffs(cols(id(c)), InsertIterator(e.comps, rows));
9.1382 return e;
9.1383 }
9.1384
9.1385 ///Add a new column to the LP
9.1386
9.1387 ///\param e is a dual linear expression (see \ref DualExpr)
9.1388 - ///\param obj is the corresponding component of the objective
9.1389 + ///\param o is the corresponding component of the objective
9.1390 ///function. It is 0 by default.
9.1391 ///\return The created column.
9.1392 Col addCol(const DualExpr &e, Value o = 0) {
9.1393 @@ -899,32 +1098,28 @@
9.1394
9.1395 ///This function adds a new empty row (i.e a new constraint) to the LP.
9.1396 ///\return The created row
9.1397 - Row addRow() { Row r; _addRow(); r.id = rows.addId(); return r;}
9.1398 + Row addRow() { Row r; r._id = _addRowId(_addRow()); return r;}
9.1399
9.1400 - ///\brief Add several new rows
9.1401 - ///(i.e a constraints) at once
9.1402 + ///\brief Add several new rows (i.e constraints) at once
9.1403 ///
9.1404 - ///This magic function takes a container as its argument
9.1405 - ///and fills its elements
9.1406 - ///with new row (i.e. variables)
9.1407 + ///This magic function takes a container as its argument and fills
9.1408 + ///its elements with new row (i.e. variables)
9.1409 ///\param t can be
9.1410 ///- a standard STL compatible iterable container with
9.1411 - ///\ref Row as its \c values_type
9.1412 - ///like
9.1413 + ///\ref Row as its \c values_type like
9.1414 ///\code
9.1415 - ///std::vector<LpSolverBase::Row>
9.1416 - ///std::list<LpSolverBase::Row>
9.1417 + ///std::vector<LpBase::Row>
9.1418 + ///std::list<LpBase::Row>
9.1419 ///\endcode
9.1420 ///- a standard STL compatible iterable container with
9.1421 - ///\ref Row as its \c mapped_type
9.1422 - ///like
9.1423 + ///\ref Row as its \c mapped_type like
9.1424 ///\code
9.1425 - ///std::map<AnyType,LpSolverBase::Row>
9.1426 + ///std::map<AnyType,LpBase::Row>
9.1427 ///\endcode
9.1428 ///- an iterable lemon \ref concepts::WriteMap "write map" like
9.1429 ///\code
9.1430 - ///ListGraph::NodeMap<LpSolverBase::Row>
9.1431 - ///ListGraph::EdgeMap<LpSolverBase::Row>
9.1432 + ///ListGraph::NodeMap<LpBase::Row>
9.1433 + ///ListGraph::ArcMap<LpBase::Row>
9.1434 ///\endcode
9.1435 ///\return The number of rows created.
9.1436 #ifdef DOXYGEN
9.1437 @@ -932,16 +1127,15 @@
9.1438 int addRowSet(T &t) { return 0;}
9.1439 #else
9.1440 template<class T>
9.1441 - typename enable_if<typename T::value_type::LpSolverRow,int>::type
9.1442 - addRowSet(T &t,dummy<0> = 0) {
9.1443 + typename enable_if<typename T::value_type::LpRow,int>::type
9.1444 + addRowSet(T &t, dummy<0> = 0) {
9.1445 int s=0;
9.1446 for(typename T::iterator i=t.begin();i!=t.end();++i) {*i=addRow();s++;}
9.1447 return s;
9.1448 }
9.1449 template<class T>
9.1450 - typename enable_if<typename T::value_type::second_type::LpSolverRow,
9.1451 - int>::type
9.1452 - addRowSet(T &t,dummy<1> = 1) {
9.1453 + typename enable_if<typename T::value_type::second_type::LpRow, int>::type
9.1454 + addRowSet(T &t, dummy<1> = 1) {
9.1455 int s=0;
9.1456 for(typename T::iterator i=t.begin();i!=t.end();++i) {
9.1457 i->second=addRow();
9.1458 @@ -950,9 +1144,8 @@
9.1459 return s;
9.1460 }
9.1461 template<class T>
9.1462 - typename enable_if<typename T::MapIt::Value::LpSolverRow,
9.1463 - int>::type
9.1464 - addRowSet(T &t,dummy<2> = 2) {
9.1465 + typename enable_if<typename T::MapIt::Value::LpRow, int>::type
9.1466 + addRowSet(T &t, dummy<2> = 2) {
9.1467 int s=0;
9.1468 for(typename T::MapIt i(t); i!=INVALID; ++i)
9.1469 {
9.1470 @@ -969,15 +1162,12 @@
9.1471 ///\param l is lower bound (-\ref INF means no bound)
9.1472 ///\param e is a linear expression (see \ref Expr)
9.1473 ///\param u is the upper bound (\ref INF means no bound)
9.1474 - ///\bug This is a temporary function. The interface will change to
9.1475 - ///a better one.
9.1476 - ///\todo Option to control whether a constraint with a single variable is
9.1477 - ///added or not.
9.1478 void row(Row r, Value l, const Expr &e, Value u) {
9.1479 e.simplify();
9.1480 - _setRowCoeffs(_lpId(r), ConstRowIterator(e.begin(), *this),
9.1481 - ConstRowIterator(e.end(), *this));
9.1482 - _setRowBounds(_lpId(r),l-e.constComp(),u-e.constComp());
9.1483 + _setRowCoeffs(rows(id(r)), ExprIterator(e.comps.begin(), cols),
9.1484 + ExprIterator(e.comps.end(), cols));
9.1485 + _setRowLowerBound(rows(id(r)),l - *e);
9.1486 + _setRowUpperBound(rows(id(r)),u - *e);
9.1487 }
9.1488
9.1489 ///Set a row (i.e a constraint) of the LP
9.1490 @@ -996,7 +1186,7 @@
9.1491 ///\return the expression associated to the row
9.1492 Expr row(Row r) const {
9.1493 Expr e;
9.1494 - _getRowCoeffs(_lpId(r), RowIterator(std::inserter(e, e.end()), *this));
9.1495 + _getRowCoeffs(rows(id(r)), InsertIterator(e.comps, cols));
9.1496 return e;
9.1497 }
9.1498
9.1499 @@ -1006,8 +1196,6 @@
9.1500 ///\param e is a linear expression (see \ref Expr)
9.1501 ///\param u is the upper bound (\ref INF means no bound)
9.1502 ///\return The created row.
9.1503 - ///\bug This is a temporary function. The interface will change to
9.1504 - ///a better one.
9.1505 Row addRow(Value l,const Expr &e, Value u) {
9.1506 Row r=addRow();
9.1507 row(r,l,e,u);
9.1508 @@ -1023,39 +1211,37 @@
9.1509 row(r,c);
9.1510 return r;
9.1511 }
9.1512 - ///Erase a coloumn (i.e a variable) from the LP
9.1513 + ///Erase a column (i.e a variable) from the LP
9.1514
9.1515 - ///\param c is the coloumn to be deleted
9.1516 - ///\todo Please check this
9.1517 - void eraseCol(Col c) {
9.1518 - _eraseCol(_lpId(c));
9.1519 - cols.eraseId(c.id);
9.1520 + ///\param c is the column to be deleted
9.1521 + void erase(Col c) {
9.1522 + _eraseCol(cols(id(c)));
9.1523 + _eraseColId(cols(id(c)));
9.1524 }
9.1525 - ///Erase a row (i.e a constraint) from the LP
9.1526 + ///Erase a row (i.e a constraint) from the LP
9.1527
9.1528 ///\param r is the row to be deleted
9.1529 - ///\todo Please check this
9.1530 - void eraseRow(Row r) {
9.1531 - _eraseRow(_lpId(r));
9.1532 - rows.eraseId(r.id);
9.1533 + void erase(Row r) {
9.1534 + _eraseRow(rows(id(r)));
9.1535 + _eraseRowId(rows(id(r)));
9.1536 }
9.1537
9.1538 /// Get the name of a column
9.1539
9.1540 - ///\param c is the coresponding coloumn
9.1541 + ///\param c is the coresponding column
9.1542 ///\return The name of the colunm
9.1543 std::string colName(Col c) const {
9.1544 std::string name;
9.1545 - _getColName(_lpId(c), name);
9.1546 + _getColName(cols(id(c)), name);
9.1547 return name;
9.1548 }
9.1549
9.1550 /// Set the name of a column
9.1551
9.1552 - ///\param c is the coresponding coloumn
9.1553 + ///\param c is the coresponding column
9.1554 ///\param name The name to be given
9.1555 void colName(Col c, const std::string& name) {
9.1556 - _setColName(_lpId(c), name);
9.1557 + _setColName(cols(id(c)), name);
9.1558 }
9.1559
9.1560 /// Get the column by its name
9.1561 @@ -1064,27 +1250,52 @@
9.1562 ///\return the proper column or \c INVALID
9.1563 Col colByName(const std::string& name) const {
9.1564 int k = _colByName(name);
9.1565 - return k != -1 ? Col(cols.fixId(k)) : Col(INVALID);
9.1566 + return k != -1 ? Col(cols[k]) : Col(INVALID);
9.1567 + }
9.1568 +
9.1569 + /// Get the name of a row
9.1570 +
9.1571 + ///\param r is the coresponding row
9.1572 + ///\return The name of the row
9.1573 + std::string rowName(Row r) const {
9.1574 + std::string name;
9.1575 + _getRowName(rows(id(r)), name);
9.1576 + return name;
9.1577 + }
9.1578 +
9.1579 + /// Set the name of a row
9.1580 +
9.1581 + ///\param r is the coresponding row
9.1582 + ///\param name The name to be given
9.1583 + void rowName(Row r, const std::string& name) {
9.1584 + _setRowName(rows(id(r)), name);
9.1585 + }
9.1586 +
9.1587 + /// Get the row by its name
9.1588 +
9.1589 + ///\param name The name of the row
9.1590 + ///\return the proper row or \c INVALID
9.1591 + Row rowByName(const std::string& name) const {
9.1592 + int k = _rowByName(name);
9.1593 + return k != -1 ? Row(rows[k]) : Row(INVALID);
9.1594 }
9.1595
9.1596 /// Set an element of the coefficient matrix of the LP
9.1597
9.1598 ///\param r is the row of the element to be modified
9.1599 - ///\param c is the coloumn of the element to be modified
9.1600 + ///\param c is the column of the element to be modified
9.1601 ///\param val is the new value of the coefficient
9.1602 -
9.1603 void coeff(Row r, Col c, Value val) {
9.1604 - _setCoeff(_lpId(r),_lpId(c), val);
9.1605 + _setCoeff(rows(id(r)),cols(id(c)), val);
9.1606 }
9.1607
9.1608 /// Get an element of the coefficient matrix of the LP
9.1609
9.1610 - ///\param r is the row of the element in question
9.1611 - ///\param c is the coloumn of the element in question
9.1612 + ///\param r is the row of the element
9.1613 + ///\param c is the column of the element
9.1614 ///\return the corresponding coefficient
9.1615 -
9.1616 Value coeff(Row r, Col c) const {
9.1617 - return _getCoeff(_lpId(r),_lpId(c));
9.1618 + return _getCoeff(rows(id(r)),cols(id(c)));
9.1619 }
9.1620
9.1621 /// Set the lower bound of a column (i.e a variable)
9.1622 @@ -1093,39 +1304,39 @@
9.1623 /// extended number of type Value, i.e. a finite number of type
9.1624 /// Value or -\ref INF.
9.1625 void colLowerBound(Col c, Value value) {
9.1626 - _setColLowerBound(_lpId(c),value);
9.1627 + _setColLowerBound(cols(id(c)),value);
9.1628 }
9.1629
9.1630 /// Get the lower bound of a column (i.e a variable)
9.1631
9.1632 - /// This function returns the lower bound for column (variable) \t c
9.1633 + /// This function returns the lower bound for column (variable) \c c
9.1634 /// (this might be -\ref INF as well).
9.1635 - ///\return The lower bound for coloumn \t c
9.1636 + ///\return The lower bound for column \c c
9.1637 Value colLowerBound(Col c) const {
9.1638 - return _getColLowerBound(_lpId(c));
9.1639 + return _getColLowerBound(cols(id(c)));
9.1640 }
9.1641
9.1642 ///\brief Set the lower bound of several columns
9.1643 - ///(i.e a variables) at once
9.1644 + ///(i.e variables) at once
9.1645 ///
9.1646 ///This magic function takes a container as its argument
9.1647 ///and applies the function on all of its elements.
9.1648 - /// The lower bound of a variable (column) has to be given by an
9.1649 - /// extended number of type Value, i.e. a finite number of type
9.1650 - /// Value or -\ref INF.
9.1651 + ///The lower bound of a variable (column) has to be given by an
9.1652 + ///extended number of type Value, i.e. a finite number of type
9.1653 + ///Value or -\ref INF.
9.1654 #ifdef DOXYGEN
9.1655 template<class T>
9.1656 void colLowerBound(T &t, Value value) { return 0;}
9.1657 #else
9.1658 template<class T>
9.1659 - typename enable_if<typename T::value_type::LpSolverCol,void>::type
9.1660 + typename enable_if<typename T::value_type::LpCol,void>::type
9.1661 colLowerBound(T &t, Value value,dummy<0> = 0) {
9.1662 for(typename T::iterator i=t.begin();i!=t.end();++i) {
9.1663 colLowerBound(*i, value);
9.1664 }
9.1665 }
9.1666 template<class T>
9.1667 - typename enable_if<typename T::value_type::second_type::LpSolverCol,
9.1668 + typename enable_if<typename T::value_type::second_type::LpCol,
9.1669 void>::type
9.1670 colLowerBound(T &t, Value value,dummy<1> = 1) {
9.1671 for(typename T::iterator i=t.begin();i!=t.end();++i) {
9.1672 @@ -1133,7 +1344,7 @@
9.1673 }
9.1674 }
9.1675 template<class T>
9.1676 - typename enable_if<typename T::MapIt::Value::LpSolverCol,
9.1677 + typename enable_if<typename T::MapIt::Value::LpCol,
9.1678 void>::type
9.1679 colLowerBound(T &t, Value value,dummy<2> = 2) {
9.1680 for(typename T::MapIt i(t); i!=INVALID; ++i){
9.1681 @@ -1148,39 +1359,39 @@
9.1682 /// extended number of type Value, i.e. a finite number of type
9.1683 /// Value or \ref INF.
9.1684 void colUpperBound(Col c, Value value) {
9.1685 - _setColUpperBound(_lpId(c),value);
9.1686 + _setColUpperBound(cols(id(c)),value);
9.1687 };
9.1688
9.1689 /// Get the upper bound of a column (i.e a variable)
9.1690
9.1691 - /// This function returns the upper bound for column (variable) \t c
9.1692 + /// This function returns the upper bound for column (variable) \c c
9.1693 /// (this might be \ref INF as well).
9.1694 - ///\return The upper bound for coloumn \t c
9.1695 + /// \return The upper bound for column \c c
9.1696 Value colUpperBound(Col c) const {
9.1697 - return _getColUpperBound(_lpId(c));
9.1698 + return _getColUpperBound(cols(id(c)));
9.1699 }
9.1700
9.1701 ///\brief Set the upper bound of several columns
9.1702 - ///(i.e a variables) at once
9.1703 + ///(i.e variables) at once
9.1704 ///
9.1705 ///This magic function takes a container as its argument
9.1706 ///and applies the function on all of its elements.
9.1707 - /// The upper bound of a variable (column) has to be given by an
9.1708 - /// extended number of type Value, i.e. a finite number of type
9.1709 - /// Value or \ref INF.
9.1710 + ///The upper bound of a variable (column) has to be given by an
9.1711 + ///extended number of type Value, i.e. a finite number of type
9.1712 + ///Value or \ref INF.
9.1713 #ifdef DOXYGEN
9.1714 template<class T>
9.1715 void colUpperBound(T &t, Value value) { return 0;}
9.1716 #else
9.1717 template<class T>
9.1718 - typename enable_if<typename T::value_type::LpSolverCol,void>::type
9.1719 + typename enable_if<typename T::value_type::LpCol,void>::type
9.1720 colUpperBound(T &t, Value value,dummy<0> = 0) {
9.1721 for(typename T::iterator i=t.begin();i!=t.end();++i) {
9.1722 colUpperBound(*i, value);
9.1723 }
9.1724 }
9.1725 template<class T>
9.1726 - typename enable_if<typename T::value_type::second_type::LpSolverCol,
9.1727 + typename enable_if<typename T::value_type::second_type::LpCol,
9.1728 void>::type
9.1729 colUpperBound(T &t, Value value,dummy<1> = 1) {
9.1730 for(typename T::iterator i=t.begin();i!=t.end();++i) {
9.1731 @@ -1188,7 +1399,7 @@
9.1732 }
9.1733 }
9.1734 template<class T>
9.1735 - typename enable_if<typename T::MapIt::Value::LpSolverCol,
9.1736 + typename enable_if<typename T::MapIt::Value::LpCol,
9.1737 void>::type
9.1738 colUpperBound(T &t, Value value,dummy<2> = 2) {
9.1739 for(typename T::MapIt i(t); i!=INVALID; ++i){
9.1740 @@ -1204,12 +1415,12 @@
9.1741 /// extended number of type Value, i.e. a finite number of type
9.1742 /// Value, -\ref INF or \ref INF.
9.1743 void colBounds(Col c, Value lower, Value upper) {
9.1744 - _setColLowerBound(_lpId(c),lower);
9.1745 - _setColUpperBound(_lpId(c),upper);
9.1746 + _setColLowerBound(cols(id(c)),lower);
9.1747 + _setColUpperBound(cols(id(c)),upper);
9.1748 }
9.1749
9.1750 ///\brief Set the lower and the upper bound of several columns
9.1751 - ///(i.e a variables) at once
9.1752 + ///(i.e variables) at once
9.1753 ///
9.1754 ///This magic function takes a container as its argument
9.1755 ///and applies the function on all of its elements.
9.1756 @@ -1222,23 +1433,21 @@
9.1757 void colBounds(T &t, Value lower, Value upper) { return 0;}
9.1758 #else
9.1759 template<class T>
9.1760 - typename enable_if<typename T::value_type::LpSolverCol,void>::type
9.1761 + typename enable_if<typename T::value_type::LpCol,void>::type
9.1762 colBounds(T &t, Value lower, Value upper,dummy<0> = 0) {
9.1763 for(typename T::iterator i=t.begin();i!=t.end();++i) {
9.1764 colBounds(*i, lower, upper);
9.1765 }
9.1766 }
9.1767 template<class T>
9.1768 - typename enable_if<typename T::value_type::second_type::LpSolverCol,
9.1769 - void>::type
9.1770 + typename enable_if<typename T::value_type::second_type::LpCol, void>::type
9.1771 colBounds(T &t, Value lower, Value upper,dummy<1> = 1) {
9.1772 for(typename T::iterator i=t.begin();i!=t.end();++i) {
9.1773 colBounds(i->second, lower, upper);
9.1774 }
9.1775 }
9.1776 template<class T>
9.1777 - typename enable_if<typename T::MapIt::Value::LpSolverCol,
9.1778 - void>::type
9.1779 + typename enable_if<typename T::MapIt::Value::LpCol, void>::type
9.1780 colBounds(T &t, Value lower, Value upper,dummy<2> = 2) {
9.1781 for(typename T::MapIt i(t); i!=INVALID; ++i){
9.1782 colBounds(*i, lower, upper);
9.1783 @@ -1246,76 +1455,371 @@
9.1784 }
9.1785 #endif
9.1786
9.1787 + /// Set the lower bound of a row (i.e a constraint)
9.1788
9.1789 - /// Set the lower and the upper bounds of a row (i.e a constraint)
9.1790 -
9.1791 - /// The lower and the upper bound of a constraint (row) have to be
9.1792 - /// given by an extended number of type Value, i.e. a finite
9.1793 - /// number of type Value, -\ref INF or \ref INF. There is no
9.1794 - /// separate function for the lower and the upper bound because
9.1795 - /// that would have been hard to implement for CPLEX.
9.1796 - void rowBounds(Row c, Value lower, Value upper) {
9.1797 - _setRowBounds(_lpId(c),lower, upper);
9.1798 + /// The lower bound of a constraint (row) has to be given by an
9.1799 + /// extended number of type Value, i.e. a finite number of type
9.1800 + /// Value or -\ref INF.
9.1801 + void rowLowerBound(Row r, Value value) {
9.1802 + _setRowLowerBound(rows(id(r)),value);
9.1803 }
9.1804
9.1805 - /// Get the lower and the upper bounds of a row (i.e a constraint)
9.1806 + /// Get the lower bound of a row (i.e a constraint)
9.1807
9.1808 - /// The lower and the upper bound of
9.1809 - /// a constraint (row) are
9.1810 - /// extended numbers of type Value, i.e. finite numbers of type
9.1811 - /// Value, -\ref INF or \ref INF.
9.1812 - /// \todo There is no separate function for the
9.1813 - /// lower and the upper bound because we had problems with the
9.1814 - /// implementation of the setting functions for CPLEX:
9.1815 - /// check out whether this can be done for these functions.
9.1816 - void getRowBounds(Row c, Value &lower, Value &upper) const {
9.1817 - _getRowBounds(_lpId(c),lower, upper);
9.1818 + /// This function returns the lower bound for row (constraint) \c c
9.1819 + /// (this might be -\ref INF as well).
9.1820 + ///\return The lower bound for row \c r
9.1821 + Value rowLowerBound(Row r) const {
9.1822 + return _getRowLowerBound(rows(id(r)));
9.1823 + }
9.1824 +
9.1825 + /// Set the upper bound of a row (i.e a constraint)
9.1826 +
9.1827 + /// The upper bound of a constraint (row) has to be given by an
9.1828 + /// extended number of type Value, i.e. a finite number of type
9.1829 + /// Value or -\ref INF.
9.1830 + void rowUpperBound(Row r, Value value) {
9.1831 + _setRowUpperBound(rows(id(r)),value);
9.1832 + }
9.1833 +
9.1834 + /// Get the upper bound of a row (i.e a constraint)
9.1835 +
9.1836 + /// This function returns the upper bound for row (constraint) \c c
9.1837 + /// (this might be -\ref INF as well).
9.1838 + ///\return The upper bound for row \c r
9.1839 + Value rowUpperBound(Row r) const {
9.1840 + return _getRowUpperBound(rows(id(r)));
9.1841 }
9.1842
9.1843 ///Set an element of the objective function
9.1844 - void objCoeff(Col c, Value v) {_setObjCoeff(_lpId(c),v); };
9.1845 + void objCoeff(Col c, Value v) {_setObjCoeff(cols(id(c)),v); };
9.1846
9.1847 ///Get an element of the objective function
9.1848 - Value objCoeff(Col c) const { return _getObjCoeff(_lpId(c)); };
9.1849 + Value objCoeff(Col c) const { return _getObjCoeff(cols(id(c))); };
9.1850
9.1851 ///Set the objective function
9.1852
9.1853 ///\param e is a linear expression of type \ref Expr.
9.1854 - void obj(Expr e) {
9.1855 - _clearObj();
9.1856 - for (Expr::iterator i=e.begin(); i!=e.end(); ++i)
9.1857 - objCoeff((*i).first,(*i).second);
9.1858 - obj_const_comp=e.constComp();
9.1859 + ///
9.1860 + void obj(const Expr& e) {
9.1861 + _setObjCoeffs(ExprIterator(e.comps.begin(), cols),
9.1862 + ExprIterator(e.comps.end(), cols));
9.1863 + obj_const_comp = *e;
9.1864 }
9.1865
9.1866 ///Get the objective function
9.1867
9.1868 - ///\return the objective function as a linear expression of type \ref Expr.
9.1869 + ///\return the objective function as a linear expression of type
9.1870 + ///Expr.
9.1871 Expr obj() const {
9.1872 Expr e;
9.1873 - for (ColIt it(*this); it != INVALID; ++it) {
9.1874 - double c = objCoeff(it);
9.1875 - if (c != 0.0) {
9.1876 - e.insert(std::make_pair(it, c));
9.1877 - }
9.1878 - }
9.1879 + _getObjCoeffs(InsertIterator(e.comps, cols));
9.1880 + *e = obj_const_comp;
9.1881 return e;
9.1882 }
9.1883
9.1884
9.1885 - ///Maximize
9.1886 - void max() { _setMax(); }
9.1887 - ///Minimize
9.1888 - void min() { _setMin(); }
9.1889 + ///Set the direction of optimization
9.1890 + void sense(Sense sense) { _setSense(sense); }
9.1891
9.1892 - ///Query function: is this a maximization problem?
9.1893 - bool isMax() const {return _isMax(); }
9.1894 + ///Query the direction of the optimization
9.1895 + Sense sense() const {return _getSense(); }
9.1896
9.1897 - ///Query function: is this a minimization problem?
9.1898 - bool isMin() const {return !isMax(); }
9.1899 + ///Set the sense to maximization
9.1900 + void max() { _setSense(MAX); }
9.1901 +
9.1902 + ///Set the sense to maximization
9.1903 + void min() { _setSense(MIN); }
9.1904 +
9.1905 + ///Clears the problem
9.1906 + void clear() { _clear(); }
9.1907
9.1908 ///@}
9.1909
9.1910 + };
9.1911 +
9.1912 + /// Addition
9.1913 +
9.1914 + ///\relates LpBase::Expr
9.1915 + ///
9.1916 + inline LpBase::Expr operator+(const LpBase::Expr &a, const LpBase::Expr &b) {
9.1917 + LpBase::Expr tmp(a);
9.1918 + tmp+=b;
9.1919 + return tmp;
9.1920 + }
9.1921 + ///Substraction
9.1922 +
9.1923 + ///\relates LpBase::Expr
9.1924 + ///
9.1925 + inline LpBase::Expr operator-(const LpBase::Expr &a, const LpBase::Expr &b) {
9.1926 + LpBase::Expr tmp(a);
9.1927 + tmp-=b;
9.1928 + return tmp;
9.1929 + }
9.1930 + ///Multiply with constant
9.1931 +
9.1932 + ///\relates LpBase::Expr
9.1933 + ///
9.1934 + inline LpBase::Expr operator*(const LpBase::Expr &a, const LpBase::Value &b) {
9.1935 + LpBase::Expr tmp(a);
9.1936 + tmp*=b;
9.1937 + return tmp;
9.1938 + }
9.1939 +
9.1940 + ///Multiply with constant
9.1941 +
9.1942 + ///\relates LpBase::Expr
9.1943 + ///
9.1944 + inline LpBase::Expr operator*(const LpBase::Value &a, const LpBase::Expr &b) {
9.1945 + LpBase::Expr tmp(b);
9.1946 + tmp*=a;
9.1947 + return tmp;
9.1948 + }
9.1949 + ///Divide with constant
9.1950 +
9.1951 + ///\relates LpBase::Expr
9.1952 + ///
9.1953 + inline LpBase::Expr operator/(const LpBase::Expr &a, const LpBase::Value &b) {
9.1954 + LpBase::Expr tmp(a);
9.1955 + tmp/=b;
9.1956 + return tmp;
9.1957 + }
9.1958 +
9.1959 + ///Create constraint
9.1960 +
9.1961 + ///\relates LpBase::Constr
9.1962 + ///
9.1963 + inline LpBase::Constr operator<=(const LpBase::Expr &e,
9.1964 + const LpBase::Expr &f) {
9.1965 + return LpBase::Constr(0, f - e, LpBase::INF);
9.1966 + }
9.1967 +
9.1968 + ///Create constraint
9.1969 +
9.1970 + ///\relates LpBase::Constr
9.1971 + ///
9.1972 + inline LpBase::Constr operator<=(const LpBase::Value &e,
9.1973 + const LpBase::Expr &f) {
9.1974 + return LpBase::Constr(e, f, LpBase::NaN);
9.1975 + }
9.1976 +
9.1977 + ///Create constraint
9.1978 +
9.1979 + ///\relates LpBase::Constr
9.1980 + ///
9.1981 + inline LpBase::Constr operator<=(const LpBase::Expr &e,
9.1982 + const LpBase::Value &f) {
9.1983 + return LpBase::Constr(- LpBase::INF, e, f);
9.1984 + }
9.1985 +
9.1986 + ///Create constraint
9.1987 +
9.1988 + ///\relates LpBase::Constr
9.1989 + ///
9.1990 + inline LpBase::Constr operator>=(const LpBase::Expr &e,
9.1991 + const LpBase::Expr &f) {
9.1992 + return LpBase::Constr(0, e - f, LpBase::INF);
9.1993 + }
9.1994 +
9.1995 +
9.1996 + ///Create constraint
9.1997 +
9.1998 + ///\relates LpBase::Constr
9.1999 + ///
9.2000 + inline LpBase::Constr operator>=(const LpBase::Value &e,
9.2001 + const LpBase::Expr &f) {
9.2002 + return LpBase::Constr(LpBase::NaN, f, e);
9.2003 + }
9.2004 +
9.2005 +
9.2006 + ///Create constraint
9.2007 +
9.2008 + ///\relates LpBase::Constr
9.2009 + ///
9.2010 + inline LpBase::Constr operator>=(const LpBase::Expr &e,
9.2011 + const LpBase::Value &f) {
9.2012 + return LpBase::Constr(f, e, LpBase::INF);
9.2013 + }
9.2014 +
9.2015 + ///Create constraint
9.2016 +
9.2017 + ///\relates LpBase::Constr
9.2018 + ///
9.2019 + inline LpBase::Constr operator==(const LpBase::Expr &e,
9.2020 + const LpBase::Value &f) {
9.2021 + return LpBase::Constr(f, e, f);
9.2022 + }
9.2023 +
9.2024 + ///Create constraint
9.2025 +
9.2026 + ///\relates LpBase::Constr
9.2027 + ///
9.2028 + inline LpBase::Constr operator==(const LpBase::Expr &e,
9.2029 + const LpBase::Expr &f) {
9.2030 + return LpBase::Constr(0, f - e, 0);
9.2031 + }
9.2032 +
9.2033 + ///Create constraint
9.2034 +
9.2035 + ///\relates LpBase::Constr
9.2036 + ///
9.2037 + inline LpBase::Constr operator<=(const LpBase::Value &n,
9.2038 + const LpBase::Constr &c) {
9.2039 + LpBase::Constr tmp(c);
9.2040 + LEMON_ASSERT(std::isnan(tmp.lowerBound()), "Wrong LP constraint");
9.2041 + tmp.lowerBound()=n;
9.2042 + return tmp;
9.2043 + }
9.2044 + ///Create constraint
9.2045 +
9.2046 + ///\relates LpBase::Constr
9.2047 + ///
9.2048 + inline LpBase::Constr operator<=(const LpBase::Constr &c,
9.2049 + const LpBase::Value &n)
9.2050 + {
9.2051 + LpBase::Constr tmp(c);
9.2052 + LEMON_ASSERT(std::isnan(tmp.upperBound()), "Wrong LP constraint");
9.2053 + tmp.upperBound()=n;
9.2054 + return tmp;
9.2055 + }
9.2056 +
9.2057 + ///Create constraint
9.2058 +
9.2059 + ///\relates LpBase::Constr
9.2060 + ///
9.2061 + inline LpBase::Constr operator>=(const LpBase::Value &n,
9.2062 + const LpBase::Constr &c) {
9.2063 + LpBase::Constr tmp(c);
9.2064 + LEMON_ASSERT(std::isnan(tmp.upperBound()), "Wrong LP constraint");
9.2065 + tmp.upperBound()=n;
9.2066 + return tmp;
9.2067 + }
9.2068 + ///Create constraint
9.2069 +
9.2070 + ///\relates LpBase::Constr
9.2071 + ///
9.2072 + inline LpBase::Constr operator>=(const LpBase::Constr &c,
9.2073 + const LpBase::Value &n)
9.2074 + {
9.2075 + LpBase::Constr tmp(c);
9.2076 + LEMON_ASSERT(std::isnan(tmp.lowerBound()), "Wrong LP constraint");
9.2077 + tmp.lowerBound()=n;
9.2078 + return tmp;
9.2079 + }
9.2080 +
9.2081 + ///Addition
9.2082 +
9.2083 + ///\relates LpBase::DualExpr
9.2084 + ///
9.2085 + inline LpBase::DualExpr operator+(const LpBase::DualExpr &a,
9.2086 + const LpBase::DualExpr &b) {
9.2087 + LpBase::DualExpr tmp(a);
9.2088 + tmp+=b;
9.2089 + return tmp;
9.2090 + }
9.2091 + ///Substraction
9.2092 +
9.2093 + ///\relates LpBase::DualExpr
9.2094 + ///
9.2095 + inline LpBase::DualExpr operator-(const LpBase::DualExpr &a,
9.2096 + const LpBase::DualExpr &b) {
9.2097 + LpBase::DualExpr tmp(a);
9.2098 + tmp-=b;
9.2099 + return tmp;
9.2100 + }
9.2101 + ///Multiply with constant
9.2102 +
9.2103 + ///\relates LpBase::DualExpr
9.2104 + ///
9.2105 + inline LpBase::DualExpr operator*(const LpBase::DualExpr &a,
9.2106 + const LpBase::Value &b) {
9.2107 + LpBase::DualExpr tmp(a);
9.2108 + tmp*=b;
9.2109 + return tmp;
9.2110 + }
9.2111 +
9.2112 + ///Multiply with constant
9.2113 +
9.2114 + ///\relates LpBase::DualExpr
9.2115 + ///
9.2116 + inline LpBase::DualExpr operator*(const LpBase::Value &a,
9.2117 + const LpBase::DualExpr &b) {
9.2118 + LpBase::DualExpr tmp(b);
9.2119 + tmp*=a;
9.2120 + return tmp;
9.2121 + }
9.2122 + ///Divide with constant
9.2123 +
9.2124 + ///\relates LpBase::DualExpr
9.2125 + ///
9.2126 + inline LpBase::DualExpr operator/(const LpBase::DualExpr &a,
9.2127 + const LpBase::Value &b) {
9.2128 + LpBase::DualExpr tmp(a);
9.2129 + tmp/=b;
9.2130 + return tmp;
9.2131 + }
9.2132 +
9.2133 + /// \ingroup lp_group
9.2134 + ///
9.2135 + /// \brief Common base class for LP solvers
9.2136 + ///
9.2137 + /// This class is an abstract base class for LP solvers. This class
9.2138 + /// provides a full interface for set and modify an LP problem,
9.2139 + /// solve it and retrieve the solution. You can use one of the
9.2140 + /// descendants as a concrete implementation, or the \c Lp
9.2141 + /// default LP solver. However, if you would like to handle LP
9.2142 + /// solvers as reference or pointer in a generic way, you can use
9.2143 + /// this class directly.
9.2144 + class LpSolver : virtual public LpBase {
9.2145 + public:
9.2146 +
9.2147 + /// The problem types for primal and dual problems
9.2148 + enum ProblemType {
9.2149 + ///Feasible solution hasn't been found (but may exist).
9.2150 + UNDEFINED = 0,
9.2151 + ///The problem has no feasible solution
9.2152 + INFEASIBLE = 1,
9.2153 + ///Feasible solution found
9.2154 + FEASIBLE = 2,
9.2155 + ///Optimal solution exists and found
9.2156 + OPTIMAL = 3,
9.2157 + ///The cost function is unbounded
9.2158 + UNBOUNDED = 4
9.2159 + };
9.2160 +
9.2161 + ///The basis status of variables
9.2162 + enum VarStatus {
9.2163 + /// The variable is in the basis
9.2164 + BASIC,
9.2165 + /// The variable is free, but not basic
9.2166 + FREE,
9.2167 + /// The variable has active lower bound
9.2168 + LOWER,
9.2169 + /// The variable has active upper bound
9.2170 + UPPER,
9.2171 + /// The variable is non-basic and fixed
9.2172 + FIXED
9.2173 + };
9.2174 +
9.2175 + protected:
9.2176 +
9.2177 + virtual SolveExitStatus _solve() = 0;
9.2178 +
9.2179 + virtual Value _getPrimal(int i) const = 0;
9.2180 + virtual Value _getDual(int i) const = 0;
9.2181 +
9.2182 + virtual Value _getPrimalRay(int i) const = 0;
9.2183 + virtual Value _getDualRay(int i) const = 0;
9.2184 +
9.2185 + virtual Value _getPrimalValue() const = 0;
9.2186 +
9.2187 + virtual VarStatus _getColStatus(int i) const = 0;
9.2188 + virtual VarStatus _getRowStatus(int i) const = 0;
9.2189 +
9.2190 + virtual ProblemType _getPrimalType() const = 0;
9.2191 + virtual ProblemType _getDualType() const = 0;
9.2192 +
9.2193 + public:
9.2194
9.2195 ///\name Solve the LP
9.2196
9.2197 @@ -1326,8 +1830,6 @@
9.2198 ///\return The result of the optimization procedure. Possible
9.2199 ///values and their meanings can be found in the documentation of
9.2200 ///\ref SolveExitStatus.
9.2201 - ///
9.2202 - ///\todo Which method is used to solve the problem
9.2203 SolveExitStatus solve() { return _solve(); }
9.2204
9.2205 ///@}
9.2206 @@ -1336,368 +1838,241 @@
9.2207
9.2208 ///@{
9.2209
9.2210 - /// The status of the primal problem (the original LP problem)
9.2211 - SolutionStatus primalStatus() const {
9.2212 - return _getPrimalStatus();
9.2213 + /// The type of the primal problem
9.2214 + ProblemType primalType() const {
9.2215 + return _getPrimalType();
9.2216 }
9.2217
9.2218 - /// The status of the dual (of the original LP) problem
9.2219 - SolutionStatus dualStatus() const {
9.2220 - return _getDualStatus();
9.2221 + /// The type of the dual problem
9.2222 + ProblemType dualType() const {
9.2223 + return _getDualType();
9.2224 }
9.2225
9.2226 - ///The type of the original LP problem
9.2227 - ProblemTypes problemType() const {
9.2228 - return _getProblemType();
9.2229 + /// Return the primal value of the column
9.2230 +
9.2231 + /// Return the primal value of the column.
9.2232 + /// \pre The problem is solved.
9.2233 + Value primal(Col c) const { return _getPrimal(cols(id(c))); }
9.2234 +
9.2235 + /// Return the primal value of the expression
9.2236 +
9.2237 + /// Return the primal value of the expression, i.e. the dot
9.2238 + /// product of the primal solution and the expression.
9.2239 + /// \pre The problem is solved.
9.2240 + Value primal(const Expr& e) const {
9.2241 + double res = *e;
9.2242 + for (Expr::ConstCoeffIt c(e); c != INVALID; ++c) {
9.2243 + res += *c * primal(c);
9.2244 + }
9.2245 + return res;
9.2246 }
9.2247 + /// Returns a component of the primal ray
9.2248 +
9.2249 + /// The primal ray is solution of the modified primal problem,
9.2250 + /// where we change each finite bound to 0, and we looking for a
9.2251 + /// negative objective value in case of minimization, and positive
9.2252 + /// objective value for maximization. If there is such solution,
9.2253 + /// that proofs the unsolvability of the dual problem, and if a
9.2254 + /// feasible primal solution exists, then the unboundness of
9.2255 + /// primal problem.
9.2256 + ///
9.2257 + /// \pre The problem is solved and the dual problem is infeasible.
9.2258 + /// \note Some solvers does not provide primal ray calculation
9.2259 + /// functions.
9.2260 + Value primalRay(Col c) const { return _getPrimalRay(cols(id(c))); }
9.2261
9.2262 - ///\e
9.2263 - Value primal(Col c) const { return _getPrimal(_lpId(c)); }
9.2264 - ///\e
9.2265 - Value primal(const Expr& e) const {
9.2266 - double res = e.constComp();
9.2267 - for (std::map<Col, double>::const_iterator it = e.begin();
9.2268 - it != e.end(); ++it) {
9.2269 - res += _getPrimal(_lpId(it->first)) * it->second;
9.2270 + /// Return the dual value of the row
9.2271 +
9.2272 + /// Return the dual value of the row.
9.2273 + /// \pre The problem is solved.
9.2274 + Value dual(Row r) const { return _getDual(rows(id(r))); }
9.2275 +
9.2276 + /// Return the dual value of the dual expression
9.2277 +
9.2278 + /// Return the dual value of the dual expression, i.e. the dot
9.2279 + /// product of the dual solution and the dual expression.
9.2280 + /// \pre The problem is solved.
9.2281 + Value dual(const DualExpr& e) const {
9.2282 + double res = 0.0;
9.2283 + for (DualExpr::ConstCoeffIt r(e); r != INVALID; ++r) {
9.2284 + res += *r * dual(r);
9.2285 }
9.2286 return res;
9.2287 }
9.2288
9.2289 - ///\e
9.2290 - Value dual(Row r) const { return _getDual(_lpId(r)); }
9.2291 - ///\e
9.2292 - Value dual(const DualExpr& e) const {
9.2293 - double res = 0.0;
9.2294 - for (std::map<Row, double>::const_iterator it = e.begin();
9.2295 - it != e.end(); ++it) {
9.2296 - res += _getPrimal(_lpId(it->first)) * it->second;
9.2297 - }
9.2298 - return res;
9.2299 - }
9.2300 + /// Returns a component of the dual ray
9.2301 +
9.2302 + /// The dual ray is solution of the modified primal problem, where
9.2303 + /// we change each finite bound to 0 (i.e. the objective function
9.2304 + /// coefficients in the primal problem), and we looking for a
9.2305 + /// ositive objective value. If there is such solution, that
9.2306 + /// proofs the unsolvability of the primal problem, and if a
9.2307 + /// feasible dual solution exists, then the unboundness of
9.2308 + /// dual problem.
9.2309 + ///
9.2310 + /// \pre The problem is solved and the primal problem is infeasible.
9.2311 + /// \note Some solvers does not provide dual ray calculation
9.2312 + /// functions.
9.2313 + Value dualRay(Row r) const { return _getDualRay(rows(id(r))); }
9.2314
9.2315 - ///\e
9.2316 - bool isBasicCol(Col c) const { return _isBasicCol(_lpId(c)); }
9.2317 + /// Return the basis status of the column
9.2318
9.2319 - ///\e
9.2320 + /// \see VarStatus
9.2321 + VarStatus colStatus(Col c) const { return _getColStatus(cols(id(c))); }
9.2322 +
9.2323 + /// Return the basis status of the row
9.2324 +
9.2325 + /// \see VarStatus
9.2326 + VarStatus rowStatus(Row r) const { return _getRowStatus(rows(id(r))); }
9.2327 +
9.2328 + ///The value of the objective function
9.2329
9.2330 ///\return
9.2331 ///- \ref INF or -\ref INF means either infeasibility or unboundedness
9.2332 /// of the primal problem, depending on whether we minimize or maximize.
9.2333 ///- \ref NaN if no primal solution is found.
9.2334 ///- The (finite) objective value if an optimal solution is found.
9.2335 - Value primalValue() const { return _getPrimalValue()+obj_const_comp;}
9.2336 + Value primal() const { return _getPrimalValue()+obj_const_comp;}
9.2337 ///@}
9.2338
9.2339 + LpSolver* newSolver() {return _newSolver();}
9.2340 + LpSolver* cloneSolver() {return _cloneSolver();}
9.2341 +
9.2342 + protected:
9.2343 +
9.2344 + virtual LpSolver* _newSolver() const = 0;
9.2345 + virtual LpSolver* _cloneSolver() const = 0;
9.2346 };
9.2347
9.2348
9.2349 /// \ingroup lp_group
9.2350 ///
9.2351 /// \brief Common base class for MIP solvers
9.2352 - /// \todo Much more docs
9.2353 - class MipSolverBase : virtual public LpSolverBase{
9.2354 + ///
9.2355 + /// This class is an abstract base class for MIP solvers. This class
9.2356 + /// provides a full interface for set and modify an MIP problem,
9.2357 + /// solve it and retrieve the solution. You can use one of the
9.2358 + /// descendants as a concrete implementation, or the \c Lp
9.2359 + /// default MIP solver. However, if you would like to handle MIP
9.2360 + /// solvers as reference or pointer in a generic way, you can use
9.2361 + /// this class directly.
9.2362 + class MipSolver : virtual public LpBase {
9.2363 public:
9.2364
9.2365 - ///Possible variable (coloumn) types (e.g. real, integer, binary etc.)
9.2366 + /// The problem types for MIP problems
9.2367 + enum ProblemType {
9.2368 + ///Feasible solution hasn't been found (but may exist).
9.2369 + UNDEFINED = 0,
9.2370 + ///The problem has no feasible solution
9.2371 + INFEASIBLE = 1,
9.2372 + ///Feasible solution found
9.2373 + FEASIBLE = 2,
9.2374 + ///Optimal solution exists and found
9.2375 + OPTIMAL = 3,
9.2376 + ///The cost function is unbounded
9.2377 + ///
9.2378 + ///The Mip or at least the relaxed problem is unbounded
9.2379 + UNBOUNDED = 4
9.2380 + };
9.2381 +
9.2382 + ///\name Solve the MIP
9.2383 +
9.2384 + ///@{
9.2385 +
9.2386 + /// Solve the MIP problem at hand
9.2387 + ///
9.2388 + ///\return The result of the optimization procedure. Possible
9.2389 + ///values and their meanings can be found in the documentation of
9.2390 + ///\ref SolveExitStatus.
9.2391 + SolveExitStatus solve() { return _solve(); }
9.2392 +
9.2393 + ///@}
9.2394 +
9.2395 + ///\name Setting column type
9.2396 + ///@{
9.2397 +
9.2398 + ///Possible variable (column) types (e.g. real, integer, binary etc.)
9.2399 enum ColTypes {
9.2400 - ///Continuous variable
9.2401 + ///Continuous variable (default)
9.2402 REAL = 0,
9.2403 ///Integer variable
9.2404 -
9.2405 - ///Unfortunately, cplex 7.5 somewhere writes something like
9.2406 - ///#define INTEGER 'I'
9.2407 - INT = 1
9.2408 - ///\todo No support for other types yet.
9.2409 + INTEGER = 1
9.2410 };
9.2411
9.2412 - ///Sets the type of the given coloumn to the given type
9.2413 + ///Sets the type of the given column to the given type
9.2414 +
9.2415 + ///Sets the type of the given column to the given type.
9.2416 ///
9.2417 - ///Sets the type of the given coloumn to the given type.
9.2418 void colType(Col c, ColTypes col_type) {
9.2419 - _colType(_lpId(c),col_type);
9.2420 + _setColType(cols(id(c)),col_type);
9.2421 }
9.2422
9.2423 ///Gives back the type of the column.
9.2424 +
9.2425 + ///Gives back the type of the column.
9.2426 ///
9.2427 - ///Gives back the type of the column.
9.2428 ColTypes colType(Col c) const {
9.2429 - return _colType(_lpId(c));
9.2430 + return _getColType(cols(id(c)));
9.2431 + }
9.2432 + ///@}
9.2433 +
9.2434 + ///\name Obtain the solution
9.2435 +
9.2436 + ///@{
9.2437 +
9.2438 + /// The type of the MIP problem
9.2439 + ProblemType type() const {
9.2440 + return _getType();
9.2441 }
9.2442
9.2443 - ///Sets the type of the given Col to integer or remove that property.
9.2444 - ///
9.2445 - ///Sets the type of the given Col to integer or remove that property.
9.2446 - void integer(Col c, bool enable) {
9.2447 - if (enable)
9.2448 - colType(c,INT);
9.2449 - else
9.2450 - colType(c,REAL);
9.2451 + /// Return the value of the row in the solution
9.2452 +
9.2453 + /// Return the value of the row in the solution.
9.2454 + /// \pre The problem is solved.
9.2455 + Value sol(Col c) const { return _getSol(cols(id(c))); }
9.2456 +
9.2457 + /// Return the value of the expression in the solution
9.2458 +
9.2459 + /// Return the value of the expression in the solution, i.e. the
9.2460 + /// dot product of the solution and the expression.
9.2461 + /// \pre The problem is solved.
9.2462 + Value sol(const Expr& e) const {
9.2463 + double res = *e;
9.2464 + for (Expr::ConstCoeffIt c(e); c != INVALID; ++c) {
9.2465 + res += *c * sol(c);
9.2466 + }
9.2467 + return res;
9.2468 }
9.2469 -
9.2470 - ///Gives back whether the type of the column is integer or not.
9.2471 - ///
9.2472 - ///Gives back the type of the column.
9.2473 - ///\return true if the column has integer type and false if not.
9.2474 - bool integer(Col c) const {
9.2475 - return (colType(c)==INT);
9.2476 - }
9.2477 -
9.2478 - /// The status of the MIP problem
9.2479 - SolutionStatus mipStatus() const {
9.2480 - return _getMipStatus();
9.2481 - }
9.2482 + ///The value of the objective function
9.2483 +
9.2484 + ///\return
9.2485 + ///- \ref INF or -\ref INF means either infeasibility or unboundedness
9.2486 + /// of the problem, depending on whether we minimize or maximize.
9.2487 + ///- \ref NaN if no primal solution is found.
9.2488 + ///- The (finite) objective value if an optimal solution is found.
9.2489 + Value solValue() const { return _getSolValue()+obj_const_comp;}
9.2490 + ///@}
9.2491
9.2492 protected:
9.2493
9.2494 - virtual ColTypes _colType(int col) const = 0;
9.2495 - virtual void _colType(int col, ColTypes col_type) = 0;
9.2496 - virtual SolutionStatus _getMipStatus() const = 0;
9.2497 + virtual SolveExitStatus _solve() = 0;
9.2498 + virtual ColTypes _getColType(int col) const = 0;
9.2499 + virtual void _setColType(int col, ColTypes col_type) = 0;
9.2500 + virtual ProblemType _getType() const = 0;
9.2501 + virtual Value _getSol(int i) const = 0;
9.2502 + virtual Value _getSolValue() const = 0;
9.2503
9.2504 + public:
9.2505 +
9.2506 + MipSolver* newSolver() {return _newSolver();}
9.2507 + MipSolver* cloneSolver() {return _cloneSolver();}
9.2508 +
9.2509 + protected:
9.2510 +
9.2511 + virtual MipSolver* _newSolver() const = 0;
9.2512 + virtual MipSolver* _cloneSolver() const = 0;
9.2513 };
9.2514
9.2515 - ///\relates LpSolverBase::Expr
9.2516 - ///
9.2517 - inline LpSolverBase::Expr operator+(const LpSolverBase::Expr &a,
9.2518 - const LpSolverBase::Expr &b)
9.2519 - {
9.2520 - LpSolverBase::Expr tmp(a);
9.2521 - tmp+=b;
9.2522 - return tmp;
9.2523 - }
9.2524 - ///\e
9.2525 -
9.2526 - ///\relates LpSolverBase::Expr
9.2527 - ///
9.2528 - inline LpSolverBase::Expr operator-(const LpSolverBase::Expr &a,
9.2529 - const LpSolverBase::Expr &b)
9.2530 - {
9.2531 - LpSolverBase::Expr tmp(a);
9.2532 - tmp-=b;
9.2533 - return tmp;
9.2534 - }
9.2535 - ///\e
9.2536 -
9.2537 - ///\relates LpSolverBase::Expr
9.2538 - ///
9.2539 - inline LpSolverBase::Expr operator*(const LpSolverBase::Expr &a,
9.2540 - const LpSolverBase::Value &b)
9.2541 - {
9.2542 - LpSolverBase::Expr tmp(a);
9.2543 - tmp*=b;
9.2544 - return tmp;
9.2545 - }
9.2546 -
9.2547 - ///\e
9.2548 -
9.2549 - ///\relates LpSolverBase::Expr
9.2550 - ///
9.2551 - inline LpSolverBase::Expr operator*(const LpSolverBase::Value &a,
9.2552 - const LpSolverBase::Expr &b)
9.2553 - {
9.2554 - LpSolverBase::Expr tmp(b);
9.2555 - tmp*=a;
9.2556 - return tmp;
9.2557 - }
9.2558 - ///\e
9.2559 -
9.2560 - ///\relates LpSolverBase::Expr
9.2561 - ///
9.2562 - inline LpSolverBase::Expr operator/(const LpSolverBase::Expr &a,
9.2563 - const LpSolverBase::Value &b)
9.2564 - {
9.2565 - LpSolverBase::Expr tmp(a);
9.2566 - tmp/=b;
9.2567 - return tmp;
9.2568 - }
9.2569 -
9.2570 - ///\e
9.2571 -
9.2572 - ///\relates LpSolverBase::Constr
9.2573 - ///
9.2574 - inline LpSolverBase::Constr operator<=(const LpSolverBase::Expr &e,
9.2575 - const LpSolverBase::Expr &f)
9.2576 - {
9.2577 - return LpSolverBase::Constr(-LpSolverBase::INF,e-f,0);
9.2578 - }
9.2579 -
9.2580 - ///\e
9.2581 -
9.2582 - ///\relates LpSolverBase::Constr
9.2583 - ///
9.2584 - inline LpSolverBase::Constr operator<=(const LpSolverBase::Value &e,
9.2585 - const LpSolverBase::Expr &f)
9.2586 - {
9.2587 - return LpSolverBase::Constr(e,f);
9.2588 - }
9.2589 -
9.2590 - ///\e
9.2591 -
9.2592 - ///\relates LpSolverBase::Constr
9.2593 - ///
9.2594 - inline LpSolverBase::Constr operator<=(const LpSolverBase::Expr &e,
9.2595 - const LpSolverBase::Value &f)
9.2596 - {
9.2597 - return LpSolverBase::Constr(-LpSolverBase::INF,e,f);
9.2598 - }
9.2599 -
9.2600 - ///\e
9.2601 -
9.2602 - ///\relates LpSolverBase::Constr
9.2603 - ///
9.2604 - inline LpSolverBase::Constr operator>=(const LpSolverBase::Expr &e,
9.2605 - const LpSolverBase::Expr &f)
9.2606 - {
9.2607 - return LpSolverBase::Constr(-LpSolverBase::INF,f-e,0);
9.2608 - }
9.2609 -
9.2610 -
9.2611 - ///\e
9.2612 -
9.2613 - ///\relates LpSolverBase::Constr
9.2614 - ///
9.2615 - inline LpSolverBase::Constr operator>=(const LpSolverBase::Value &e,
9.2616 - const LpSolverBase::Expr &f)
9.2617 - {
9.2618 - return LpSolverBase::Constr(f,e);
9.2619 - }
9.2620 -
9.2621 -
9.2622 - ///\e
9.2623 -
9.2624 - ///\relates LpSolverBase::Constr
9.2625 - ///
9.2626 - inline LpSolverBase::Constr operator>=(const LpSolverBase::Expr &e,
9.2627 - const LpSolverBase::Value &f)
9.2628 - {
9.2629 - return LpSolverBase::Constr(f,e,LpSolverBase::INF);
9.2630 - }
9.2631 -
9.2632 - ///\e
9.2633 -
9.2634 - ///\relates LpSolverBase::Constr
9.2635 - ///
9.2636 - inline LpSolverBase::Constr operator==(const LpSolverBase::Expr &e,
9.2637 - const LpSolverBase::Value &f)
9.2638 - {
9.2639 - return LpSolverBase::Constr(f,e,f);
9.2640 - }
9.2641 -
9.2642 - ///\e
9.2643 -
9.2644 - ///\relates LpSolverBase::Constr
9.2645 - ///
9.2646 - inline LpSolverBase::Constr operator==(const LpSolverBase::Expr &e,
9.2647 - const LpSolverBase::Expr &f)
9.2648 - {
9.2649 - return LpSolverBase::Constr(0,e-f,0);
9.2650 - }
9.2651 -
9.2652 - ///\e
9.2653 -
9.2654 - ///\relates LpSolverBase::Constr
9.2655 - ///
9.2656 - inline LpSolverBase::Constr operator<=(const LpSolverBase::Value &n,
9.2657 - const LpSolverBase::Constr&c)
9.2658 - {
9.2659 - LpSolverBase::Constr tmp(c);
9.2660 - LEMON_ASSERT(LpSolverBase::isNaN(tmp.lowerBound()), "Wrong LP constraint");
9.2661 - tmp.lowerBound()=n;
9.2662 - return tmp;
9.2663 - }
9.2664 - ///\e
9.2665 -
9.2666 - ///\relates LpSolverBase::Constr
9.2667 - ///
9.2668 - inline LpSolverBase::Constr operator<=(const LpSolverBase::Constr& c,
9.2669 - const LpSolverBase::Value &n)
9.2670 - {
9.2671 - LpSolverBase::Constr tmp(c);
9.2672 - LEMON_ASSERT(LpSolverBase::isNaN(tmp.upperBound()), "Wrong LP constraint");
9.2673 - tmp.upperBound()=n;
9.2674 - return tmp;
9.2675 - }
9.2676 -
9.2677 - ///\e
9.2678 -
9.2679 - ///\relates LpSolverBase::Constr
9.2680 - ///
9.2681 - inline LpSolverBase::Constr operator>=(const LpSolverBase::Value &n,
9.2682 - const LpSolverBase::Constr&c)
9.2683 - {
9.2684 - LpSolverBase::Constr tmp(c);
9.2685 - LEMON_ASSERT(LpSolverBase::isNaN(tmp.upperBound()), "Wrong LP constraint");
9.2686 - tmp.upperBound()=n;
9.2687 - return tmp;
9.2688 - }
9.2689 - ///\e
9.2690 -
9.2691 - ///\relates LpSolverBase::Constr
9.2692 - ///
9.2693 - inline LpSolverBase::Constr operator>=(const LpSolverBase::Constr& c,
9.2694 - const LpSolverBase::Value &n)
9.2695 - {
9.2696 - LpSolverBase::Constr tmp(c);
9.2697 - LEMON_ASSERT(LpSolverBase::isNaN(tmp.lowerBound()), "Wrong LP constraint");
9.2698 - tmp.lowerBound()=n;
9.2699 - return tmp;
9.2700 - }
9.2701 -
9.2702 - ///\e
9.2703 -
9.2704 - ///\relates LpSolverBase::DualExpr
9.2705 - ///
9.2706 - inline LpSolverBase::DualExpr operator+(const LpSolverBase::DualExpr &a,
9.2707 - const LpSolverBase::DualExpr &b)
9.2708 - {
9.2709 - LpSolverBase::DualExpr tmp(a);
9.2710 - tmp+=b;
9.2711 - return tmp;
9.2712 - }
9.2713 - ///\e
9.2714 -
9.2715 - ///\relates LpSolverBase::DualExpr
9.2716 - ///
9.2717 - inline LpSolverBase::DualExpr operator-(const LpSolverBase::DualExpr &a,
9.2718 - const LpSolverBase::DualExpr &b)
9.2719 - {
9.2720 - LpSolverBase::DualExpr tmp(a);
9.2721 - tmp-=b;
9.2722 - return tmp;
9.2723 - }
9.2724 - ///\e
9.2725 -
9.2726 - ///\relates LpSolverBase::DualExpr
9.2727 - ///
9.2728 - inline LpSolverBase::DualExpr operator*(const LpSolverBase::DualExpr &a,
9.2729 - const LpSolverBase::Value &b)
9.2730 - {
9.2731 - LpSolverBase::DualExpr tmp(a);
9.2732 - tmp*=b;
9.2733 - return tmp;
9.2734 - }
9.2735 -
9.2736 - ///\e
9.2737 -
9.2738 - ///\relates LpSolverBase::DualExpr
9.2739 - ///
9.2740 - inline LpSolverBase::DualExpr operator*(const LpSolverBase::Value &a,
9.2741 - const LpSolverBase::DualExpr &b)
9.2742 - {
9.2743 - LpSolverBase::DualExpr tmp(b);
9.2744 - tmp*=a;
9.2745 - return tmp;
9.2746 - }
9.2747 - ///\e
9.2748 -
9.2749 - ///\relates LpSolverBase::DualExpr
9.2750 - ///
9.2751 - inline LpSolverBase::DualExpr operator/(const LpSolverBase::DualExpr &a,
9.2752 - const LpSolverBase::Value &b)
9.2753 - {
9.2754 - LpSolverBase::DualExpr tmp(a);
9.2755 - tmp/=b;
9.2756 - return tmp;
9.2757 - }
9.2758
9.2759
9.2760 } //namespace lemon
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
10.2 +++ b/lemon/lp_clp.cc Tue Dec 02 22:48:28 2008 +0100
10.3 @@ -0,0 +1,437 @@
10.4 +/* -*- mode: C++; indent-tabs-mode: nil; -*-
10.5 + *
10.6 + * This file is a part of LEMON, a generic C++ optimization library.
10.7 + *
10.8 + * Copyright (C) 2003-2008
10.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
10.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
10.11 + *
10.12 + * Permission to use, modify and distribute this software is granted
10.13 + * provided that this copyright notice appears in all copies. For
10.14 + * precise terms see the accompanying LICENSE file.
10.15 + *
10.16 + * This software is provided "AS IS" with no warranty of any kind,
10.17 + * express or implied, and with no claim as to its suitability for any
10.18 + * purpose.
10.19 + *
10.20 + */
10.21 +
10.22 +#include <lemon/lp_clp.h>
10.23 +#include <coin/ClpSimplex.hpp>
10.24 +
10.25 +namespace lemon {
10.26 +
10.27 + LpClp::LpClp() {
10.28 + _prob = new ClpSimplex();
10.29 + _init_temporals();
10.30 + messageLevel(MESSAGE_NO_OUTPUT);
10.31 + }
10.32 +
10.33 + LpClp::LpClp(const LpClp& other) {
10.34 + _prob = new ClpSimplex(*other._prob);
10.35 + rows = other.rows;
10.36 + cols = other.cols;
10.37 + _init_temporals();
10.38 + messageLevel(MESSAGE_NO_OUTPUT);
10.39 + }
10.40 +
10.41 + LpClp::~LpClp() {
10.42 + delete _prob;
10.43 + _clear_temporals();
10.44 + }
10.45 +
10.46 + void LpClp::_init_temporals() {
10.47 + _primal_ray = 0;
10.48 + _dual_ray = 0;
10.49 + }
10.50 +
10.51 + void LpClp::_clear_temporals() {
10.52 + if (_primal_ray) {
10.53 + delete[] _primal_ray;
10.54 + _primal_ray = 0;
10.55 + }
10.56 + if (_dual_ray) {
10.57 + delete[] _dual_ray;
10.58 + _dual_ray = 0;
10.59 + }
10.60 + }
10.61 +
10.62 + LpClp* LpClp::_newSolver() const {
10.63 + LpClp* newlp = new LpClp;
10.64 + return newlp;
10.65 + }
10.66 +
10.67 + LpClp* LpClp::_cloneSolver() const {
10.68 + LpClp* copylp = new LpClp(*this);
10.69 + return copylp;
10.70 + }
10.71 +
10.72 + const char* LpClp::_solverName() const { return "LpClp"; }
10.73 +
10.74 + int LpClp::_addCol() {
10.75 + _prob->addColumn(0, 0, 0, -COIN_DBL_MAX, COIN_DBL_MAX, 0.0);
10.76 + return _prob->numberColumns() - 1;
10.77 + }
10.78 +
10.79 + int LpClp::_addRow() {
10.80 + _prob->addRow(0, 0, 0, -COIN_DBL_MAX, COIN_DBL_MAX);
10.81 + return _prob->numberRows() - 1;
10.82 + }
10.83 +
10.84 +
10.85 + void LpClp::_eraseCol(int c) {
10.86 + _col_names_ref.erase(_prob->getColumnName(c));
10.87 + _prob->deleteColumns(1, &c);
10.88 + }
10.89 +
10.90 + void LpClp::_eraseRow(int r) {
10.91 + _row_names_ref.erase(_prob->getRowName(r));
10.92 + _prob->deleteRows(1, &r);
10.93 + }
10.94 +
10.95 + void LpClp::_eraseColId(int i) {
10.96 + cols.eraseIndex(i);
10.97 + cols.shiftIndices(i);
10.98 + }
10.99 +
10.100 + void LpClp::_eraseRowId(int i) {
10.101 + rows.eraseIndex(i);
10.102 + rows.shiftIndices(i);
10.103 + }
10.104 +
10.105 + void LpClp::_getColName(int c, std::string& name) const {
10.106 + name = _prob->getColumnName(c);
10.107 + }
10.108 +
10.109 + void LpClp::_setColName(int c, const std::string& name) {
10.110 + _prob->setColumnName(c, const_cast<std::string&>(name));
10.111 + _col_names_ref[name] = c;
10.112 + }
10.113 +
10.114 + int LpClp::_colByName(const std::string& name) const {
10.115 + std::map<std::string, int>::const_iterator it = _col_names_ref.find(name);
10.116 + return it != _col_names_ref.end() ? it->second : -1;
10.117 + }
10.118 +
10.119 + void LpClp::_getRowName(int r, std::string& name) const {
10.120 + name = _prob->getRowName(r);
10.121 + }
10.122 +
10.123 + void LpClp::_setRowName(int r, const std::string& name) {
10.124 + _prob->setRowName(r, const_cast<std::string&>(name));
10.125 + _row_names_ref[name] = r;
10.126 + }
10.127 +
10.128 + int LpClp::_rowByName(const std::string& name) const {
10.129 + std::map<std::string, int>::const_iterator it = _row_names_ref.find(name);
10.130 + return it != _row_names_ref.end() ? it->second : -1;
10.131 + }
10.132 +
10.133 +
10.134 + void LpClp::_setRowCoeffs(int ix, ExprIterator b, ExprIterator e) {
10.135 + std::map<int, Value> coeffs;
10.136 +
10.137 + int n = _prob->clpMatrix()->getNumCols();
10.138 +
10.139 + const int* indices = _prob->clpMatrix()->getIndices();
10.140 + const double* elements = _prob->clpMatrix()->getElements();
10.141 +
10.142 + for (int i = 0; i < n; ++i) {
10.143 + CoinBigIndex begin = _prob->clpMatrix()->getVectorStarts()[i];
10.144 + CoinBigIndex end = begin + _prob->clpMatrix()->getVectorLengths()[i];
10.145 +
10.146 + const int* it = std::lower_bound(indices + begin, indices + end, ix);
10.147 + if (it != indices + end && *it == ix && elements[it - indices] != 0.0) {
10.148 + coeffs[i] = 0.0;
10.149 + }
10.150 + }
10.151 +
10.152 + for (ExprIterator it = b; it != e; ++it) {
10.153 + coeffs[it->first] = it->second;
10.154 + }
10.155 +
10.156 + for (std::map<int, Value>::iterator it = coeffs.begin();
10.157 + it != coeffs.end(); ++it) {
10.158 + _prob->modifyCoefficient(ix, it->first, it->second);
10.159 + }
10.160 + }
10.161 +
10.162 + void LpClp::_getRowCoeffs(int ix, InsertIterator b) const {
10.163 + int n = _prob->clpMatrix()->getNumCols();
10.164 +
10.165 + const int* indices = _prob->clpMatrix()->getIndices();
10.166 + const double* elements = _prob->clpMatrix()->getElements();
10.167 +
10.168 + for (int i = 0; i < n; ++i) {
10.169 + CoinBigIndex begin = _prob->clpMatrix()->getVectorStarts()[i];
10.170 + CoinBigIndex end = begin + _prob->clpMatrix()->getVectorLengths()[i];
10.171 +
10.172 + const int* it = std::lower_bound(indices + begin, indices + end, ix);
10.173 + if (it != indices + end && *it == ix) {
10.174 + *b = std::make_pair(i, elements[it - indices]);
10.175 + }
10.176 + }
10.177 + }
10.178 +
10.179 + void LpClp::_setColCoeffs(int ix, ExprIterator b, ExprIterator e) {
10.180 + std::map<int, Value> coeffs;
10.181 +
10.182 + CoinBigIndex begin = _prob->clpMatrix()->getVectorStarts()[ix];
10.183 + CoinBigIndex end = begin + _prob->clpMatrix()->getVectorLengths()[ix];
10.184 +
10.185 + const int* indices = _prob->clpMatrix()->getIndices();
10.186 + const double* elements = _prob->clpMatrix()->getElements();
10.187 +
10.188 + for (CoinBigIndex i = begin; i != end; ++i) {
10.189 + if (elements[i] != 0.0) {
10.190 + coeffs[indices[i]] = 0.0;
10.191 + }
10.192 + }
10.193 + for (ExprIterator it = b; it != e; ++it) {
10.194 + coeffs[it->first] = it->second;
10.195 + }
10.196 + for (std::map<int, Value>::iterator it = coeffs.begin();
10.197 + it != coeffs.end(); ++it) {
10.198 + _prob->modifyCoefficient(it->first, ix, it->second);
10.199 + }
10.200 + }
10.201 +
10.202 + void LpClp::_getColCoeffs(int ix, InsertIterator b) const {
10.203 + CoinBigIndex begin = _prob->clpMatrix()->getVectorStarts()[ix];
10.204 + CoinBigIndex end = begin + _prob->clpMatrix()->getVectorLengths()[ix];
10.205 +
10.206 + const int* indices = _prob->clpMatrix()->getIndices();
10.207 + const double* elements = _prob->clpMatrix()->getElements();
10.208 +
10.209 + for (CoinBigIndex i = begin; i != end; ++i) {
10.210 + *b = std::make_pair(indices[i], elements[i]);
10.211 + ++b;
10.212 + }
10.213 + }
10.214 +
10.215 + void LpClp::_setCoeff(int ix, int jx, Value value) {
10.216 + _prob->modifyCoefficient(ix, jx, value);
10.217 + }
10.218 +
10.219 + LpClp::Value LpClp::_getCoeff(int ix, int jx) const {
10.220 + CoinBigIndex begin = _prob->clpMatrix()->getVectorStarts()[ix];
10.221 + CoinBigIndex end = begin + _prob->clpMatrix()->getVectorLengths()[ix];
10.222 +
10.223 + const int* indices = _prob->clpMatrix()->getIndices();
10.224 + const double* elements = _prob->clpMatrix()->getElements();
10.225 +
10.226 + const int* it = std::lower_bound(indices + begin, indices + end, jx);
10.227 + if (it != indices + end && *it == jx) {
10.228 + return elements[it - indices];
10.229 + } else {
10.230 + return 0.0;
10.231 + }
10.232 + }
10.233 +
10.234 + void LpClp::_setColLowerBound(int i, Value lo) {
10.235 + _prob->setColumnLower(i, lo == - INF ? - COIN_DBL_MAX : lo);
10.236 + }
10.237 +
10.238 + LpClp::Value LpClp::_getColLowerBound(int i) const {
10.239 + double val = _prob->getColLower()[i];
10.240 + return val == - COIN_DBL_MAX ? - INF : val;
10.241 + }
10.242 +
10.243 + void LpClp::_setColUpperBound(int i, Value up) {
10.244 + _prob->setColumnUpper(i, up == INF ? COIN_DBL_MAX : up);
10.245 + }
10.246 +
10.247 + LpClp::Value LpClp::_getColUpperBound(int i) const {
10.248 + double val = _prob->getColUpper()[i];
10.249 + return val == COIN_DBL_MAX ? INF : val;
10.250 + }
10.251 +
10.252 + void LpClp::_setRowLowerBound(int i, Value lo) {
10.253 + _prob->setRowLower(i, lo == - INF ? - COIN_DBL_MAX : lo);
10.254 + }
10.255 +
10.256 + LpClp::Value LpClp::_getRowLowerBound(int i) const {
10.257 + double val = _prob->getRowLower()[i];
10.258 + return val == - COIN_DBL_MAX ? - INF : val;
10.259 + }
10.260 +
10.261 + void LpClp::_setRowUpperBound(int i, Value up) {
10.262 + _prob->setRowUpper(i, up == INF ? COIN_DBL_MAX : up);
10.263 + }
10.264 +
10.265 + LpClp::Value LpClp::_getRowUpperBound(int i) const {
10.266 + double val = _prob->getRowUpper()[i];
10.267 + return val == COIN_DBL_MAX ? INF : val;
10.268 + }
10.269 +
10.270 + void LpClp::_setObjCoeffs(ExprIterator b, ExprIterator e) {
10.271 + int num = _prob->clpMatrix()->getNumCols();
10.272 + for (int i = 0; i < num; ++i) {
10.273 + _prob->setObjectiveCoefficient(i, 0.0);
10.274 + }
10.275 + for (ExprIterator it = b; it != e; ++it) {
10.276 + _prob->setObjectiveCoefficient(it->first, it->second);
10.277 + }
10.278 + }
10.279 +
10.280 + void LpClp::_getObjCoeffs(InsertIterator b) const {
10.281 + int num = _prob->clpMatrix()->getNumCols();
10.282 + for (int i = 0; i < num; ++i) {
10.283 + Value coef = _prob->getObjCoefficients()[i];
10.284 + if (coef != 0.0) {
10.285 + *b = std::make_pair(i, coef);
10.286 + ++b;
10.287 + }
10.288 + }
10.289 + }
10.290 +
10.291 + void LpClp::_setObjCoeff(int i, Value obj_coef) {
10.292 + _prob->setObjectiveCoefficient(i, obj_coef);
10.293 + }
10.294 +
10.295 + LpClp::Value LpClp::_getObjCoeff(int i) const {
10.296 + return _prob->getObjCoefficients()[i];
10.297 + }
10.298 +
10.299 + LpClp::SolveExitStatus LpClp::_solve() {
10.300 + return _prob->primal() >= 0 ? SOLVED : UNSOLVED;
10.301 + }
10.302 +
10.303 + LpClp::SolveExitStatus LpClp::solvePrimal() {
10.304 + return _prob->primal() >= 0 ? SOLVED : UNSOLVED;
10.305 + }
10.306 +
10.307 + LpClp::SolveExitStatus LpClp::solveDual() {
10.308 + return _prob->dual() >= 0 ? SOLVED : UNSOLVED;
10.309 + }
10.310 +
10.311 + LpClp::SolveExitStatus LpClp::solveBarrier() {
10.312 + return _prob->barrier() >= 0 ? SOLVED : UNSOLVED;
10.313 + }
10.314 +
10.315 + LpClp::Value LpClp::_getPrimal(int i) const {
10.316 + return _prob->primalColumnSolution()[i];
10.317 + }
10.318 + LpClp::Value LpClp::_getPrimalValue() const {
10.319 + return _prob->objectiveValue();
10.320 + }
10.321 +
10.322 + LpClp::Value LpClp::_getDual(int i) const {
10.323 + return _prob->dualRowSolution()[i];
10.324 + }
10.325 +
10.326 + LpClp::Value LpClp::_getPrimalRay(int i) const {
10.327 + if (!_primal_ray) {
10.328 + _primal_ray = _prob->unboundedRay();
10.329 + LEMON_ASSERT(_primal_ray != 0, "Primal ray is not provided");
10.330 + }
10.331 + return _primal_ray[i];
10.332 + }
10.333 +
10.334 + LpClp::Value LpClp::_getDualRay(int i) const {
10.335 + if (!_dual_ray) {
10.336 + _dual_ray = _prob->infeasibilityRay();
10.337 + LEMON_ASSERT(_dual_ray != 0, "Dual ray is not provided");
10.338 + }
10.339 + return _dual_ray[i];
10.340 + }
10.341 +
10.342 + LpClp::VarStatus LpClp::_getColStatus(int i) const {
10.343 + switch (_prob->getColumnStatus(i)) {
10.344 + case ClpSimplex::basic:
10.345 + return BASIC;
10.346 + case ClpSimplex::isFree:
10.347 + return FREE;
10.348 + case ClpSimplex::atUpperBound:
10.349 + return UPPER;
10.350 + case ClpSimplex::atLowerBound:
10.351 + return LOWER;
10.352 + case ClpSimplex::isFixed:
10.353 + return FIXED;
10.354 + case ClpSimplex::superBasic:
10.355 + return FREE;
10.356 + default:
10.357 + LEMON_ASSERT(false, "Wrong column status");
10.358 + return VarStatus();
10.359 + }
10.360 + }
10.361 +
10.362 + LpClp::VarStatus LpClp::_getRowStatus(int i) const {
10.363 + switch (_prob->getColumnStatus(i)) {
10.364 + case ClpSimplex::basic:
10.365 + return BASIC;
10.366 + case ClpSimplex::isFree:
10.367 + return FREE;
10.368 + case ClpSimplex::atUpperBound:
10.369 + return UPPER;
10.370 + case ClpSimplex::atLowerBound:
10.371 + return LOWER;
10.372 + case ClpSimplex::isFixed:
10.373 + return FIXED;
10.374 + case ClpSimplex::superBasic:
10.375 + return FREE;
10.376 + default:
10.377 + LEMON_ASSERT(false, "Wrong row status");
10.378 + return VarStatus();
10.379 + }
10.380 + }
10.381 +
10.382 +
10.383 + LpClp::ProblemType LpClp::_getPrimalType() const {
10.384 + if (_prob->isProvenOptimal()) {
10.385 + return OPTIMAL;
10.386 + } else if (_prob->isProvenPrimalInfeasible()) {
10.387 + return INFEASIBLE;
10.388 + } else if (_prob->isProvenDualInfeasible()) {
10.389 + return UNBOUNDED;
10.390 + } else {
10.391 + return UNDEFINED;
10.392 + }
10.393 + }
10.394 +
10.395 + LpClp::ProblemType LpClp::_getDualType() const {
10.396 + if (_prob->isProvenOptimal()) {
10.397 + return OPTIMAL;
10.398 + } else if (_prob->isProvenDualInfeasible()) {
10.399 + return INFEASIBLE;
10.400 + } else if (_prob->isProvenPrimalInfeasible()) {
10.401 + return INFEASIBLE;
10.402 + } else {
10.403 + return UNDEFINED;
10.404 + }
10.405 + }
10.406 +
10.407 + void LpClp::_setSense(LpClp::Sense sense) {
10.408 + switch (sense) {
10.409 + case MIN:
10.410 + _prob->setOptimizationDirection(1);
10.411 + break;
10.412 + case MAX:
10.413 + _prob->setOptimizationDirection(-1);
10.414 + break;
10.415 + }
10.416 + }
10.417 +
10.418 + LpClp::Sense LpClp::_getSense() const {
10.419 + double dir = _prob->optimizationDirection();
10.420 + if (dir > 0.0) {
10.421 + return MIN;
10.422 + } else {
10.423 + return MAX;
10.424 + }
10.425 + }
10.426 +
10.427 + void LpClp::_clear() {
10.428 + delete _prob;
10.429 + _prob = new ClpSimplex();
10.430 + rows.clear();
10.431 + cols.clear();
10.432 + _col_names_ref.clear();
10.433 + _clear_temporals();
10.434 + }
10.435 +
10.436 + void LpClp::messageLevel(MessageLevel m) {
10.437 + _prob->setLogLevel(static_cast<int>(m));
10.438 + }
10.439 +
10.440 +} //END OF NAMESPACE LEMON
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
11.2 +++ b/lemon/lp_clp.h Tue Dec 02 22:48:28 2008 +0100
11.3 @@ -0,0 +1,179 @@
11.4 +/* -*- mode: C++; indent-tabs-mode: nil; -*-
11.5 + *
11.6 + * This file is a part of LEMON, a generic C++ optimization library.
11.7 + *
11.8 + * Copyright (C) 2003-2008
11.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
11.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
11.11 + *
11.12 + * Permission to use, modify and distribute this software is granted
11.13 + * provided that this copyright notice appears in all copies. For
11.14 + * precise terms see the accompanying LICENSE file.
11.15 + *
11.16 + * This software is provided "AS IS" with no warranty of any kind,
11.17 + * express or implied, and with no claim as to its suitability for any
11.18 + * purpose.
11.19 + *
11.20 + */
11.21 +
11.22 +#ifndef LEMON_LP_CLP_H
11.23 +#define LEMON_LP_CLP_H
11.24 +
11.25 +///\file
11.26 +///\brief Header of the LEMON-CLP lp solver interface.
11.27 +
11.28 +#include <vector>
11.29 +#include <string>
11.30 +
11.31 +#include <lemon/lp_base.h>
11.32 +
11.33 +class ClpSimplex;
11.34 +
11.35 +namespace lemon {
11.36 +
11.37 + /// \ingroup lp_group
11.38 + ///
11.39 + /// \brief Interface for the CLP solver
11.40 + ///
11.41 + /// This class implements an interface for the Clp LP solver. The
11.42 + /// Clp library is an object oriented lp solver library developed at
11.43 + /// the IBM. The CLP is part of the COIN-OR package and it can be
11.44 + /// used with Common Public License.
11.45 + class LpClp : public LpSolver {
11.46 + protected:
11.47 +
11.48 + ClpSimplex* _prob;
11.49 +
11.50 + std::map<std::string, int> _col_names_ref;
11.51 + std::map<std::string, int> _row_names_ref;
11.52 +
11.53 + public:
11.54 +
11.55 + /// \e
11.56 + LpClp();
11.57 + /// \e
11.58 + LpClp(const LpClp&);
11.59 + /// \e
11.60 + ~LpClp();
11.61 +
11.62 + protected:
11.63 +
11.64 + mutable double* _primal_ray;
11.65 + mutable double* _dual_ray;
11.66 +
11.67 + void _init_temporals();
11.68 + void _clear_temporals();
11.69 +
11.70 + protected:
11.71 +
11.72 + virtual LpClp* _newSolver() const;
11.73 + virtual LpClp* _cloneSolver() const;
11.74 +
11.75 + virtual const char* _solverName() const;
11.76 +
11.77 + virtual int _addCol();
11.78 + virtual int _addRow();
11.79 +
11.80 + virtual void _eraseCol(int i);
11.81 + virtual void _eraseRow(int i);
11.82 +
11.83 + virtual void _eraseColId(int i);
11.84 + virtual void _eraseRowId(int i);
11.85 +
11.86 + virtual void _getColName(int col, std::string& name) const;
11.87 + virtual void _setColName(int col, const std::string& name);
11.88 + virtual int _colByName(const std::string& name) const;
11.89 +
11.90 + virtual void _getRowName(int row, std::string& name) const;
11.91 + virtual void _setRowName(int row, const std::string& name);
11.92 + virtual int _rowByName(const std::string& name) const;
11.93 +
11.94 + virtual void _setRowCoeffs(int i, ExprIterator b, ExprIterator e);
11.95 + virtual void _getRowCoeffs(int i, InsertIterator b) const;
11.96 +
11.97 + virtual void _setColCoeffs(int i, ExprIterator b, ExprIterator e);
11.98 + virtual void _getColCoeffs(int i, InsertIterator b) const;
11.99 +
11.100 + virtual void _setCoeff(int row, int col, Value value);
11.101 + virtual Value _getCoeff(int row, int col) const;
11.102 +
11.103 + virtual void _setColLowerBound(int i, Value value);
11.104 + virtual Value _getColLowerBound(int i) const;
11.105 + virtual void _setColUpperBound(int i, Value value);
11.106 + virtual Value _getColUpperBound(int i) const;
11.107 +
11.108 + virtual void _setRowLowerBound(int i, Value value);
11.109 + virtual Value _getRowLowerBound(int i) const;
11.110 + virtual void _setRowUpperBound(int i, Value value);
11.111 + virtual Value _getRowUpperBound(int i) const;
11.112 +
11.113 + virtual void _setObjCoeffs(ExprIterator, ExprIterator);
11.114 + virtual void _getObjCoeffs(InsertIterator) const;
11.115 +
11.116 + virtual void _setObjCoeff(int i, Value obj_coef);
11.117 + virtual Value _getObjCoeff(int i) const;
11.118 +
11.119 + virtual void _setSense(Sense sense);
11.120 + virtual Sense _getSense() const;
11.121 +
11.122 + virtual SolveExitStatus _solve();
11.123 +
11.124 + virtual Value _getPrimal(int i) const;
11.125 + virtual Value _getDual(int i) const;
11.126 +
11.127 + virtual Value _getPrimalValue() const;
11.128 +
11.129 + virtual Value _getPrimalRay(int i) const;
11.130 + virtual Value _getDualRay(int i) const;
11.131 +
11.132 + virtual VarStatus _getColStatus(int i) const;
11.133 + virtual VarStatus _getRowStatus(int i) const;
11.134 +
11.135 + virtual ProblemType _getPrimalType() const;
11.136 + virtual ProblemType _getDualType() const;
11.137 +
11.138 + virtual void _clear();
11.139 +
11.140 + public:
11.141 +
11.142 + ///Solves LP with primal simplex method.
11.143 + SolveExitStatus solvePrimal();
11.144 +
11.145 + ///Solves LP with dual simplex method.
11.146 + SolveExitStatus solveDual();
11.147 +
11.148 + ///Solves LP with barrier method.
11.149 + SolveExitStatus solveBarrier();
11.150 +
11.151 + ///Returns the constraint identifier understood by CLP.
11.152 + int clpRow(Row r) const { return rows(id(r)); }
11.153 +
11.154 + ///Returns the variable identifier understood by CLP.
11.155 + int clpCol(Col c) const { return cols(id(c)); }
11.156 +
11.157 + ///Enum for \c messageLevel() parameter
11.158 + enum MessageLevel {
11.159 + /// no output (default value)
11.160 + MESSAGE_NO_OUTPUT = 0,
11.161 + /// print final solution
11.162 + MESSAGE_FINAL_SOLUTION = 1,
11.163 + /// print factorization
11.164 + MESSAGE_FACTORIZATION = 2,
11.165 + /// normal output
11.166 + MESSAGE_NORMAL_OUTPUT = 3,
11.167 + /// verbose output
11.168 + MESSAGE_VERBOSE_OUTPUT = 4
11.169 + };
11.170 + ///Set the verbosity of the messages
11.171 +
11.172 + ///Set the verbosity of the messages
11.173 + ///
11.174 + ///\param m is the level of the messages output by the solver routines.
11.175 + void messageLevel(MessageLevel m);
11.176 +
11.177 + };
11.178 +
11.179 +} //END OF NAMESPACE LEMON
11.180 +
11.181 +#endif //LEMON_LP_CLP_H
11.182 +
12.1 --- a/lemon/lp_cplex.cc Tue Dec 02 21:40:33 2008 +0100
12.2 +++ b/lemon/lp_cplex.cc Tue Dec 02 22:48:28 2008 +0100
12.3 @@ -18,6 +18,8 @@
12.4
12.5 #include <iostream>
12.6 #include <vector>
12.7 +#include <cstring>
12.8 +
12.9 #include <lemon/lp_cplex.h>
12.10
12.11 extern "C" {
12.12 @@ -29,167 +31,226 @@
12.13 ///\brief Implementation of the LEMON-CPLEX lp solver interface.
12.14 namespace lemon {
12.15
12.16 - LpCplex::LpCplex() {
12.17 - // env = CPXopenCPLEXdevelop(&status);
12.18 - env = CPXopenCPLEX(&status);
12.19 - lp = CPXcreateprob(env, &status, "LP problem");
12.20 + CplexEnv::LicenseError::LicenseError(int status) {
12.21 + if (!CPXgeterrorstring(0, status, _message)) {
12.22 + std::strcpy(_message, "Cplex unknown error");
12.23 + }
12.24 }
12.25
12.26 - LpCplex::LpCplex(const LpCplex& cplex) : LpSolverBase() {
12.27 - env = CPXopenCPLEX(&status);
12.28 - lp = CPXcloneprob(env, cplex.lp, &status);
12.29 + CplexEnv::CplexEnv() {
12.30 + int status;
12.31 + _cnt = new int;
12.32 + _env = CPXopenCPLEX(&status);
12.33 + if (_env == 0) {
12.34 + delete _cnt;
12.35 + _cnt = 0;
12.36 + throw LicenseError(status);
12.37 + }
12.38 + }
12.39 +
12.40 + CplexEnv::CplexEnv(const CplexEnv& other) {
12.41 + _env = other._env;
12.42 + _cnt = other._cnt;
12.43 + ++(*_cnt);
12.44 + }
12.45 +
12.46 + CplexEnv& CplexEnv::operator=(const CplexEnv& other) {
12.47 + _env = other._env;
12.48 + _cnt = other._cnt;
12.49 + ++(*_cnt);
12.50 + return *this;
12.51 + }
12.52 +
12.53 + CplexEnv::~CplexEnv() {
12.54 + --(*_cnt);
12.55 + if (*_cnt == 0) {
12.56 + delete _cnt;
12.57 + CPXcloseCPLEX(&_env);
12.58 + }
12.59 + }
12.60 +
12.61 + CplexBase::CplexBase() : LpBase() {
12.62 + int status;
12.63 + _prob = CPXcreateprob(cplexEnv(), &status, "Cplex problem");
12.64 + }
12.65 +
12.66 + CplexBase::CplexBase(const CplexEnv& env)
12.67 + : LpBase(), _env(env) {
12.68 + int status;
12.69 + _prob = CPXcreateprob(cplexEnv(), &status, "Cplex problem");
12.70 + }
12.71 +
12.72 + CplexBase::CplexBase(const CplexBase& cplex)
12.73 + : LpBase() {
12.74 + int status;
12.75 + _prob = CPXcloneprob(cplexEnv(), cplex._prob, &status);
12.76 rows = cplex.rows;
12.77 cols = cplex.cols;
12.78 }
12.79
12.80 - LpCplex::~LpCplex() {
12.81 - CPXfreeprob(env,&lp);
12.82 - CPXcloseCPLEX(&env);
12.83 + CplexBase::~CplexBase() {
12.84 + CPXfreeprob(cplexEnv(),&_prob);
12.85 }
12.86
12.87 - LpSolverBase* LpCplex::_newLp()
12.88 - {
12.89 - //The first approach opens a new environment
12.90 - return new LpCplex();
12.91 - }
12.92 -
12.93 - LpSolverBase* LpCplex::_copyLp() {
12.94 - return new LpCplex(*this);
12.95 - }
12.96 -
12.97 - int LpCplex::_addCol()
12.98 - {
12.99 - int i = CPXgetnumcols(env, lp);
12.100 - Value lb[1],ub[1];
12.101 - lb[0]=-INF;
12.102 - ub[0]=INF;
12.103 - status = CPXnewcols(env, lp, 1, NULL, lb, ub, NULL, NULL);
12.104 + int CplexBase::_addCol() {
12.105 + int i = CPXgetnumcols(cplexEnv(), _prob);
12.106 + double lb = -INF, ub = INF;
12.107 + CPXnewcols(cplexEnv(), _prob, 1, 0, &lb, &ub, 0, 0);
12.108 return i;
12.109 }
12.110
12.111
12.112 - int LpCplex::_addRow()
12.113 - {
12.114 - //We want a row that is not constrained
12.115 - char sense[1];
12.116 - sense[0]='L';//<= constraint
12.117 - Value rhs[1];
12.118 - rhs[0]=INF;
12.119 - int i = CPXgetnumrows(env, lp);
12.120 - status = CPXnewrows(env, lp, 1, rhs, sense, NULL, NULL);
12.121 + int CplexBase::_addRow() {
12.122 + int i = CPXgetnumrows(cplexEnv(), _prob);
12.123 + const double ub = INF;
12.124 + const char s = 'L';
12.125 + CPXnewrows(cplexEnv(), _prob, 1, &ub, &s, 0, 0);
12.126 return i;
12.127 }
12.128
12.129
12.130 - void LpCplex::_eraseCol(int i) {
12.131 - CPXdelcols(env, lp, i, i);
12.132 + void CplexBase::_eraseCol(int i) {
12.133 + CPXdelcols(cplexEnv(), _prob, i, i);
12.134 }
12.135
12.136 - void LpCplex::_eraseRow(int i) {
12.137 - CPXdelrows(env, lp, i, i);
12.138 + void CplexBase::_eraseRow(int i) {
12.139 + CPXdelrows(cplexEnv(), _prob, i, i);
12.140 }
12.141
12.142 - void LpCplex::_getColName(int col, std::string &name) const
12.143 - {
12.144 - ///\bug Untested
12.145 - int storespace;
12.146 - CPXgetcolname(env, lp, 0, 0, 0, &storespace, col, col);
12.147 - if (storespace == 0) {
12.148 + void CplexBase::_eraseColId(int i) {
12.149 + cols.eraseIndex(i);
12.150 + cols.shiftIndices(i);
12.151 + }
12.152 + void CplexBase::_eraseRowId(int i) {
12.153 + rows.eraseIndex(i);
12.154 + rows.shiftIndices(i);
12.155 + }
12.156 +
12.157 + void CplexBase::_getColName(int col, std::string &name) const {
12.158 + int size;
12.159 + CPXgetcolname(cplexEnv(), _prob, 0, 0, 0, &size, col, col);
12.160 + if (size == 0) {
12.161 name.clear();
12.162 return;
12.163 }
12.164
12.165 - storespace *= -1;
12.166 - std::vector<char> buf(storespace);
12.167 - char *names[1];
12.168 - int dontcare;
12.169 - ///\bug return code unchecked for error
12.170 - CPXgetcolname(env, lp, names, &*buf.begin(), storespace,
12.171 - &dontcare, col, col);
12.172 - name = names[0];
12.173 + size *= -1;
12.174 + std::vector<char> buf(size);
12.175 + char *cname;
12.176 + int tmp;
12.177 + CPXgetcolname(cplexEnv(), _prob, &cname, &buf.front(), size,
12.178 + &tmp, col, col);
12.179 + name = cname;
12.180 }
12.181
12.182 - void LpCplex::_setColName(int col, const std::string &name)
12.183 - {
12.184 - ///\bug Untested
12.185 - char *names[1];
12.186 - names[0] = const_cast<char*>(name.c_str());
12.187 - ///\bug return code unchecked for error
12.188 - CPXchgcolname(env, lp, 1, &col, names);
12.189 + void CplexBase::_setColName(int col, const std::string &name) {
12.190 + char *cname;
12.191 + cname = const_cast<char*>(name.c_str());
12.192 + CPXchgcolname(cplexEnv(), _prob, 1, &col, &cname);
12.193 }
12.194
12.195 - int LpCplex::_colByName(const std::string& name) const
12.196 - {
12.197 + int CplexBase::_colByName(const std::string& name) const {
12.198 int index;
12.199 - if (CPXgetcolindex(env, lp,
12.200 + if (CPXgetcolindex(cplexEnv(), _prob,
12.201 const_cast<char*>(name.c_str()), &index) == 0) {
12.202 return index;
12.203 }
12.204 return -1;
12.205 }
12.206
12.207 - ///\warning Data at index 0 is ignored in the arrays.
12.208 - void LpCplex::_setRowCoeffs(int i, ConstRowIterator b, ConstRowIterator e)
12.209 + void CplexBase::_getRowName(int row, std::string &name) const {
12.210 + int size;
12.211 + CPXgetrowname(cplexEnv(), _prob, 0, 0, 0, &size, row, row);
12.212 + if (size == 0) {
12.213 + name.clear();
12.214 + return;
12.215 + }
12.216 +
12.217 + size *= -1;
12.218 + std::vector<char> buf(size);
12.219 + char *cname;
12.220 + int tmp;
12.221 + CPXgetrowname(cplexEnv(), _prob, &cname, &buf.front(), size,
12.222 + &tmp, row, row);
12.223 + name = cname;
12.224 + }
12.225 +
12.226 + void CplexBase::_setRowName(int row, const std::string &name) {
12.227 + char *cname;
12.228 + cname = const_cast<char*>(name.c_str());
12.229 + CPXchgrowname(cplexEnv(), _prob, 1, &row, &cname);
12.230 + }
12.231 +
12.232 + int CplexBase::_rowByName(const std::string& name) const {
12.233 + int index;
12.234 + if (CPXgetrowindex(cplexEnv(), _prob,
12.235 + const_cast<char*>(name.c_str()), &index) == 0) {
12.236 + return index;
12.237 + }
12.238 + return -1;
12.239 + }
12.240 +
12.241 + void CplexBase::_setRowCoeffs(int i, ExprIterator b,
12.242 + ExprIterator e)
12.243 {
12.244 std::vector<int> indices;
12.245 std::vector<int> rowlist;
12.246 std::vector<Value> values;
12.247
12.248 - for(ConstRowIterator it=b; it!=e; ++it) {
12.249 + for(ExprIterator it=b; it!=e; ++it) {
12.250 indices.push_back(it->first);
12.251 values.push_back(it->second);
12.252 rowlist.push_back(i);
12.253 }
12.254
12.255 - status = CPXchgcoeflist(env, lp, values.size(),
12.256 - &rowlist[0], &indices[0], &values[0]);
12.257 + CPXchgcoeflist(cplexEnv(), _prob, values.size(),
12.258 + &rowlist.front(), &indices.front(), &values.front());
12.259 }
12.260
12.261 - void LpCplex::_getRowCoeffs(int i, RowIterator b) const {
12.262 + void CplexBase::_getRowCoeffs(int i, InsertIterator b) const {
12.263 int tmp1, tmp2, tmp3, length;
12.264 - CPXgetrows(env, lp, &tmp1, &tmp2, 0, 0, 0, &length, i, i);
12.265 + CPXgetrows(cplexEnv(), _prob, &tmp1, &tmp2, 0, 0, 0, &length, i, i);
12.266
12.267 length = -length;
12.268 std::vector<int> indices(length);
12.269 std::vector<double> values(length);
12.270
12.271 - CPXgetrows(env, lp, &tmp1, &tmp2, &indices[0], &values[0],
12.272 + CPXgetrows(cplexEnv(), _prob, &tmp1, &tmp2,
12.273 + &indices.front(), &values.front(),
12.274 length, &tmp3, i, i);
12.275
12.276 for (int i = 0; i < length; ++i) {
12.277 *b = std::make_pair(indices[i], values[i]);
12.278 ++b;
12.279 }
12.280 -
12.281 - /// \todo implement
12.282 }
12.283
12.284 - void LpCplex::_setColCoeffs(int i, ConstColIterator b, ConstColIterator e)
12.285 - {
12.286 + void CplexBase::_setColCoeffs(int i, ExprIterator b, ExprIterator e) {
12.287 std::vector<int> indices;
12.288 std::vector<int> collist;
12.289 std::vector<Value> values;
12.290
12.291 - for(ConstColIterator it=b; it!=e; ++it) {
12.292 + for(ExprIterator it=b; it!=e; ++it) {
12.293 indices.push_back(it->first);
12.294 values.push_back(it->second);
12.295 collist.push_back(i);
12.296 }
12.297
12.298 - status = CPXchgcoeflist(env, lp, values.size(),
12.299 - &indices[0], &collist[0], &values[0]);
12.300 + CPXchgcoeflist(cplexEnv(), _prob, values.size(),
12.301 + &indices.front(), &collist.front(), &values.front());
12.302 }
12.303
12.304 - void LpCplex::_getColCoeffs(int i, ColIterator b) const {
12.305 + void CplexBase::_getColCoeffs(int i, InsertIterator b) const {
12.306
12.307 int tmp1, tmp2, tmp3, length;
12.308 - CPXgetcols(env, lp, &tmp1, &tmp2, 0, 0, 0, &length, i, i);
12.309 + CPXgetcols(cplexEnv(), _prob, &tmp1, &tmp2, 0, 0, 0, &length, i, i);
12.310
12.311 length = -length;
12.312 std::vector<int> indices(length);
12.313 std::vector<double> values(length);
12.314
12.315 - CPXgetcols(env, lp, &tmp1, &tmp2, &indices[0], &values[0],
12.316 + CPXgetcols(cplexEnv(), _prob, &tmp1, &tmp2,
12.317 + &indices.front(), &values.front(),
12.318 length, &tmp3, i, i);
12.319
12.320 for (int i = 0; i < length; ++i) {
12.321 @@ -199,175 +260,209 @@
12.322
12.323 }
12.324
12.325 - void LpCplex::_setCoeff(int row, int col, Value value)
12.326 - {
12.327 - CPXchgcoef(env, lp, row, col, value);
12.328 + void CplexBase::_setCoeff(int row, int col, Value value) {
12.329 + CPXchgcoef(cplexEnv(), _prob, row, col, value);
12.330 }
12.331
12.332 - LpCplex::Value LpCplex::_getCoeff(int row, int col) const
12.333 - {
12.334 - LpCplex::Value value;
12.335 - CPXgetcoef(env, lp, row, col, &value);
12.336 + CplexBase::Value CplexBase::_getCoeff(int row, int col) const {
12.337 + CplexBase::Value value;
12.338 + CPXgetcoef(cplexEnv(), _prob, row, col, &value);
12.339 return value;
12.340 }
12.341
12.342 - void LpCplex::_setColLowerBound(int i, Value value)
12.343 + void CplexBase::_setColLowerBound(int i, Value value) {
12.344 + const char s = 'L';
12.345 + CPXchgbds(cplexEnv(), _prob, 1, &i, &s, &value);
12.346 + }
12.347 +
12.348 + CplexBase::Value CplexBase::_getColLowerBound(int i) const {
12.349 + CplexBase::Value res;
12.350 + CPXgetlb(cplexEnv(), _prob, &res, i, i);
12.351 + return res <= -CPX_INFBOUND ? -INF : res;
12.352 + }
12.353 +
12.354 + void CplexBase::_setColUpperBound(int i, Value value)
12.355 {
12.356 - int indices[1];
12.357 - indices[0]=i;
12.358 - char lu[1];
12.359 - lu[0]='L';
12.360 - Value bd[1];
12.361 - bd[0]=value;
12.362 - status = CPXchgbds(env, lp, 1, indices, lu, bd);
12.363 + const char s = 'U';
12.364 + CPXchgbds(cplexEnv(), _prob, 1, &i, &s, &value);
12.365 + }
12.366 +
12.367 + CplexBase::Value CplexBase::_getColUpperBound(int i) const {
12.368 + CplexBase::Value res;
12.369 + CPXgetub(cplexEnv(), _prob, &res, i, i);
12.370 + return res >= CPX_INFBOUND ? INF : res;
12.371 + }
12.372 +
12.373 + CplexBase::Value CplexBase::_getRowLowerBound(int i) const {
12.374 + char s;
12.375 + CPXgetsense(cplexEnv(), _prob, &s, i, i);
12.376 + CplexBase::Value res;
12.377 +
12.378 + switch (s) {
12.379 + case 'G':
12.380 + case 'R':
12.381 + case 'E':
12.382 + CPXgetrhs(cplexEnv(), _prob, &res, i, i);
12.383 + return res <= -CPX_INFBOUND ? -INF : res;
12.384 + default:
12.385 + return -INF;
12.386 + }
12.387 + }
12.388 +
12.389 + CplexBase::Value CplexBase::_getRowUpperBound(int i) const {
12.390 + char s;
12.391 + CPXgetsense(cplexEnv(), _prob, &s, i, i);
12.392 + CplexBase::Value res;
12.393 +
12.394 + switch (s) {
12.395 + case 'L':
12.396 + case 'E':
12.397 + CPXgetrhs(cplexEnv(), _prob, &res, i, i);
12.398 + return res >= CPX_INFBOUND ? INF : res;
12.399 + case 'R':
12.400 + CPXgetrhs(cplexEnv(), _prob, &res, i, i);
12.401 + {
12.402 + double rng;
12.403 + CPXgetrngval(cplexEnv(), _prob, &rng, i, i);
12.404 + res += rng;
12.405 + }
12.406 + return res >= CPX_INFBOUND ? INF : res;
12.407 + default:
12.408 + return INF;
12.409 + }
12.410 + }
12.411 +
12.412 + //This is easier to implement
12.413 + void CplexBase::_set_row_bounds(int i, Value lb, Value ub) {
12.414 + if (lb == -INF) {
12.415 + const char s = 'L';
12.416 + CPXchgsense(cplexEnv(), _prob, 1, &i, &s);
12.417 + CPXchgrhs(cplexEnv(), _prob, 1, &i, &ub);
12.418 + } else if (ub == INF) {
12.419 + const char s = 'G';
12.420 + CPXchgsense(cplexEnv(), _prob, 1, &i, &s);
12.421 + CPXchgrhs(cplexEnv(), _prob, 1, &i, &lb);
12.422 + } else if (lb == ub){
12.423 + const char s = 'E';
12.424 + CPXchgsense(cplexEnv(), _prob, 1, &i, &s);
12.425 + CPXchgrhs(cplexEnv(), _prob, 1, &i, &lb);
12.426 + } else {
12.427 + const char s = 'R';
12.428 + CPXchgsense(cplexEnv(), _prob, 1, &i, &s);
12.429 + CPXchgrhs(cplexEnv(), _prob, 1, &i, &lb);
12.430 + double len = ub - lb;
12.431 + CPXchgrngval(cplexEnv(), _prob, 1, &i, &len);
12.432 + }
12.433 + }
12.434 +
12.435 + void CplexBase::_setRowLowerBound(int i, Value lb)
12.436 + {
12.437 + LEMON_ASSERT(lb != INF, "Invalid bound");
12.438 + _set_row_bounds(i, lb, CplexBase::_getRowUpperBound(i));
12.439 + }
12.440 +
12.441 + void CplexBase::_setRowUpperBound(int i, Value ub)
12.442 + {
12.443 +
12.444 + LEMON_ASSERT(ub != -INF, "Invalid bound");
12.445 + _set_row_bounds(i, CplexBase::_getRowLowerBound(i), ub);
12.446 + }
12.447 +
12.448 + void CplexBase::_setObjCoeffs(ExprIterator b, ExprIterator e)
12.449 + {
12.450 + std::vector<int> indices;
12.451 + std::vector<Value> values;
12.452 + for(ExprIterator it=b; it!=e; ++it) {
12.453 + indices.push_back(it->first);
12.454 + values.push_back(it->second);
12.455 + }
12.456 + CPXchgobj(cplexEnv(), _prob, values.size(),
12.457 + &indices.front(), &values.front());
12.458
12.459 }
12.460
12.461 - LpCplex::Value LpCplex::_getColLowerBound(int i) const
12.462 + void CplexBase::_getObjCoeffs(InsertIterator b) const
12.463 {
12.464 - LpCplex::Value x;
12.465 - CPXgetlb (env, lp, &x, i, i);
12.466 - if (x <= -CPX_INFBOUND) x = -INF;
12.467 - return x;
12.468 - }
12.469 + int num = CPXgetnumcols(cplexEnv(), _prob);
12.470 + std::vector<Value> x(num);
12.471
12.472 - void LpCplex::_setColUpperBound(int i, Value value)
12.473 - {
12.474 - int indices[1];
12.475 - indices[0]=i;
12.476 - char lu[1];
12.477 - lu[0]='U';
12.478 - Value bd[1];
12.479 - bd[0]=value;
12.480 - status = CPXchgbds(env, lp, 1, indices, lu, bd);
12.481 - }
12.482 -
12.483 - LpCplex::Value LpCplex::_getColUpperBound(int i) const
12.484 - {
12.485 - LpCplex::Value x;
12.486 - CPXgetub (env, lp, &x, i, i);
12.487 - if (x >= CPX_INFBOUND) x = INF;
12.488 - return x;
12.489 - }
12.490 -
12.491 - //This will be easier to implement
12.492 - void LpCplex::_setRowBounds(int i, Value lb, Value ub)
12.493 - {
12.494 - //Bad parameter
12.495 - if (lb==INF || ub==-INF) {
12.496 - //FIXME error
12.497 - }
12.498 -
12.499 - int cnt=1;
12.500 - int indices[1];
12.501 - indices[0]=i;
12.502 - char sense[1];
12.503 -
12.504 - if (lb==-INF){
12.505 - sense[0]='L';
12.506 - CPXchgsense(env, lp, cnt, indices, sense);
12.507 - CPXchgcoef(env, lp, i, -1, ub);
12.508 -
12.509 - }
12.510 - else{
12.511 - if (ub==INF){
12.512 - sense[0]='G';
12.513 - CPXchgsense(env, lp, cnt, indices, sense);
12.514 - CPXchgcoef(env, lp, i, -1, lb);
12.515 - }
12.516 - else{
12.517 - if (lb == ub){
12.518 - sense[0]='E';
12.519 - CPXchgsense(env, lp, cnt, indices, sense);
12.520 - CPXchgcoef(env, lp, i, -1, lb);
12.521 - }
12.522 - else{
12.523 - sense[0]='R';
12.524 - CPXchgsense(env, lp, cnt, indices, sense);
12.525 - CPXchgcoef(env, lp, i, -1, lb);
12.526 - CPXchgcoef(env, lp, i, -2, ub-lb);
12.527 - }
12.528 + CPXgetobj(cplexEnv(), _prob, &x.front(), 0, num - 1);
12.529 + for (int i = 0; i < num; ++i) {
12.530 + if (x[i] != 0.0) {
12.531 + *b = std::make_pair(i, x[i]);
12.532 + ++b;
12.533 }
12.534 }
12.535 }
12.536
12.537 -// void LpCplex::_setRowLowerBound(int i, Value value)
12.538 -// {
12.539 -// //Not implemented, obsolete
12.540 -// }
12.541 -
12.542 -// void LpCplex::_setRowUpperBound(int i, Value value)
12.543 -// {
12.544 -// //Not implemented, obsolete
12.545 -// // //TODO Ezt kell meg megirni
12.546 -// // //type of the problem
12.547 -// // char sense[1];
12.548 -// // status = CPXgetsense(env, lp, sense, i, i);
12.549 -// // Value rhs[1];
12.550 -// // status = CPXgetrhs(env, lp, rhs, i, i);
12.551 -
12.552 -// // switch (sense[0]) {
12.553 -// // case 'L'://<= constraint
12.554 -// // break;
12.555 -// // case 'E'://= constraint
12.556 -// // break;
12.557 -// // case 'G'://>= constraint
12.558 -// // break;
12.559 -// // case 'R'://ranged constraint
12.560 -// // break;
12.561 -// // default: ;
12.562 -// // //FIXME error
12.563 -// // }
12.564 -
12.565 -// // status = CPXchgcoef(env, lp, i, -2, value_rng);
12.566 -// }
12.567 -
12.568 - void LpCplex::_getRowBounds(int i, Value &lb, Value &ub) const
12.569 + void CplexBase::_setObjCoeff(int i, Value obj_coef)
12.570 {
12.571 - char sense;
12.572 - CPXgetsense(env, lp, &sense,i,i);
12.573 - lb=-INF;
12.574 - ub=INF;
12.575 - switch (sense)
12.576 - {
12.577 - case 'L':
12.578 - CPXgetcoef(env, lp, i, -1, &ub);
12.579 - break;
12.580 - case 'G':
12.581 - CPXgetcoef(env, lp, i, -1, &lb);
12.582 - break;
12.583 - case 'E':
12.584 - CPXgetcoef(env, lp, i, -1, &lb);
12.585 - ub=lb;
12.586 - break;
12.587 - case 'R':
12.588 - CPXgetcoef(env, lp, i, -1, &lb);
12.589 - Value x;
12.590 - CPXgetcoef(env, lp, i, -2, &x);
12.591 - ub=lb+x;
12.592 - break;
12.593 - }
12.594 + CPXchgobj(cplexEnv(), _prob, 1, &i, &obj_coef);
12.595 }
12.596
12.597 - void LpCplex::_setObjCoeff(int i, Value obj_coef)
12.598 - {
12.599 - CPXchgcoef(env, lp, -1, i, obj_coef);
12.600 - }
12.601 -
12.602 - LpCplex::Value LpCplex::_getObjCoeff(int i) const
12.603 + CplexBase::Value CplexBase::_getObjCoeff(int i) const
12.604 {
12.605 Value x;
12.606 - CPXgetcoef(env, lp, -1, i, &x);
12.607 + CPXgetobj(cplexEnv(), _prob, &x, i, i);
12.608 return x;
12.609 }
12.610
12.611 - void LpCplex::_clearObj()
12.612 - {
12.613 - for (int i=0;i< CPXgetnumcols(env, lp);++i){
12.614 - CPXchgcoef(env, lp, -1, i, 0);
12.615 + void CplexBase::_setSense(CplexBase::Sense sense) {
12.616 + switch (sense) {
12.617 + case MIN:
12.618 + CPXchgobjsen(cplexEnv(), _prob, CPX_MIN);
12.619 + break;
12.620 + case MAX:
12.621 + CPXchgobjsen(cplexEnv(), _prob, CPX_MAX);
12.622 + break;
12.623 }
12.624 + }
12.625
12.626 + CplexBase::Sense CplexBase::_getSense() const {
12.627 + switch (CPXgetobjsen(cplexEnv(), _prob)) {
12.628 + case CPX_MIN:
12.629 + return MIN;
12.630 + case CPX_MAX:
12.631 + return MAX;
12.632 + default:
12.633 + LEMON_ASSERT(false, "Invalid sense");
12.634 + return CplexBase::Sense();
12.635 + }
12.636 }
12.637 +
12.638 + void CplexBase::_clear() {
12.639 + CPXfreeprob(cplexEnv(),&_prob);
12.640 + int status;
12.641 + _prob = CPXcreateprob(cplexEnv(), &status, "Cplex problem");
12.642 + rows.clear();
12.643 + cols.clear();
12.644 + }
12.645 +
12.646 + // LpCplex members
12.647 +
12.648 + LpCplex::LpCplex()
12.649 + : LpBase(), CplexBase(), LpSolver() {}
12.650 +
12.651 + LpCplex::LpCplex(const CplexEnv& env)
12.652 + : LpBase(), CplexBase(env), LpSolver() {}
12.653 +
12.654 + LpCplex::LpCplex(const LpCplex& other)
12.655 + : LpBase(), CplexBase(other), LpSolver() {}
12.656 +
12.657 + LpCplex::~LpCplex() {}
12.658 +
12.659 + LpCplex* LpCplex::_newSolver() const { return new LpCplex; }
12.660 + LpCplex* LpCplex::_cloneSolver() const {return new LpCplex(*this); }
12.661 +
12.662 + const char* LpCplex::_solverName() const { return "LpCplex"; }
12.663 +
12.664 + void LpCplex::_clear_temporals() {
12.665 + _col_status.clear();
12.666 + _row_status.clear();
12.667 + _primal_ray.clear();
12.668 + _dual_ray.clear();
12.669 + }
12.670 +
12.671 // The routine returns zero unless an error occurred during the
12.672 // optimization. Examples of errors include exhausting available
12.673 // memory (CPXERR_NO_MEMORY) or encountering invalid data in the
12.674 @@ -377,32 +472,24 @@
12.675 // value does not necessarily mean that a solution exists. Use query
12.676 // routines CPXsolninfo, CPXgetstat, and CPXsolution to obtain
12.677 // further information about the status of the optimization.
12.678 - LpCplex::SolveExitStatus LpCplex::_solve()
12.679 - {
12.680 - //CPX_PARAM_LPMETHOD
12.681 - status = CPXlpopt(env, lp);
12.682 - //status = CPXprimopt(env, lp);
12.683 + LpCplex::SolveExitStatus LpCplex::convertStatus(int status) {
12.684 #if CPX_VERSION >= 800
12.685 - if (status)
12.686 - {
12.687 + if (status == 0) {
12.688 + switch (CPXgetstat(cplexEnv(), _prob)) {
12.689 + case CPX_STAT_OPTIMAL:
12.690 + case CPX_STAT_INFEASIBLE:
12.691 + case CPX_STAT_UNBOUNDED:
12.692 + return SOLVED;
12.693 + default:
12.694 + return UNSOLVED;
12.695 + }
12.696 + } else {
12.697 return UNSOLVED;
12.698 }
12.699 - else
12.700 - {
12.701 - switch (CPXgetstat(env, lp))
12.702 - {
12.703 - case CPX_STAT_OPTIMAL:
12.704 - case CPX_STAT_INFEASIBLE:
12.705 - case CPX_STAT_UNBOUNDED:
12.706 - return SOLVED;
12.707 - default:
12.708 - return UNSOLVED;
12.709 - }
12.710 - }
12.711 #else
12.712 - if (status == 0){
12.713 + if (status == 0) {
12.714 //We want to exclude some cases
12.715 - switch (CPXgetstat(env, lp)){
12.716 + switch (CPXgetstat(cplexEnv(), _prob)) {
12.717 case CPX_OBJ_LIM:
12.718 case CPX_IT_LIM_FEAS:
12.719 case CPX_IT_LIM_INFEAS:
12.720 @@ -412,115 +499,179 @@
12.721 default:
12.722 return SOLVED;
12.723 }
12.724 - }
12.725 - else{
12.726 + } else {
12.727 return UNSOLVED;
12.728 }
12.729 #endif
12.730 }
12.731
12.732 - LpCplex::Value LpCplex::_getPrimal(int i) const
12.733 - {
12.734 + LpCplex::SolveExitStatus LpCplex::_solve() {
12.735 + _clear_temporals();
12.736 + return convertStatus(CPXlpopt(cplexEnv(), _prob));
12.737 + }
12.738 +
12.739 + LpCplex::SolveExitStatus LpCplex::solvePrimal() {
12.740 + _clear_temporals();
12.741 + return convertStatus(CPXprimopt(cplexEnv(), _prob));
12.742 + }
12.743 +
12.744 + LpCplex::SolveExitStatus LpCplex::solveDual() {
12.745 + _clear_temporals();
12.746 + return convertStatus(CPXdualopt(cplexEnv(), _prob));
12.747 + }
12.748 +
12.749 + LpCplex::SolveExitStatus LpCplex::solveBarrier() {
12.750 + _clear_temporals();
12.751 + return convertStatus(CPXbaropt(cplexEnv(), _prob));
12.752 + }
12.753 +
12.754 + LpCplex::Value LpCplex::_getPrimal(int i) const {
12.755 Value x;
12.756 - CPXgetx(env, lp, &x, i, i);
12.757 + CPXgetx(cplexEnv(), _prob, &x, i, i);
12.758 return x;
12.759 }
12.760
12.761 - LpCplex::Value LpCplex::_getDual(int i) const
12.762 - {
12.763 + LpCplex::Value LpCplex::_getDual(int i) const {
12.764 Value y;
12.765 - CPXgetpi(env, lp, &y, i, i);
12.766 + CPXgetpi(cplexEnv(), _prob, &y, i, i);
12.767 return y;
12.768 }
12.769
12.770 - LpCplex::Value LpCplex::_getPrimalValue() const
12.771 - {
12.772 + LpCplex::Value LpCplex::_getPrimalValue() const {
12.773 Value objval;
12.774 - //method = CPXgetmethod (env, lp);
12.775 - //printf("CPXgetprobtype %d \n",CPXgetprobtype(env,lp));
12.776 - CPXgetobjval(env, lp, &objval);
12.777 - //printf("Objective value: %g \n",objval);
12.778 + CPXgetobjval(cplexEnv(), _prob, &objval);
12.779 return objval;
12.780 }
12.781 - bool LpCplex::_isBasicCol(int i) const
12.782 - {
12.783 - std::vector<int> cstat(CPXgetnumcols(env, lp));
12.784 - CPXgetbase(env, lp, &*cstat.begin(), NULL);
12.785 - return (cstat[i]==CPX_BASIC);
12.786 +
12.787 + LpCplex::VarStatus LpCplex::_getColStatus(int i) const {
12.788 + if (_col_status.empty()) {
12.789 + _col_status.resize(CPXgetnumcols(cplexEnv(), _prob));
12.790 + CPXgetbase(cplexEnv(), _prob, &_col_status.front(), 0);
12.791 + }
12.792 + switch (_col_status[i]) {
12.793 + case CPX_BASIC:
12.794 + return BASIC;
12.795 + case CPX_FREE_SUPER:
12.796 + return FREE;
12.797 + case CPX_AT_LOWER:
12.798 + return LOWER;
12.799 + case CPX_AT_UPPER:
12.800 + return UPPER;
12.801 + default:
12.802 + LEMON_ASSERT(false, "Wrong column status");
12.803 + return LpCplex::VarStatus();
12.804 + }
12.805 }
12.806
12.807 -//7.5-os cplex statusai (Vigyazat: a 9.0-asei masok!)
12.808 -// This table lists the statuses, returned by the CPXgetstat()
12.809 -// routine, for solutions to LP problems or mixed integer problems. If
12.810 -// no solution exists, the return value is zero.
12.811 + LpCplex::VarStatus LpCplex::_getRowStatus(int i) const {
12.812 + if (_row_status.empty()) {
12.813 + _row_status.resize(CPXgetnumrows(cplexEnv(), _prob));
12.814 + CPXgetbase(cplexEnv(), _prob, 0, &_row_status.front());
12.815 + }
12.816 + switch (_row_status[i]) {
12.817 + case CPX_BASIC:
12.818 + return BASIC;
12.819 + case CPX_AT_LOWER:
12.820 + {
12.821 + char s;
12.822 + CPXgetsense(cplexEnv(), _prob, &s, i, i);
12.823 + return s != 'L' ? LOWER : UPPER;
12.824 + }
12.825 + case CPX_AT_UPPER:
12.826 + return UPPER;
12.827 + default:
12.828 + LEMON_ASSERT(false, "Wrong row status");
12.829 + return LpCplex::VarStatus();
12.830 + }
12.831 + }
12.832
12.833 -// For Simplex, Barrier
12.834 -// 1 CPX_OPTIMAL
12.835 -// Optimal solution found
12.836 -// 2 CPX_INFEASIBLE
12.837 -// Problem infeasible
12.838 -// 3 CPX_UNBOUNDED
12.839 -// Problem unbounded
12.840 -// 4 CPX_OBJ_LIM
12.841 -// Objective limit exceeded in Phase II
12.842 -// 5 CPX_IT_LIM_FEAS
12.843 -// Iteration limit exceeded in Phase II
12.844 -// 6 CPX_IT_LIM_INFEAS
12.845 -// Iteration limit exceeded in Phase I
12.846 -// 7 CPX_TIME_LIM_FEAS
12.847 -// Time limit exceeded in Phase II
12.848 -// 8 CPX_TIME_LIM_INFEAS
12.849 -// Time limit exceeded in Phase I
12.850 -// 9 CPX_NUM_BEST_FEAS
12.851 -// Problem non-optimal, singularities in Phase II
12.852 -// 10 CPX_NUM_BEST_INFEAS
12.853 -// Problem non-optimal, singularities in Phase I
12.854 -// 11 CPX_OPTIMAL_INFEAS
12.855 -// Optimal solution found, unscaled infeasibilities
12.856 -// 12 CPX_ABORT_FEAS
12.857 -// Aborted in Phase II
12.858 -// 13 CPX_ABORT_INFEAS
12.859 -// Aborted in Phase I
12.860 -// 14 CPX_ABORT_DUAL_INFEAS
12.861 -// Aborted in barrier, dual infeasible
12.862 -// 15 CPX_ABORT_PRIM_INFEAS
12.863 -// Aborted in barrier, primal infeasible
12.864 -// 16 CPX_ABORT_PRIM_DUAL_INFEAS
12.865 -// Aborted in barrier, primal and dual infeasible
12.866 -// 17 CPX_ABORT_PRIM_DUAL_FEAS
12.867 -// Aborted in barrier, primal and dual feasible
12.868 -// 18 CPX_ABORT_CROSSOVER
12.869 -// Aborted in crossover
12.870 -// 19 CPX_INForUNBD
12.871 -// Infeasible or unbounded
12.872 -// 20 CPX_PIVOT
12.873 -// User pivot used
12.874 -//
12.875 -// Ezeket hova tegyem:
12.876 -// ??case CPX_ABORT_DUAL_INFEAS
12.877 -// ??case CPX_ABORT_CROSSOVER
12.878 -// ??case CPX_INForUNBD
12.879 -// ??case CPX_PIVOT
12.880 + LpCplex::Value LpCplex::_getPrimalRay(int i) const {
12.881 + if (_primal_ray.empty()) {
12.882 + _primal_ray.resize(CPXgetnumcols(cplexEnv(), _prob));
12.883 + CPXgetray(cplexEnv(), _prob, &_primal_ray.front());
12.884 + }
12.885 + return _primal_ray[i];
12.886 + }
12.887
12.888 -//Some more interesting stuff:
12.889 + LpCplex::Value LpCplex::_getDualRay(int i) const {
12.890 + if (_dual_ray.empty()) {
12.891
12.892 -// CPX_PARAM_LPMETHOD 1062 int LPMETHOD
12.893 -// 0 Automatic
12.894 -// 1 Primal Simplex
12.895 -// 2 Dual Simplex
12.896 -// 3 Network Simplex
12.897 -// 4 Standard Barrier
12.898 -// Default: 0
12.899 -// Description: Method for linear optimization.
12.900 -// Determines which algorithm is used when CPXlpopt() (or "optimize"
12.901 -// in the Interactive Optimizer) is called. Currently the behavior of
12.902 -// the "Automatic" setting is that CPLEX simply invokes the dual
12.903 -// simplex method, but this capability may be expanded in the future
12.904 -// so that CPLEX chooses the method based on problem characteristics
12.905 + }
12.906 + return _dual_ray[i];
12.907 + }
12.908 +
12.909 + //7.5-os cplex statusai (Vigyazat: a 9.0-asei masok!)
12.910 + // This table lists the statuses, returned by the CPXgetstat()
12.911 + // routine, for solutions to LP problems or mixed integer problems. If
12.912 + // no solution exists, the return value is zero.
12.913 +
12.914 + // For Simplex, Barrier
12.915 + // 1 CPX_OPTIMAL
12.916 + // Optimal solution found
12.917 + // 2 CPX_INFEASIBLE
12.918 + // Problem infeasible
12.919 + // 3 CPX_UNBOUNDED
12.920 + // Problem unbounded
12.921 + // 4 CPX_OBJ_LIM
12.922 + // Objective limit exceeded in Phase II
12.923 + // 5 CPX_IT_LIM_FEAS
12.924 + // Iteration limit exceeded in Phase II
12.925 + // 6 CPX_IT_LIM_INFEAS
12.926 + // Iteration limit exceeded in Phase I
12.927 + // 7 CPX_TIME_LIM_FEAS
12.928 + // Time limit exceeded in Phase II
12.929 + // 8 CPX_TIME_LIM_INFEAS
12.930 + // Time limit exceeded in Phase I
12.931 + // 9 CPX_NUM_BEST_FEAS
12.932 + // Problem non-optimal, singularities in Phase II
12.933 + // 10 CPX_NUM_BEST_INFEAS
12.934 + // Problem non-optimal, singularities in Phase I
12.935 + // 11 CPX_OPTIMAL_INFEAS
12.936 + // Optimal solution found, unscaled infeasibilities
12.937 + // 12 CPX_ABORT_FEAS
12.938 + // Aborted in Phase II
12.939 + // 13 CPX_ABORT_INFEAS
12.940 + // Aborted in Phase I
12.941 + // 14 CPX_ABORT_DUAL_INFEAS
12.942 + // Aborted in barrier, dual infeasible
12.943 + // 15 CPX_ABORT_PRIM_INFEAS
12.944 + // Aborted in barrier, primal infeasible
12.945 + // 16 CPX_ABORT_PRIM_DUAL_INFEAS
12.946 + // Aborted in barrier, primal and dual infeasible
12.947 + // 17 CPX_ABORT_PRIM_DUAL_FEAS
12.948 + // Aborted in barrier, primal and dual feasible
12.949 + // 18 CPX_ABORT_CROSSOVER
12.950 + // Aborted in crossover
12.951 + // 19 CPX_INForUNBD
12.952 + // Infeasible or unbounded
12.953 + // 20 CPX_PIVOT
12.954 + // User pivot used
12.955 + //
12.956 + // Ezeket hova tegyem:
12.957 + // ??case CPX_ABORT_DUAL_INFEAS
12.958 + // ??case CPX_ABORT_CROSSOVER
12.959 + // ??case CPX_INForUNBD
12.960 + // ??case CPX_PIVOT
12.961 +
12.962 + //Some more interesting stuff:
12.963 +
12.964 + // CPX_PARAM_PROBMETHOD 1062 int LPMETHOD
12.965 + // 0 Automatic
12.966 + // 1 Primal Simplex
12.967 + // 2 Dual Simplex
12.968 + // 3 Network Simplex
12.969 + // 4 Standard Barrier
12.970 + // Default: 0
12.971 + // Description: Method for linear optimization.
12.972 + // Determines which algorithm is used when CPXlpopt() (or "optimize"
12.973 + // in the Interactive Optimizer) is called. Currently the behavior of
12.974 + // the "Automatic" setting is that CPLEX simply invokes the dual
12.975 + // simplex method, but this capability may be expanded in the future
12.976 + // so that CPLEX chooses the method based on problem characteristics
12.977 #if CPX_VERSION < 900
12.978 - void statusSwitch(CPXENVptr env,int& stat){
12.979 + void statusSwitch(CPXENVptr cplexEnv(),int& stat){
12.980 int lpmethod;
12.981 - CPXgetintparam (env,CPX_PARAM_LPMETHOD,&lpmethod);
12.982 + CPXgetintparam (cplexEnv(),CPX_PARAM_PROBMETHOD,&lpmethod);
12.983 if (lpmethod==2){
12.984 if (stat==CPX_UNBOUNDED){
12.985 stat=CPX_INFEASIBLE;
12.986 @@ -535,8 +686,213 @@
12.987 void statusSwitch(CPXENVptr,int&){}
12.988 #endif
12.989
12.990 - LpCplex::SolutionStatus LpCplex::_getPrimalStatus() const
12.991 - {
12.992 + LpCplex::ProblemType LpCplex::_getPrimalType() const {
12.993 + // Unboundedness not treated well: the following is from cplex 9.0 doc
12.994 + // About Unboundedness
12.995 +
12.996 + // The treatment of models that are unbounded involves a few
12.997 + // subtleties. Specifically, a declaration of unboundedness means that
12.998 + // ILOG CPLEX has determined that the model has an unbounded
12.999 + // ray. Given any feasible solution x with objective z, a multiple of
12.1000 + // the unbounded ray can be added to x to give a feasible solution
12.1001 + // with objective z-1 (or z+1 for maximization models). Thus, if a
12.1002 + // feasible solution exists, then the optimal objective is
12.1003 + // unbounded. Note that ILOG CPLEX has not necessarily concluded that
12.1004 + // a feasible solution exists. Users can call the routine CPXsolninfo
12.1005 + // to determine whether ILOG CPLEX has also concluded that the model
12.1006 + // has a feasible solution.
12.1007 +
12.1008 + int stat = CPXgetstat(cplexEnv(), _prob);
12.1009 +#if CPX_VERSION >= 800
12.1010 + switch (stat)
12.1011 + {
12.1012 + case CPX_STAT_OPTIMAL:
12.1013 + return OPTIMAL;
12.1014 + case CPX_STAT_UNBOUNDED:
12.1015 + return UNBOUNDED;
12.1016 + case CPX_STAT_INFEASIBLE:
12.1017 + return INFEASIBLE;
12.1018 + default:
12.1019 + return UNDEFINED;
12.1020 + }
12.1021 +#else
12.1022 + statusSwitch(cplexEnv(),stat);
12.1023 + //CPXgetstat(cplexEnv(), _prob);
12.1024 + //printf("A primal status: %d, CPX_OPTIMAL=%d \n",stat,CPX_OPTIMAL);
12.1025 + switch (stat) {
12.1026 + case 0:
12.1027 + return UNDEFINED; //Undefined
12.1028 + case CPX_OPTIMAL://Optimal
12.1029 + return OPTIMAL;
12.1030 + case CPX_UNBOUNDED://Unbounded
12.1031 + return INFEASIBLE;//In case of dual simplex
12.1032 + //return UNBOUNDED;
12.1033 + case CPX_INFEASIBLE://Infeasible
12.1034 + // case CPX_IT_LIM_INFEAS:
12.1035 + // case CPX_TIME_LIM_INFEAS:
12.1036 + // case CPX_NUM_BEST_INFEAS:
12.1037 + // case CPX_OPTIMAL_INFEAS:
12.1038 + // case CPX_ABORT_INFEAS:
12.1039 + // case CPX_ABORT_PRIM_INFEAS:
12.1040 + // case CPX_ABORT_PRIM_DUAL_INFEAS:
12.1041 + return UNBOUNDED;//In case of dual simplex
12.1042 + //return INFEASIBLE;
12.1043 + // case CPX_OBJ_LIM:
12.1044 + // case CPX_IT_LIM_FEAS:
12.1045 + // case CPX_TIME_LIM_FEAS:
12.1046 + // case CPX_NUM_BEST_FEAS:
12.1047 + // case CPX_ABORT_FEAS:
12.1048 + // case CPX_ABORT_PRIM_DUAL_FEAS:
12.1049 + // return FEASIBLE;
12.1050 + default:
12.1051 + return UNDEFINED; //Everything else comes here
12.1052 + //FIXME error
12.1053 + }
12.1054 +#endif
12.1055 + }
12.1056 +
12.1057 + //9.0-as cplex verzio statusai
12.1058 + // CPX_STAT_ABORT_DUAL_OBJ_LIM
12.1059 + // CPX_STAT_ABORT_IT_LIM
12.1060 + // CPX_STAT_ABORT_OBJ_LIM
12.1061 + // CPX_STAT_ABORT_PRIM_OBJ_LIM
12.1062 + // CPX_STAT_ABORT_TIME_LIM
12.1063 + // CPX_STAT_ABORT_USER
12.1064 + // CPX_STAT_FEASIBLE_RELAXED
12.1065 + // CPX_STAT_INFEASIBLE
12.1066 + // CPX_STAT_INForUNBD
12.1067 + // CPX_STAT_NUM_BEST
12.1068 + // CPX_STAT_OPTIMAL
12.1069 + // CPX_STAT_OPTIMAL_FACE_UNBOUNDED
12.1070 + // CPX_STAT_OPTIMAL_INFEAS
12.1071 + // CPX_STAT_OPTIMAL_RELAXED
12.1072 + // CPX_STAT_UNBOUNDED
12.1073 +
12.1074 + LpCplex::ProblemType LpCplex::_getDualType() const {
12.1075 + int stat = CPXgetstat(cplexEnv(), _prob);
12.1076 +#if CPX_VERSION >= 800
12.1077 + switch (stat) {
12.1078 + case CPX_STAT_OPTIMAL:
12.1079 + return OPTIMAL;
12.1080 + case CPX_STAT_UNBOUNDED:
12.1081 + return INFEASIBLE;
12.1082 + default:
12.1083 + return UNDEFINED;
12.1084 + }
12.1085 +#else
12.1086 + statusSwitch(cplexEnv(),stat);
12.1087 + switch (stat) {
12.1088 + case 0:
12.1089 + return UNDEFINED; //Undefined
12.1090 + case CPX_OPTIMAL://Optimal
12.1091 + return OPTIMAL;
12.1092 + case CPX_UNBOUNDED:
12.1093 + return INFEASIBLE;
12.1094 + default:
12.1095 + return UNDEFINED; //Everything else comes here
12.1096 + //FIXME error
12.1097 + }
12.1098 +#endif
12.1099 + }
12.1100 +
12.1101 + // MipCplex members
12.1102 +
12.1103 + MipCplex::MipCplex()
12.1104 + : LpBase(), CplexBase(), MipSolver() {
12.1105 +
12.1106 +#if CPX_VERSION < 800
12.1107 + CPXchgprobtype(cplexEnv(), _prob, CPXPROB_MIP);
12.1108 +#else
12.1109 + CPXchgprobtype(cplexEnv(), _prob, CPXPROB_MILP);
12.1110 +#endif
12.1111 + }
12.1112 +
12.1113 + MipCplex::MipCplex(const CplexEnv& env)
12.1114 + : LpBase(), CplexBase(env), MipSolver() {
12.1115 +
12.1116 +#if CPX_VERSION < 800
12.1117 + CPXchgprobtype(cplexEnv(), _prob, CPXPROB_MIP);
12.1118 +#else
12.1119 + CPXchgprobtype(cplexEnv(), _prob, CPXPROB_MILP);
12.1120 +#endif
12.1121 +
12.1122 + }
12.1123 +
12.1124 + MipCplex::MipCplex(const MipCplex& other)
12.1125 + : LpBase(), CplexBase(other), MipSolver() {}
12.1126 +
12.1127 + MipCplex::~MipCplex() {}
12.1128 +
12.1129 + MipCplex* MipCplex::_newSolver() const { return new MipCplex; }
12.1130 + MipCplex* MipCplex::_cloneSolver() const {return new MipCplex(*this); }
12.1131 +
12.1132 + const char* MipCplex::_solverName() const { return "MipCplex"; }
12.1133 +
12.1134 + void MipCplex::_setColType(int i, MipCplex::ColTypes col_type) {
12.1135 +
12.1136 + // Note If a variable is to be changed to binary, a call to CPXchgbds
12.1137 + // should also be made to change the bounds to 0 and 1.
12.1138 +
12.1139 + switch (col_type){
12.1140 + case INTEGER: {
12.1141 + const char t = 'I';
12.1142 + CPXchgctype (cplexEnv(), _prob, 1, &i, &t);
12.1143 + } break;
12.1144 + case REAL: {
12.1145 + const char t = 'C';
12.1146 + CPXchgctype (cplexEnv(), _prob, 1, &i, &t);
12.1147 + } break;
12.1148 + default:
12.1149 + break;
12.1150 + }
12.1151 + }
12.1152 +
12.1153 + MipCplex::ColTypes MipCplex::_getColType(int i) const {
12.1154 + char t;
12.1155 + CPXgetctype (cplexEnv(), _prob, &t, i, i);
12.1156 + switch (t) {
12.1157 + case 'I':
12.1158 + return INTEGER;
12.1159 + case 'C':
12.1160 + return REAL;
12.1161 + default:
12.1162 + LEMON_ASSERT(false, "Invalid column type");
12.1163 + return ColTypes();
12.1164 + }
12.1165 +
12.1166 + }
12.1167 +
12.1168 + MipCplex::SolveExitStatus MipCplex::_solve() {
12.1169 + int status;
12.1170 + status = CPXmipopt (cplexEnv(), _prob);
12.1171 + if (status==0)
12.1172 + return SOLVED;
12.1173 + else
12.1174 + return UNSOLVED;
12.1175 +
12.1176 + }
12.1177 +
12.1178 +
12.1179 + MipCplex::ProblemType MipCplex::_getType() const {
12.1180 +
12.1181 + int stat = CPXgetstat(cplexEnv(), _prob);
12.1182 +
12.1183 + //Fortunately, MIP statuses did not change for cplex 8.0
12.1184 + switch (stat) {
12.1185 + case CPXMIP_OPTIMAL:
12.1186 + // Optimal integer solution has been found.
12.1187 + case CPXMIP_OPTIMAL_TOL:
12.1188 + // Optimal soluton with the tolerance defined by epgap or epagap has
12.1189 + // been found.
12.1190 + return OPTIMAL;
12.1191 + //This also exists in later issues
12.1192 + // case CPXMIP_UNBOUNDED:
12.1193 + //return UNBOUNDED;
12.1194 + case CPXMIP_INFEASIBLE:
12.1195 + return INFEASIBLE;
12.1196 + default:
12.1197 + return UNDEFINED;
12.1198 + }
12.1199 //Unboundedness not treated well: the following is from cplex 9.0 doc
12.1200 // About Unboundedness
12.1201
12.1202 @@ -551,148 +907,18 @@
12.1203 // a feasible solution exists. Users can call the routine CPXsolninfo
12.1204 // to determine whether ILOG CPLEX has also concluded that the model
12.1205 // has a feasible solution.
12.1206 -
12.1207 - int stat = CPXgetstat(env, lp);
12.1208 -#if CPX_VERSION >= 800
12.1209 - switch (stat)
12.1210 - {
12.1211 - case CPX_STAT_OPTIMAL:
12.1212 - return OPTIMAL;
12.1213 - case CPX_STAT_UNBOUNDED:
12.1214 - return INFINITE;
12.1215 - case CPX_STAT_INFEASIBLE:
12.1216 - return INFEASIBLE;
12.1217 - default:
12.1218 - return UNDEFINED;
12.1219 - }
12.1220 -#else
12.1221 - statusSwitch(env,stat);
12.1222 - //CPXgetstat(env, lp);
12.1223 - //printf("A primal status: %d, CPX_OPTIMAL=%d \n",stat,CPX_OPTIMAL);
12.1224 - switch (stat) {
12.1225 - case 0:
12.1226 - return UNDEFINED; //Undefined
12.1227 - case CPX_OPTIMAL://Optimal
12.1228 - return OPTIMAL;
12.1229 - case CPX_UNBOUNDED://Unbounded
12.1230 - return INFEASIBLE;//In case of dual simplex
12.1231 - //return INFINITE;
12.1232 - case CPX_INFEASIBLE://Infeasible
12.1233 - // case CPX_IT_LIM_INFEAS:
12.1234 -// case CPX_TIME_LIM_INFEAS:
12.1235 -// case CPX_NUM_BEST_INFEAS:
12.1236 -// case CPX_OPTIMAL_INFEAS:
12.1237 -// case CPX_ABORT_INFEAS:
12.1238 -// case CPX_ABORT_PRIM_INFEAS:
12.1239 -// case CPX_ABORT_PRIM_DUAL_INFEAS:
12.1240 - return INFINITE;//In case of dual simplex
12.1241 - //return INFEASIBLE;
12.1242 -// case CPX_OBJ_LIM:
12.1243 -// case CPX_IT_LIM_FEAS:
12.1244 -// case CPX_TIME_LIM_FEAS:
12.1245 -// case CPX_NUM_BEST_FEAS:
12.1246 -// case CPX_ABORT_FEAS:
12.1247 -// case CPX_ABORT_PRIM_DUAL_FEAS:
12.1248 -// return FEASIBLE;
12.1249 - default:
12.1250 - return UNDEFINED; //Everything else comes here
12.1251 - //FIXME error
12.1252 - }
12.1253 -#endif
12.1254 }
12.1255
12.1256 -//9.0-as cplex verzio statusai
12.1257 -// CPX_STAT_ABORT_DUAL_OBJ_LIM
12.1258 -// CPX_STAT_ABORT_IT_LIM
12.1259 -// CPX_STAT_ABORT_OBJ_LIM
12.1260 -// CPX_STAT_ABORT_PRIM_OBJ_LIM
12.1261 -// CPX_STAT_ABORT_TIME_LIM
12.1262 -// CPX_STAT_ABORT_USER
12.1263 -// CPX_STAT_FEASIBLE_RELAXED
12.1264 -// CPX_STAT_INFEASIBLE
12.1265 -// CPX_STAT_INForUNBD
12.1266 -// CPX_STAT_NUM_BEST
12.1267 -// CPX_STAT_OPTIMAL
12.1268 -// CPX_STAT_OPTIMAL_FACE_UNBOUNDED
12.1269 -// CPX_STAT_OPTIMAL_INFEAS
12.1270 -// CPX_STAT_OPTIMAL_RELAXED
12.1271 -// CPX_STAT_UNBOUNDED
12.1272 -
12.1273 - LpCplex::SolutionStatus LpCplex::_getDualStatus() const
12.1274 - {
12.1275 - int stat = CPXgetstat(env, lp);
12.1276 -#if CPX_VERSION >= 800
12.1277 - switch (stat)
12.1278 - {
12.1279 - case CPX_STAT_OPTIMAL:
12.1280 - return OPTIMAL;
12.1281 - case CPX_STAT_UNBOUNDED:
12.1282 - return INFEASIBLE;
12.1283 - default:
12.1284 - return UNDEFINED;
12.1285 - }
12.1286 -#else
12.1287 - statusSwitch(env,stat);
12.1288 - switch (stat) {
12.1289 - case 0:
12.1290 - return UNDEFINED; //Undefined
12.1291 - case CPX_OPTIMAL://Optimal
12.1292 - return OPTIMAL;
12.1293 - case CPX_UNBOUNDED:
12.1294 - return INFEASIBLE;
12.1295 - default:
12.1296 - return UNDEFINED; //Everything else comes here
12.1297 - //FIXME error
12.1298 - }
12.1299 -#endif
12.1300 + MipCplex::Value MipCplex::_getSol(int i) const {
12.1301 + Value x;
12.1302 + CPXgetmipx(cplexEnv(), _prob, &x, i, i);
12.1303 + return x;
12.1304 }
12.1305
12.1306 - LpCplex::ProblemTypes LpCplex::_getProblemType() const
12.1307 - {
12.1308 - int stat = CPXgetstat(env, lp);
12.1309 -#if CPX_VERSION >= 800
12.1310 - switch (stat)
12.1311 - {
12.1312 - case CPX_STAT_OPTIMAL:
12.1313 - return PRIMAL_DUAL_FEASIBLE;
12.1314 - case CPX_STAT_UNBOUNDED:
12.1315 - return PRIMAL_FEASIBLE_DUAL_INFEASIBLE;
12.1316 - default:
12.1317 - return UNKNOWN;
12.1318 - }
12.1319 -#else
12.1320 - switch (stat) {
12.1321 - case CPX_OPTIMAL://Optimal
12.1322 - return PRIMAL_DUAL_FEASIBLE;
12.1323 - case CPX_UNBOUNDED:
12.1324 - return PRIMAL_FEASIBLE_DUAL_INFEASIBLE;
12.1325 -// return PRIMAL_INFEASIBLE_DUAL_FEASIBLE;
12.1326 -// return PRIMAL_DUAL_INFEASIBLE;
12.1327 -
12.1328 -//Seems to be that this is all we can say for sure
12.1329 - default:
12.1330 - //In all other cases
12.1331 - return UNKNOWN;
12.1332 - //FIXME error
12.1333 - }
12.1334 -#endif
12.1335 - }
12.1336 -
12.1337 - void LpCplex::_setMax()
12.1338 - {
12.1339 - CPXchgobjsen(env, lp, CPX_MAX);
12.1340 - }
12.1341 - void LpCplex::_setMin()
12.1342 - {
12.1343 - CPXchgobjsen(env, lp, CPX_MIN);
12.1344 - }
12.1345 -
12.1346 - bool LpCplex::_isMax() const
12.1347 - {
12.1348 - if (CPXgetobjsen(env, lp)==CPX_MAX)
12.1349 - return true;
12.1350 - else
12.1351 - return false;
12.1352 + MipCplex::Value MipCplex::_getSolValue() const {
12.1353 + Value objval;
12.1354 + CPXgetmipobjval(cplexEnv(), _prob, &objval);
12.1355 + return objval;
12.1356 }
12.1357
12.1358 } //namespace lemon
13.1 --- a/lemon/lp_cplex.h Tue Dec 02 21:40:33 2008 +0100
13.2 +++ b/lemon/lp_cplex.h Tue Dec 02 22:48:28 2008 +0100
13.3 @@ -29,84 +29,227 @@
13.4
13.5 namespace lemon {
13.6
13.7 -
13.8 - /// \brief Interface for the CPLEX solver
13.9 + /// \brief Reference counted wrapper around cpxenv pointer
13.10 ///
13.11 - /// This class implements an interface for the CPLEX LP solver.
13.12 - class LpCplex :virtual public LpSolverBase {
13.13 + /// The cplex uses environment object which is responsible for
13.14 + /// checking the proper license usage. This class provides a simple
13.15 + /// interface for share the environment object between different
13.16 + /// problems.
13.17 + class CplexEnv {
13.18 + friend class CplexBase;
13.19 + private:
13.20 + cpxenv* _env;
13.21 + mutable int* _cnt;
13.22
13.23 public:
13.24
13.25 - typedef LpSolverBase Parent;
13.26 + /// \brief This exception is thrown when the license check is not
13.27 + /// sufficient
13.28 + class LicenseError : public Exception {
13.29 + friend class CplexEnv;
13.30 + private:
13.31
13.32 - /// \e
13.33 - int status;
13.34 - cpxenv* env;
13.35 - cpxlp* lp;
13.36 + LicenseError(int status);
13.37 + char _message[510];
13.38
13.39 + public:
13.40
13.41 - /// \e
13.42 - LpCplex();
13.43 - /// \e
13.44 - LpCplex(const LpCplex&);
13.45 - /// \e
13.46 - ~LpCplex();
13.47 + /// The short error message
13.48 + virtual const char* what() const throw() {
13.49 + return _message;
13.50 + }
13.51 + };
13.52 +
13.53 + /// Constructor
13.54 + CplexEnv();
13.55 + /// Shallow copy constructor
13.56 + CplexEnv(const CplexEnv&);
13.57 + /// Shallow assignement
13.58 + CplexEnv& operator=(const CplexEnv&);
13.59 + /// Destructor
13.60 + virtual ~CplexEnv();
13.61
13.62 protected:
13.63 - virtual LpSolverBase* _newLp();
13.64 - virtual LpSolverBase* _copyLp();
13.65
13.66 + cpxenv* cplexEnv() { return _env; }
13.67 + const cpxenv* cplexEnv() const { return _env; }
13.68 + };
13.69 +
13.70 + /// \brief Base interface for the CPLEX LP and MIP solver
13.71 + ///
13.72 + /// This class implements the common interface of the CPLEX LP and
13.73 + /// MIP solvers.
13.74 + /// \ingroup lp_group
13.75 + class CplexBase : virtual public LpBase {
13.76 + protected:
13.77 +
13.78 + CplexEnv _env;
13.79 + cpxlp* _prob;
13.80 +
13.81 + CplexBase();
13.82 + CplexBase(const CplexEnv&);
13.83 + CplexBase(const CplexBase &);
13.84 + virtual ~CplexBase();
13.85
13.86 virtual int _addCol();
13.87 virtual int _addRow();
13.88 +
13.89 virtual void _eraseCol(int i);
13.90 virtual void _eraseRow(int i);
13.91 - virtual void _getColName(int col, std::string & name) const;
13.92 - virtual void _setColName(int col, const std::string & name);
13.93 +
13.94 + virtual void _eraseColId(int i);
13.95 + virtual void _eraseRowId(int i);
13.96 +
13.97 + virtual void _getColName(int col, std::string& name) const;
13.98 + virtual void _setColName(int col, const std::string& name);
13.99 virtual int _colByName(const std::string& name) const;
13.100 - virtual void _setRowCoeffs(int i, ConstRowIterator b, ConstRowIterator e);
13.101 - virtual void _getRowCoeffs(int i, RowIterator b) const;
13.102 - virtual void _setColCoeffs(int i, ConstColIterator b, ConstColIterator e);
13.103 - virtual void _getColCoeffs(int i, ColIterator b) const;
13.104 +
13.105 + virtual void _getRowName(int row, std::string& name) const;
13.106 + virtual void _setRowName(int row, const std::string& name);
13.107 + virtual int _rowByName(const std::string& name) const;
13.108 +
13.109 + virtual void _setRowCoeffs(int i, ExprIterator b, ExprIterator e);
13.110 + virtual void _getRowCoeffs(int i, InsertIterator b) const;
13.111 +
13.112 + virtual void _setColCoeffs(int i, ExprIterator b, ExprIterator e);
13.113 + virtual void _getColCoeffs(int i, InsertIterator b) const;
13.114 +
13.115 virtual void _setCoeff(int row, int col, Value value);
13.116 virtual Value _getCoeff(int row, int col) const;
13.117
13.118 virtual void _setColLowerBound(int i, Value value);
13.119 virtual Value _getColLowerBound(int i) const;
13.120 +
13.121 virtual void _setColUpperBound(int i, Value value);
13.122 virtual Value _getColUpperBound(int i) const;
13.123
13.124 -// virtual void _setRowLowerBound(int i, Value value);
13.125 -// virtual void _setRowUpperBound(int i, Value value);
13.126 - virtual void _setRowBounds(int i, Value lower, Value upper);
13.127 - virtual void _getRowBounds(int i, Value &lb, Value &ub) const;
13.128 + private:
13.129 + void _set_row_bounds(int i, Value lb, Value ub);
13.130 + protected:
13.131 +
13.132 + virtual void _setRowLowerBound(int i, Value value);
13.133 + virtual Value _getRowLowerBound(int i) const;
13.134 +
13.135 + virtual void _setRowUpperBound(int i, Value value);
13.136 + virtual Value _getRowUpperBound(int i) const;
13.137 +
13.138 + virtual void _setObjCoeffs(ExprIterator b, ExprIterator e);
13.139 + virtual void _getObjCoeffs(InsertIterator b) const;
13.140 +
13.141 virtual void _setObjCoeff(int i, Value obj_coef);
13.142 virtual Value _getObjCoeff(int i) const;
13.143 - virtual void _clearObj();
13.144
13.145 + virtual void _setSense(Sense sense);
13.146 + virtual Sense _getSense() const;
13.147 +
13.148 + virtual void _clear();
13.149 +
13.150 + public:
13.151 +
13.152 + /// Returns the used \c CplexEnv instance
13.153 + const CplexEnv& env() const { return _env; }
13.154 + ///
13.155 + const cpxenv* cplexEnv() const { return _env.cplexEnv(); }
13.156 +
13.157 + cpxlp* cplexLp() { return _prob; }
13.158 + const cpxlp* cplexLp() const { return _prob; }
13.159 +
13.160 + };
13.161 +
13.162 + /// \brief Interface for the CPLEX LP solver
13.163 + ///
13.164 + /// This class implements an interface for the CPLEX LP solver.
13.165 + ///\ingroup lp_group
13.166 + class LpCplex : public CplexBase, public LpSolver {
13.167 + public:
13.168 + /// \e
13.169 + LpCplex();
13.170 + /// \e
13.171 + LpCplex(const CplexEnv&);
13.172 + /// \e
13.173 + LpCplex(const LpCplex&);
13.174 + /// \e
13.175 + virtual ~LpCplex();
13.176 +
13.177 + private:
13.178 +
13.179 + // these values cannot retrieved element by element
13.180 + mutable std::vector<int> _col_status;
13.181 + mutable std::vector<int> _row_status;
13.182 +
13.183 + mutable std::vector<Value> _primal_ray;
13.184 + mutable std::vector<Value> _dual_ray;
13.185 +
13.186 + void _clear_temporals();
13.187 +
13.188 + SolveExitStatus convertStatus(int status);
13.189 +
13.190 + protected:
13.191 +
13.192 + virtual LpCplex* _cloneSolver() const;
13.193 + virtual LpCplex* _newSolver() const;
13.194 +
13.195 + virtual const char* _solverName() const;
13.196
13.197 virtual SolveExitStatus _solve();
13.198 virtual Value _getPrimal(int i) const;
13.199 virtual Value _getDual(int i) const;
13.200 virtual Value _getPrimalValue() const;
13.201 - virtual bool _isBasicCol(int i) const;
13.202
13.203 - virtual SolutionStatus _getPrimalStatus() const;
13.204 - virtual SolutionStatus _getDualStatus() const;
13.205 - virtual ProblemTypes _getProblemType() const;
13.206 + virtual VarStatus _getColStatus(int i) const;
13.207 + virtual VarStatus _getRowStatus(int i) const;
13.208
13.209 + virtual Value _getPrimalRay(int i) const;
13.210 + virtual Value _getDualRay(int i) const;
13.211
13.212 - virtual void _setMax();
13.213 - virtual void _setMin();
13.214 -
13.215 - virtual bool _isMax() const;
13.216 + virtual ProblemType _getPrimalType() const;
13.217 + virtual ProblemType _getDualType() const;
13.218
13.219 public:
13.220
13.221 - cpxenv* cplexEnv() { return env; }
13.222 - cpxlp* cplexLp() { return lp; }
13.223 + /// Solve with primal simplex method
13.224 + SolveExitStatus solvePrimal();
13.225 +
13.226 + /// Solve with dual simplex method
13.227 + SolveExitStatus solveDual();
13.228 +
13.229 + /// Solve with barrier method
13.230 + SolveExitStatus solveBarrier();
13.231
13.232 };
13.233 +
13.234 + /// \brief Interface for the CPLEX MIP solver
13.235 + ///
13.236 + /// This class implements an interface for the CPLEX MIP solver.
13.237 + ///\ingroup lp_group
13.238 + class MipCplex : public CplexBase, public MipSolver {
13.239 + public:
13.240 + /// \e
13.241 + MipCplex();
13.242 + /// \e
13.243 + MipCplex(const CplexEnv&);
13.244 + /// \e
13.245 + MipCplex(const MipCplex&);
13.246 + /// \e
13.247 + virtual ~MipCplex();
13.248 +
13.249 + protected:
13.250 +
13.251 + virtual MipCplex* _cloneSolver() const;
13.252 + virtual MipCplex* _newSolver() const;
13.253 +
13.254 + virtual const char* _solverName() const;
13.255 +
13.256 + virtual ColTypes _getColType(int col) const;
13.257 + virtual void _setColType(int col, ColTypes col_type);
13.258 +
13.259 + virtual SolveExitStatus _solve();
13.260 + virtual ProblemType _getType() const;
13.261 + virtual Value _getSol(int i) const;
13.262 + virtual Value _getSolValue() const;
13.263 +
13.264 + };
13.265 +
13.266 } //END OF NAMESPACE LEMON
13.267
13.268 #endif //LEMON_LP_CPLEX_H
14.1 --- a/lemon/lp_glpk.cc Tue Dec 02 21:40:33 2008 +0100
14.2 +++ b/lemon/lp_glpk.cc Tue Dec 02 22:48:28 2008 +0100
14.3 @@ -17,628 +17,936 @@
14.4 */
14.5
14.6 ///\file
14.7 -///\brief Implementation of the LEMON-GLPK lp solver interface.
14.8 +///\brief Implementation of the LEMON GLPK LP and MIP solver interface.
14.9
14.10 #include <lemon/lp_glpk.h>
14.11 -//#include <iostream>
14.12 +#include <glpk.h>
14.13
14.14 -extern "C" {
14.15 -#include <glpk.h>
14.16 -}
14.17 -
14.18 -#if GLP_MAJOR_VERSION > 4 || (GLP_MAJOR_VERSION == 4 && GLP_MINOR_VERSION > 15)
14.19 -#define LEMON_glp(func) (glp_##func)
14.20 -#define LEMON_lpx(func) (lpx_##func)
14.21 -
14.22 -#define LEMON_GLP(def) (GLP_##def)
14.23 -#define LEMON_LPX(def) (LPX_##def)
14.24 -
14.25 -#else
14.26 -
14.27 -#define LEMON_glp(func) (lpx_##func)
14.28 -#define LEMON_lpx(func) (lpx_##func)
14.29 -
14.30 -#define LEMON_GLP(def) (LPX_##def)
14.31 -#define LEMON_LPX(def) (LPX_##def)
14.32 -
14.33 -#endif
14.34 +#include <lemon/assert.h>
14.35
14.36 namespace lemon {
14.37
14.38 - LpGlpk::LpGlpk() : Parent() {
14.39 - solved = false;
14.40 - rows = _lp_bits::LpId(1);
14.41 - cols = _lp_bits::LpId(1);
14.42 - lp = LEMON_glp(create_prob)();
14.43 - LEMON_glp(create_index)(lp);
14.44 - messageLevel(0);
14.45 + // GlpkBase members
14.46 +
14.47 + GlpkBase::GlpkBase() : LpBase() {
14.48 + lp = glp_create_prob();
14.49 + glp_create_index(lp);
14.50 }
14.51
14.52 - LpGlpk::LpGlpk(const LpGlpk &glp) : Parent() {
14.53 - solved = false;
14.54 - rows = _lp_bits::LpId(1);
14.55 - cols = _lp_bits::LpId(1);
14.56 - lp = LEMON_glp(create_prob)();
14.57 - LEMON_glp(create_index)(lp);
14.58 - messageLevel(0);
14.59 - //Coefficient matrix, row bounds
14.60 - LEMON_glp(add_rows)(lp, LEMON_glp(get_num_rows)(glp.lp));
14.61 - LEMON_glp(add_cols)(lp, LEMON_glp(get_num_cols)(glp.lp));
14.62 - int len;
14.63 - std::vector<int> ind(1+LEMON_glp(get_num_cols)(glp.lp));
14.64 - std::vector<Value> val(1+LEMON_glp(get_num_cols)(glp.lp));
14.65 - for (int i=1;i<=LEMON_glp(get_num_rows)(glp.lp);++i)
14.66 - {
14.67 - len=LEMON_glp(get_mat_row)(glp.lp,i,&*ind.begin(),&*val.begin());
14.68 - LEMON_glp(set_mat_row)(lp, i,len,&*ind.begin(),&*val.begin());
14.69 - LEMON_glp(set_row_bnds)(lp,i,
14.70 - LEMON_glp(get_row_type)(glp.lp,i),
14.71 - LEMON_glp(get_row_lb)(glp.lp,i),
14.72 - LEMON_glp(get_row_ub)(glp.lp,i));
14.73 - }
14.74 -
14.75 - //Objective function, coloumn bounds
14.76 - LEMON_glp(set_obj_dir)(lp, LEMON_glp(get_obj_dir)(glp.lp));
14.77 - //Objectif function's constant term treated separately
14.78 - LEMON_glp(set_obj_coef)(lp,0,LEMON_glp(get_obj_coef)(glp.lp,0));
14.79 - for (int i=1;i<=LEMON_glp(get_num_cols)(glp.lp);++i)
14.80 - {
14.81 - LEMON_glp(set_obj_coef)(lp,i,
14.82 - LEMON_glp(get_obj_coef)(glp.lp,i));
14.83 - LEMON_glp(set_col_bnds)(lp,i,
14.84 - LEMON_glp(get_col_type)(glp.lp,i),
14.85 - LEMON_glp(get_col_lb)(glp.lp,i),
14.86 - LEMON_glp(get_col_ub)(glp.lp,i));
14.87 - }
14.88 - rows = glp.rows;
14.89 - cols = glp.cols;
14.90 + GlpkBase::GlpkBase(const GlpkBase &other) : LpBase() {
14.91 + lp = glp_create_prob();
14.92 + glp_copy_prob(lp, other.lp, GLP_ON);
14.93 + glp_create_index(lp);
14.94 + rows = other.rows;
14.95 + cols = other.cols;
14.96 }
14.97
14.98 - LpGlpk::~LpGlpk() {
14.99 - LEMON_glp(delete_prob)(lp);
14.100 + GlpkBase::~GlpkBase() {
14.101 + glp_delete_prob(lp);
14.102 }
14.103
14.104 - int LpGlpk::_addCol() {
14.105 - int i=LEMON_glp(add_cols)(lp, 1);
14.106 - LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(FR), 0.0, 0.0);
14.107 - solved = false;
14.108 + int GlpkBase::_addCol() {
14.109 + int i = glp_add_cols(lp, 1);
14.110 + glp_set_col_bnds(lp, i, GLP_FR, 0.0, 0.0);
14.111 return i;
14.112 }
14.113
14.114 - ///\e
14.115 -
14.116 -
14.117 - LpSolverBase* LpGlpk::_newLp()
14.118 - {
14.119 - LpGlpk* newlp = new LpGlpk;
14.120 - return newlp;
14.121 - }
14.122 -
14.123 - ///\e
14.124 -
14.125 - LpSolverBase* LpGlpk::_copyLp()
14.126 - {
14.127 - LpGlpk *newlp = new LpGlpk(*this);
14.128 - return newlp;
14.129 - }
14.130 -
14.131 - int LpGlpk::_addRow() {
14.132 - int i=LEMON_glp(add_rows)(lp, 1);
14.133 - solved = false;
14.134 + int GlpkBase::_addRow() {
14.135 + int i = glp_add_rows(lp, 1);
14.136 + glp_set_row_bnds(lp, i, GLP_FR, 0.0, 0.0);
14.137 return i;
14.138 }
14.139
14.140 -
14.141 - void LpGlpk::_eraseCol(int i) {
14.142 + void GlpkBase::_eraseCol(int i) {
14.143 int ca[2];
14.144 - ca[1]=i;
14.145 - LEMON_glp(del_cols)(lp, 1, ca);
14.146 - solved = false;
14.147 + ca[1] = i;
14.148 + glp_del_cols(lp, 1, ca);
14.149 }
14.150
14.151 - void LpGlpk::_eraseRow(int i) {
14.152 + void GlpkBase::_eraseRow(int i) {
14.153 int ra[2];
14.154 - ra[1]=i;
14.155 - LEMON_glp(del_rows)(lp, 1, ra);
14.156 - solved = false;
14.157 + ra[1] = i;
14.158 + glp_del_rows(lp, 1, ra);
14.159 }
14.160
14.161 - void LpGlpk::_getColName(int c, std::string & name) const
14.162 - {
14.163 -
14.164 - const char *n = LEMON_glp(get_col_name)(lp,c);
14.165 - name = n?n:"";
14.166 + void GlpkBase::_eraseColId(int i) {
14.167 + cols.eraseIndex(i);
14.168 + cols.shiftIndices(i);
14.169 }
14.170
14.171 + void GlpkBase::_eraseRowId(int i) {
14.172 + rows.eraseIndex(i);
14.173 + rows.shiftIndices(i);
14.174 + }
14.175
14.176 - void LpGlpk::_setColName(int c, const std::string & name)
14.177 - {
14.178 - LEMON_glp(set_col_name)(lp,c,const_cast<char*>(name.c_str()));
14.179 + void GlpkBase::_getColName(int c, std::string& name) const {
14.180 + const char *str = glp_get_col_name(lp, c);
14.181 + if (str) name = str;
14.182 + else name.clear();
14.183 + }
14.184 +
14.185 + void GlpkBase::_setColName(int c, const std::string & name) {
14.186 + glp_set_col_name(lp, c, const_cast<char*>(name.c_str()));
14.187
14.188 }
14.189
14.190 - int LpGlpk::_colByName(const std::string& name) const
14.191 - {
14.192 - int k = LEMON_glp(find_col)(lp, const_cast<char*>(name.c_str()));
14.193 + int GlpkBase::_colByName(const std::string& name) const {
14.194 + int k = glp_find_col(lp, const_cast<char*>(name.c_str()));
14.195 return k > 0 ? k : -1;
14.196 }
14.197
14.198 + void GlpkBase::_getRowName(int r, std::string& name) const {
14.199 + const char *str = glp_get_row_name(lp, r);
14.200 + if (str) name = str;
14.201 + else name.clear();
14.202 + }
14.203
14.204 - void LpGlpk::_setRowCoeffs(int i, ConstRowIterator b, ConstRowIterator e)
14.205 - {
14.206 - std::vector<int> indices;
14.207 + void GlpkBase::_setRowName(int r, const std::string & name) {
14.208 + glp_set_row_name(lp, r, const_cast<char*>(name.c_str()));
14.209 +
14.210 + }
14.211 +
14.212 + int GlpkBase::_rowByName(const std::string& name) const {
14.213 + int k = glp_find_row(lp, const_cast<char*>(name.c_str()));
14.214 + return k > 0 ? k : -1;
14.215 + }
14.216 +
14.217 + void GlpkBase::_setRowCoeffs(int i, ExprIterator b, ExprIterator e) {
14.218 + std::vector<int> indexes;
14.219 std::vector<Value> values;
14.220
14.221 - indices.push_back(0);
14.222 + indexes.push_back(0);
14.223 values.push_back(0);
14.224
14.225 - for(ConstRowIterator it=b; it!=e; ++it) {
14.226 - indices.push_back(it->first);
14.227 + for(ExprIterator it = b; it != e; ++it) {
14.228 + indexes.push_back(it->first);
14.229 values.push_back(it->second);
14.230 }
14.231
14.232 - LEMON_glp(set_mat_row)(lp, i, values.size() - 1,
14.233 - &indices[0], &values[0]);
14.234 -
14.235 - solved = false;
14.236 + glp_set_mat_row(lp, i, values.size() - 1,
14.237 + &indexes.front(), &values.front());
14.238 }
14.239
14.240 - void LpGlpk::_getRowCoeffs(int ix, RowIterator b) const
14.241 - {
14.242 - int length = LEMON_glp(get_mat_row)(lp, ix, 0, 0);
14.243 + void GlpkBase::_getRowCoeffs(int ix, InsertIterator b) const {
14.244 + int length = glp_get_mat_row(lp, ix, 0, 0);
14.245
14.246 - std::vector<int> indices(length + 1);
14.247 + std::vector<int> indexes(length + 1);
14.248 std::vector<Value> values(length + 1);
14.249
14.250 - LEMON_glp(get_mat_row)(lp, ix, &indices[0], &values[0]);
14.251 + glp_get_mat_row(lp, ix, &indexes.front(), &values.front());
14.252
14.253 for (int i = 1; i <= length; ++i) {
14.254 - *b = std::make_pair(indices[i], values[i]);
14.255 + *b = std::make_pair(indexes[i], values[i]);
14.256 ++b;
14.257 }
14.258 }
14.259
14.260 - void LpGlpk::_setColCoeffs(int ix, ConstColIterator b, ConstColIterator e) {
14.261 + void GlpkBase::_setColCoeffs(int ix, ExprIterator b,
14.262 + ExprIterator e) {
14.263
14.264 - std::vector<int> indices;
14.265 + std::vector<int> indexes;
14.266 std::vector<Value> values;
14.267
14.268 - indices.push_back(0);
14.269 + indexes.push_back(0);
14.270 values.push_back(0);
14.271
14.272 - for(ConstColIterator it=b; it!=e; ++it) {
14.273 - indices.push_back(it->first);
14.274 + for(ExprIterator it = b; it != e; ++it) {
14.275 + indexes.push_back(it->first);
14.276 values.push_back(it->second);
14.277 }
14.278
14.279 - LEMON_glp(set_mat_col)(lp, ix, values.size() - 1,
14.280 - &indices[0], &values[0]);
14.281 -
14.282 - solved = false;
14.283 + glp_set_mat_col(lp, ix, values.size() - 1,
14.284 + &indexes.front(), &values.front());
14.285 }
14.286
14.287 - void LpGlpk::_getColCoeffs(int ix, ColIterator b) const
14.288 - {
14.289 - int length = LEMON_glp(get_mat_col)(lp, ix, 0, 0);
14.290 + void GlpkBase::_getColCoeffs(int ix, InsertIterator b) const {
14.291 + int length = glp_get_mat_col(lp, ix, 0, 0);
14.292
14.293 - std::vector<int> indices(length + 1);
14.294 + std::vector<int> indexes(length + 1);
14.295 std::vector<Value> values(length + 1);
14.296
14.297 - LEMON_glp(get_mat_col)(lp, ix, &indices[0], &values[0]);
14.298 + glp_get_mat_col(lp, ix, &indexes.front(), &values.front());
14.299
14.300 - for (int i = 1; i <= length; ++i) {
14.301 - *b = std::make_pair(indices[i], values[i]);
14.302 + for (int i = 1; i <= length; ++i) {
14.303 + *b = std::make_pair(indexes[i], values[i]);
14.304 ++b;
14.305 }
14.306 }
14.307
14.308 - void LpGlpk::_setCoeff(int ix, int jx, Value value)
14.309 - {
14.310 + void GlpkBase::_setCoeff(int ix, int jx, Value value) {
14.311
14.312 - if (LEMON_glp(get_num_cols)(lp) < LEMON_glp(get_num_rows)(lp)) {
14.313 + if (glp_get_num_cols(lp) < glp_get_num_rows(lp)) {
14.314
14.315 - int length=LEMON_glp(get_mat_row)(lp, ix, 0, 0);
14.316 + int length = glp_get_mat_row(lp, ix, 0, 0);
14.317
14.318 - std::vector<int> indices(length + 2);
14.319 + std::vector<int> indexes(length + 2);
14.320 std::vector<Value> values(length + 2);
14.321
14.322 - LEMON_glp(get_mat_row)(lp, ix, &indices[0], &values[0]);
14.323 + glp_get_mat_row(lp, ix, &indexes.front(), &values.front());
14.324
14.325 //The following code does not suppose that the elements of the
14.326 - //array indices are sorted
14.327 - bool found=false;
14.328 - for (int i = 1; i <= length; ++i) {
14.329 - if (indices[i]==jx){
14.330 - found=true;
14.331 - values[i]=value;
14.332 + //array indexes are sorted
14.333 + bool found = false;
14.334 + for (int i = 1; i <= length; ++i) {
14.335 + if (indexes[i] == jx) {
14.336 + found = true;
14.337 + values[i] = value;
14.338 break;
14.339 }
14.340 }
14.341 - if (!found){
14.342 + if (!found) {
14.343 ++length;
14.344 - indices[length]=jx;
14.345 - values[length]=value;
14.346 + indexes[length] = jx;
14.347 + values[length] = value;
14.348 }
14.349
14.350 - LEMON_glp(set_mat_row)(lp, ix, length, &indices[0], &values[0]);
14.351 + glp_set_mat_row(lp, ix, length, &indexes.front(), &values.front());
14.352
14.353 } else {
14.354
14.355 - int length=LEMON_glp(get_mat_col)(lp, jx, 0, 0);
14.356 + int length = glp_get_mat_col(lp, jx, 0, 0);
14.357
14.358 - std::vector<int> indices(length + 2);
14.359 + std::vector<int> indexes(length + 2);
14.360 std::vector<Value> values(length + 2);
14.361
14.362 - LEMON_glp(get_mat_col)(lp, jx, &indices[0], &values[0]);
14.363 + glp_get_mat_col(lp, jx, &indexes.front(), &values.front());
14.364
14.365 //The following code does not suppose that the elements of the
14.366 - //array indices are sorted
14.367 - bool found=false;
14.368 + //array indexes are sorted
14.369 + bool found = false;
14.370 for (int i = 1; i <= length; ++i) {
14.371 - if (indices[i]==ix){
14.372 - found=true;
14.373 - values[i]=value;
14.374 + if (indexes[i] == ix) {
14.375 + found = true;
14.376 + values[i] = value;
14.377 break;
14.378 }
14.379 }
14.380 - if (!found){
14.381 + if (!found) {
14.382 ++length;
14.383 - indices[length]=ix;
14.384 - values[length]=value;
14.385 + indexes[length] = ix;
14.386 + values[length] = value;
14.387 }
14.388
14.389 - LEMON_glp(set_mat_col)(lp, jx, length, &indices[0], &values[0]);
14.390 + glp_set_mat_col(lp, jx, length, &indexes.front(), &values.front());
14.391 }
14.392
14.393 - solved = false;
14.394 }
14.395
14.396 - LpGlpk::Value LpGlpk::_getCoeff(int ix, int jx) const
14.397 - {
14.398 + GlpkBase::Value GlpkBase::_getCoeff(int ix, int jx) const {
14.399
14.400 - int length=LEMON_glp(get_mat_row)(lp, ix, 0, 0);
14.401 + int length = glp_get_mat_row(lp, ix, 0, 0);
14.402
14.403 - std::vector<int> indices(length + 1);
14.404 + std::vector<int> indexes(length + 1);
14.405 std::vector<Value> values(length + 1);
14.406
14.407 - LEMON_glp(get_mat_row)(lp, ix, &indices[0], &values[0]);
14.408 + glp_get_mat_row(lp, ix, &indexes.front(), &values.front());
14.409
14.410 - //The following code does not suppose that the elements of the
14.411 - //array indices are sorted
14.412 - for (int i = 1; i <= length; ++i) {
14.413 - if (indices[i]==jx){
14.414 + for (int i = 1; i <= length; ++i) {
14.415 + if (indexes[i] == jx) {
14.416 return values[i];
14.417 }
14.418 }
14.419 +
14.420 return 0;
14.421 + }
14.422 +
14.423 + void GlpkBase::_setColLowerBound(int i, Value lo) {
14.424 + LEMON_ASSERT(lo != INF, "Invalid bound");
14.425 +
14.426 + int b = glp_get_col_type(lp, i);
14.427 + double up = glp_get_col_ub(lp, i);
14.428 + if (lo == -INF) {
14.429 + switch (b) {
14.430 + case GLP_FR:
14.431 + case GLP_LO:
14.432 + glp_set_col_bnds(lp, i, GLP_FR, lo, up);
14.433 + break;
14.434 + case GLP_UP:
14.435 + break;
14.436 + case GLP_DB:
14.437 + case GLP_FX:
14.438 + glp_set_col_bnds(lp, i, GLP_UP, lo, up);
14.439 + break;
14.440 + default:
14.441 + break;
14.442 + }
14.443 + } else {
14.444 + switch (b) {
14.445 + case GLP_FR:
14.446 + case GLP_LO:
14.447 + glp_set_col_bnds(lp, i, GLP_LO, lo, up);
14.448 + break;
14.449 + case GLP_UP:
14.450 + case GLP_DB:
14.451 + case GLP_FX:
14.452 + if (lo == up)
14.453 + glp_set_col_bnds(lp, i, GLP_FX, lo, up);
14.454 + else
14.455 + glp_set_col_bnds(lp, i, GLP_DB, lo, up);
14.456 + break;
14.457 + default:
14.458 + break;
14.459 + }
14.460 + }
14.461 + }
14.462 +
14.463 + GlpkBase::Value GlpkBase::_getColLowerBound(int i) const {
14.464 + int b = glp_get_col_type(lp, i);
14.465 + switch (b) {
14.466 + case GLP_LO:
14.467 + case GLP_DB:
14.468 + case GLP_FX:
14.469 + return glp_get_col_lb(lp, i);
14.470 + default:
14.471 + return -INF;
14.472 + }
14.473 + }
14.474 +
14.475 + void GlpkBase::_setColUpperBound(int i, Value up) {
14.476 + LEMON_ASSERT(up != -INF, "Invalid bound");
14.477 +
14.478 + int b = glp_get_col_type(lp, i);
14.479 + double lo = glp_get_col_lb(lp, i);
14.480 + if (up == INF) {
14.481 + switch (b) {
14.482 + case GLP_FR:
14.483 + case GLP_LO:
14.484 + break;
14.485 + case GLP_UP:
14.486 + glp_set_col_bnds(lp, i, GLP_FR, lo, up);
14.487 + break;
14.488 + case GLP_DB:
14.489 + case GLP_FX:
14.490 + glp_set_col_bnds(lp, i, GLP_LO, lo, up);
14.491 + break;
14.492 + default:
14.493 + break;
14.494 + }
14.495 + } else {
14.496 + switch (b) {
14.497 + case GLP_FR:
14.498 + glp_set_col_bnds(lp, i, GLP_UP, lo, up);
14.499 + break;
14.500 + case GLP_UP:
14.501 + glp_set_col_bnds(lp, i, GLP_UP, lo, up);
14.502 + break;
14.503 + case GLP_LO:
14.504 + case GLP_DB:
14.505 + case GLP_FX:
14.506 + if (lo == up)
14.507 + glp_set_col_bnds(lp, i, GLP_FX, lo, up);
14.508 + else
14.509 + glp_set_col_bnds(lp, i, GLP_DB, lo, up);
14.510 + break;
14.511 + default:
14.512 + break;
14.513 + }
14.514 + }
14.515
14.516 }
14.517
14.518 -
14.519 - void LpGlpk::_setColLowerBound(int i, Value lo)
14.520 - {
14.521 - if (lo==INF) {
14.522 - //FIXME error
14.523 - }
14.524 - int b=LEMON_glp(get_col_type)(lp, i);
14.525 - double up=LEMON_glp(get_col_ub)(lp, i);
14.526 - if (lo==-INF) {
14.527 + GlpkBase::Value GlpkBase::_getColUpperBound(int i) const {
14.528 + int b = glp_get_col_type(lp, i);
14.529 switch (b) {
14.530 - case LEMON_GLP(FR):
14.531 - case LEMON_GLP(LO):
14.532 - LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(FR), lo, up);
14.533 - break;
14.534 - case LEMON_GLP(UP):
14.535 - break;
14.536 - case LEMON_GLP(DB):
14.537 - case LEMON_GLP(FX):
14.538 - LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(UP), lo, up);
14.539 - break;
14.540 - default: ;
14.541 - //FIXME error
14.542 - }
14.543 - } else {
14.544 - switch (b) {
14.545 - case LEMON_GLP(FR):
14.546 - case LEMON_GLP(LO):
14.547 - LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(LO), lo, up);
14.548 - break;
14.549 - case LEMON_GLP(UP):
14.550 - case LEMON_GLP(DB):
14.551 - case LEMON_GLP(FX):
14.552 - if (lo==up)
14.553 - LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(FX), lo, up);
14.554 - else
14.555 - LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(DB), lo, up);
14.556 - break;
14.557 - default: ;
14.558 - //FIXME error
14.559 - }
14.560 - }
14.561 -
14.562 - solved = false;
14.563 - }
14.564 -
14.565 - LpGlpk::Value LpGlpk::_getColLowerBound(int i) const
14.566 - {
14.567 - int b=LEMON_glp(get_col_type)(lp, i);
14.568 - switch (b) {
14.569 - case LEMON_GLP(LO):
14.570 - case LEMON_GLP(DB):
14.571 - case LEMON_GLP(FX):
14.572 - return LEMON_glp(get_col_lb)(lp, i);
14.573 - default: ;
14.574 - return -INF;
14.575 - }
14.576 - }
14.577 -
14.578 - void LpGlpk::_setColUpperBound(int i, Value up)
14.579 - {
14.580 - if (up==-INF) {
14.581 - //FIXME error
14.582 - }
14.583 - int b=LEMON_glp(get_col_type)(lp, i);
14.584 - double lo=LEMON_glp(get_col_lb)(lp, i);
14.585 - if (up==INF) {
14.586 - switch (b) {
14.587 - case LEMON_GLP(FR):
14.588 - case LEMON_GLP(LO):
14.589 - break;
14.590 - case LEMON_GLP(UP):
14.591 - LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(FR), lo, up);
14.592 - break;
14.593 - case LEMON_GLP(DB):
14.594 - case LEMON_GLP(FX):
14.595 - LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(LO), lo, up);
14.596 - break;
14.597 - default: ;
14.598 - //FIXME error
14.599 - }
14.600 - } else {
14.601 - switch (b) {
14.602 - case LEMON_GLP(FR):
14.603 - LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(UP), lo, up);
14.604 - break;
14.605 - case LEMON_GLP(UP):
14.606 - LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(UP), lo, up);
14.607 - break;
14.608 - case LEMON_GLP(LO):
14.609 - case LEMON_GLP(DB):
14.610 - case LEMON_GLP(FX):
14.611 - if (lo==up)
14.612 - LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(FX), lo, up);
14.613 - else
14.614 - LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(DB), lo, up);
14.615 - break;
14.616 - default: ;
14.617 - //FIXME error
14.618 - }
14.619 - }
14.620 -
14.621 - solved = false;
14.622 - }
14.623 -
14.624 - LpGlpk::Value LpGlpk::_getColUpperBound(int i) const
14.625 - {
14.626 - int b=LEMON_glp(get_col_type)(lp, i);
14.627 - switch (b) {
14.628 - case LEMON_GLP(UP):
14.629 - case LEMON_GLP(DB):
14.630 - case LEMON_GLP(FX):
14.631 - return LEMON_glp(get_col_ub)(lp, i);
14.632 - default: ;
14.633 + case GLP_UP:
14.634 + case GLP_DB:
14.635 + case GLP_FX:
14.636 + return glp_get_col_ub(lp, i);
14.637 + default:
14.638 return INF;
14.639 }
14.640 }
14.641
14.642 - void LpGlpk::_setRowBounds(int i, Value lb, Value ub)
14.643 - {
14.644 - //Bad parameter
14.645 - if (lb==INF || ub==-INF) {
14.646 - //FIXME error
14.647 - }
14.648 + void GlpkBase::_setRowLowerBound(int i, Value lo) {
14.649 + LEMON_ASSERT(lo != INF, "Invalid bound");
14.650
14.651 - if (lb == -INF){
14.652 - if (ub == INF){
14.653 - LEMON_glp(set_row_bnds)(lp, i, LEMON_GLP(FR), lb, ub);
14.654 + int b = glp_get_row_type(lp, i);
14.655 + double up = glp_get_row_ub(lp, i);
14.656 + if (lo == -INF) {
14.657 + switch (b) {
14.658 + case GLP_FR:
14.659 + case GLP_LO:
14.660 + glp_set_row_bnds(lp, i, GLP_FR, lo, up);
14.661 + break;
14.662 + case GLP_UP:
14.663 + break;
14.664 + case GLP_DB:
14.665 + case GLP_FX:
14.666 + glp_set_row_bnds(lp, i, GLP_UP, lo, up);
14.667 + break;
14.668 + default:
14.669 + break;
14.670 }
14.671 - else{
14.672 - LEMON_glp(set_row_bnds)(lp, i, LEMON_GLP(UP), lb, ub);
14.673 + } else {
14.674 + switch (b) {
14.675 + case GLP_FR:
14.676 + case GLP_LO:
14.677 + glp_set_row_bnds(lp, i, GLP_LO, lo, up);
14.678 + break;
14.679 + case GLP_UP:
14.680 + case GLP_DB:
14.681 + case GLP_FX:
14.682 + if (lo == up)
14.683 + glp_set_row_bnds(lp, i, GLP_FX, lo, up);
14.684 + else
14.685 + glp_set_row_bnds(lp, i, GLP_DB, lo, up);
14.686 + break;
14.687 + default:
14.688 + break;
14.689 }
14.690 }
14.691 - else{
14.692 - if (ub==INF){
14.693 - LEMON_glp(set_row_bnds)(lp, i, LEMON_GLP(LO), lb, ub);
14.694 -
14.695 - }
14.696 - else{
14.697 - if (lb == ub){
14.698 - LEMON_glp(set_row_bnds)(lp, i, LEMON_GLP(FX), lb, ub);
14.699 - }
14.700 - else{
14.701 - LEMON_glp(set_row_bnds)(lp, i, LEMON_GLP(DB), lb, ub);
14.702 - }
14.703 - }
14.704 - }
14.705 -
14.706 - solved = false;
14.707 - }
14.708 -
14.709 - void LpGlpk::_getRowBounds(int i, Value &lb, Value &ub) const
14.710 - {
14.711 -
14.712 - int b=LEMON_glp(get_row_type)(lp, i);
14.713 - switch (b) {
14.714 - case LEMON_GLP(FR):
14.715 - case LEMON_GLP(UP):
14.716 - lb = -INF;
14.717 - break;
14.718 - default:
14.719 - lb=LEMON_glp(get_row_lb)(lp, i);
14.720 - }
14.721 -
14.722 - switch (b) {
14.723 - case LEMON_GLP(FR):
14.724 - case LEMON_GLP(LO):
14.725 - ub = INF;
14.726 - break;
14.727 - default:
14.728 - ub=LEMON_glp(get_row_ub)(lp, i);
14.729 - }
14.730
14.731 }
14.732
14.733 - void LpGlpk::_setObjCoeff(int i, Value obj_coef)
14.734 - {
14.735 - //i=0 means the constant term (shift)
14.736 - LEMON_glp(set_obj_coef)(lp, i, obj_coef);
14.737 -
14.738 - solved = false;
14.739 - }
14.740 -
14.741 - LpGlpk::Value LpGlpk::_getObjCoeff(int i) const {
14.742 - //i=0 means the constant term (shift)
14.743 - return LEMON_glp(get_obj_coef)(lp, i);
14.744 - }
14.745 -
14.746 - void LpGlpk::_clearObj()
14.747 - {
14.748 - for (int i=0;i<=LEMON_glp(get_num_cols)(lp);++i){
14.749 - LEMON_glp(set_obj_coef)(lp, i, 0);
14.750 - }
14.751 -
14.752 - solved = false;
14.753 - }
14.754 -
14.755 - LpGlpk::SolveExitStatus LpGlpk::_solve()
14.756 - {
14.757 - // A way to check the problem to be solved
14.758 - //LEMON_glp(write_cpxlp(lp,"naittvan.cpx");
14.759 -
14.760 - LEMON_lpx(std_basis)(lp);
14.761 - int i = LEMON_lpx(simplex)(lp);
14.762 -
14.763 - switch (i) {
14.764 - case LEMON_LPX(E_OK):
14.765 - solved = true;
14.766 - return SOLVED;
14.767 + GlpkBase::Value GlpkBase::_getRowLowerBound(int i) const {
14.768 + int b = glp_get_row_type(lp, i);
14.769 + switch (b) {
14.770 + case GLP_LO:
14.771 + case GLP_DB:
14.772 + case GLP_FX:
14.773 + return glp_get_row_lb(lp, i);
14.774 default:
14.775 - return UNSOLVED;
14.776 + return -INF;
14.777 }
14.778 }
14.779
14.780 - LpGlpk::Value LpGlpk::_getPrimal(int i) const
14.781 - {
14.782 - return LEMON_glp(get_col_prim)(lp,i);
14.783 - }
14.784 + void GlpkBase::_setRowUpperBound(int i, Value up) {
14.785 + LEMON_ASSERT(up != -INF, "Invalid bound");
14.786
14.787 - LpGlpk::Value LpGlpk::_getDual(int i) const
14.788 - {
14.789 - return LEMON_glp(get_row_dual)(lp,i);
14.790 - }
14.791 -
14.792 - LpGlpk::Value LpGlpk::_getPrimalValue() const
14.793 - {
14.794 - return LEMON_glp(get_obj_val)(lp);
14.795 - }
14.796 - bool LpGlpk::_isBasicCol(int i) const
14.797 - {
14.798 - return (LEMON_glp(get_col_stat)(lp, i)==LEMON_GLP(BS));
14.799 - }
14.800 -
14.801 -
14.802 - LpGlpk::SolutionStatus LpGlpk::_getPrimalStatus() const
14.803 - {
14.804 - if (!solved) return UNDEFINED;
14.805 - int stat= LEMON_lpx(get_status)(lp);
14.806 - switch (stat) {
14.807 - case LEMON_LPX(UNDEF)://Undefined (no solve has been run yet)
14.808 - return UNDEFINED;
14.809 - case LEMON_LPX(NOFEAS)://There is no feasible solution (primal, I guess)
14.810 - case LEMON_LPX(INFEAS)://Infeasible
14.811 - return INFEASIBLE;
14.812 - case LEMON_LPX(UNBND)://Unbounded
14.813 - return INFINITE;
14.814 - case LEMON_LPX(FEAS)://Feasible
14.815 - return FEASIBLE;
14.816 - case LEMON_LPX(OPT)://Feasible
14.817 - return OPTIMAL;
14.818 - default:
14.819 - return UNDEFINED; //to avoid gcc warning
14.820 - //FIXME error
14.821 + int b = glp_get_row_type(lp, i);
14.822 + double lo = glp_get_row_lb(lp, i);
14.823 + if (up == INF) {
14.824 + switch (b) {
14.825 + case GLP_FR:
14.826 + case GLP_LO:
14.827 + break;
14.828 + case GLP_UP:
14.829 + glp_set_row_bnds(lp, i, GLP_FR, lo, up);
14.830 + break;
14.831 + case GLP_DB:
14.832 + case GLP_FX:
14.833 + glp_set_row_bnds(lp, i, GLP_LO, lo, up);
14.834 + break;
14.835 + default:
14.836 + break;
14.837 + }
14.838 + } else {
14.839 + switch (b) {
14.840 + case GLP_FR:
14.841 + glp_set_row_bnds(lp, i, GLP_UP, lo, up);
14.842 + break;
14.843 + case GLP_UP:
14.844 + glp_set_row_bnds(lp, i, GLP_UP, lo, up);
14.845 + break;
14.846 + case GLP_LO:
14.847 + case GLP_DB:
14.848 + case GLP_FX:
14.849 + if (lo == up)
14.850 + glp_set_row_bnds(lp, i, GLP_FX, lo, up);
14.851 + else
14.852 + glp_set_row_bnds(lp, i, GLP_DB, lo, up);
14.853 + break;
14.854 + default:
14.855 + break;
14.856 + }
14.857 }
14.858 }
14.859
14.860 - LpGlpk::SolutionStatus LpGlpk::_getDualStatus() const
14.861 - {
14.862 - if (!solved) return UNDEFINED;
14.863 - switch (LEMON_lpx(get_dual_stat)(lp)) {
14.864 - case LEMON_LPX(D_UNDEF)://Undefined (no solve has been run yet)
14.865 - return UNDEFINED;
14.866 - case LEMON_LPX(D_NOFEAS)://There is no dual feasible solution
14.867 -// case LEMON_LPX(D_INFEAS://Infeasible
14.868 - return INFEASIBLE;
14.869 - case LEMON_LPX(D_FEAS)://Feasible
14.870 - switch (LEMON_lpx(get_status)(lp)) {
14.871 - case LEMON_LPX(NOFEAS):
14.872 - return INFINITE;
14.873 - case LEMON_LPX(OPT):
14.874 - return OPTIMAL;
14.875 - default:
14.876 - return FEASIBLE;
14.877 - }
14.878 + GlpkBase::Value GlpkBase::_getRowUpperBound(int i) const {
14.879 + int b = glp_get_row_type(lp, i);
14.880 + switch (b) {
14.881 + case GLP_UP:
14.882 + case GLP_DB:
14.883 + case GLP_FX:
14.884 + return glp_get_row_ub(lp, i);
14.885 default:
14.886 - return UNDEFINED; //to avoid gcc warning
14.887 - //FIXME error
14.888 + return INF;
14.889 }
14.890 }
14.891
14.892 - LpGlpk::ProblemTypes LpGlpk::_getProblemType() const
14.893 - {
14.894 - if (!solved) return UNKNOWN;
14.895 - //int stat= LEMON_glp(get_status(lp);
14.896 - int statp= LEMON_lpx(get_prim_stat)(lp);
14.897 - int statd= LEMON_lpx(get_dual_stat)(lp);
14.898 - if (statp==LEMON_LPX(P_FEAS) && statd==LEMON_LPX(D_FEAS))
14.899 - return PRIMAL_DUAL_FEASIBLE;
14.900 - if (statp==LEMON_LPX(P_FEAS) && statd==LEMON_LPX(D_NOFEAS))
14.901 - return PRIMAL_FEASIBLE_DUAL_INFEASIBLE;
14.902 - if (statp==LEMON_LPX(P_NOFEAS) && statd==LEMON_LPX(D_FEAS))
14.903 - return PRIMAL_INFEASIBLE_DUAL_FEASIBLE;
14.904 - if (statp==LEMON_LPX(P_NOFEAS) && statd==LEMON_LPX(D_NOFEAS))
14.905 - return PRIMAL_DUAL_INFEASIBLE;
14.906 - //In all other cases
14.907 - return UNKNOWN;
14.908 + void GlpkBase::_setObjCoeffs(ExprIterator b, ExprIterator e) {
14.909 + for (int i = 1; i <= glp_get_num_cols(lp); ++i) {
14.910 + glp_set_obj_coef(lp, i, 0.0);
14.911 + }
14.912 + for (ExprIterator it = b; it != e; ++it) {
14.913 + glp_set_obj_coef(lp, it->first, it->second);
14.914 + }
14.915 }
14.916
14.917 - void LpGlpk::_setMax()
14.918 - {
14.919 - solved = false;
14.920 - LEMON_glp(set_obj_dir)(lp, LEMON_GLP(MAX));
14.921 + void GlpkBase::_getObjCoeffs(InsertIterator b) const {
14.922 + for (int i = 1; i <= glp_get_num_cols(lp); ++i) {
14.923 + Value val = glp_get_obj_coef(lp, i);
14.924 + if (val != 0.0) {
14.925 + *b = std::make_pair(i, val);
14.926 + ++b;
14.927 + }
14.928 + }
14.929 }
14.930
14.931 - void LpGlpk::_setMin()
14.932 - {
14.933 - solved = false;
14.934 - LEMON_glp(set_obj_dir)(lp, LEMON_GLP(MIN));
14.935 + void GlpkBase::_setObjCoeff(int i, Value obj_coef) {
14.936 + //i = 0 means the constant term (shift)
14.937 + glp_set_obj_coef(lp, i, obj_coef);
14.938 }
14.939
14.940 - bool LpGlpk::_isMax() const
14.941 - {
14.942 - return (LEMON_glp(get_obj_dir)(lp)==LEMON_GLP(MAX));
14.943 + GlpkBase::Value GlpkBase::_getObjCoeff(int i) const {
14.944 + //i = 0 means the constant term (shift)
14.945 + return glp_get_obj_coef(lp, i);
14.946 }
14.947
14.948 -
14.949 -
14.950 - void LpGlpk::messageLevel(int m)
14.951 - {
14.952 - LEMON_lpx(set_int_parm)(lp, LEMON_LPX(K_MSGLEV), m);
14.953 + void GlpkBase::_setSense(GlpkBase::Sense sense) {
14.954 + switch (sense) {
14.955 + case MIN:
14.956 + glp_set_obj_dir(lp, GLP_MIN);
14.957 + break;
14.958 + case MAX:
14.959 + glp_set_obj_dir(lp, GLP_MAX);
14.960 + break;
14.961 + }
14.962 }
14.963
14.964 - void LpGlpk::presolver(bool b)
14.965 - {
14.966 - LEMON_lpx(set_int_parm)(lp, LEMON_LPX(K_PRESOL), b);
14.967 + GlpkBase::Sense GlpkBase::_getSense() const {
14.968 + switch(glp_get_obj_dir(lp)) {
14.969 + case GLP_MIN:
14.970 + return MIN;
14.971 + case GLP_MAX:
14.972 + return MAX;
14.973 + default:
14.974 + LEMON_ASSERT(false, "Wrong sense");
14.975 + return GlpkBase::Sense();
14.976 + }
14.977 }
14.978
14.979 + void GlpkBase::_clear() {
14.980 + glp_erase_prob(lp);
14.981 + rows.clear();
14.982 + cols.clear();
14.983 + }
14.984 +
14.985 + // LpGlpk members
14.986 +
14.987 + LpGlpk::LpGlpk()
14.988 + : LpBase(), GlpkBase(), LpSolver() {
14.989 + messageLevel(MESSAGE_NO_OUTPUT);
14.990 + }
14.991 +
14.992 + LpGlpk::LpGlpk(const LpGlpk& other)
14.993 + : LpBase(other), GlpkBase(other), LpSolver(other) {
14.994 + messageLevel(MESSAGE_NO_OUTPUT);
14.995 + }
14.996 +
14.997 + LpGlpk* LpGlpk::_newSolver() const { return new LpGlpk; }
14.998 + LpGlpk* LpGlpk::_cloneSolver() const { return new LpGlpk(*this); }
14.999 +
14.1000 + const char* LpGlpk::_solverName() const { return "LpGlpk"; }
14.1001 +
14.1002 + void LpGlpk::_clear_temporals() {
14.1003 + _primal_ray.clear();
14.1004 + _dual_ray.clear();
14.1005 + }
14.1006 +
14.1007 + LpGlpk::SolveExitStatus LpGlpk::_solve() {
14.1008 + return solvePrimal();
14.1009 + }
14.1010 +
14.1011 + LpGlpk::SolveExitStatus LpGlpk::solvePrimal() {
14.1012 + _clear_temporals();
14.1013 +
14.1014 + glp_smcp smcp;
14.1015 + glp_init_smcp(&smcp);
14.1016 +
14.1017 + switch (_message_level) {
14.1018 + case MESSAGE_NO_OUTPUT:
14.1019 + smcp.msg_lev = GLP_MSG_OFF;
14.1020 + break;
14.1021 + case MESSAGE_ERROR_MESSAGE:
14.1022 + smcp.msg_lev = GLP_MSG_ERR;
14.1023 + break;
14.1024 + case MESSAGE_NORMAL_OUTPUT:
14.1025 + smcp.msg_lev = GLP_MSG_ON;
14.1026 + break;
14.1027 + case MESSAGE_FULL_OUTPUT:
14.1028 + smcp.msg_lev = GLP_MSG_ALL;
14.1029 + break;
14.1030 + }
14.1031 +
14.1032 + if (glp_simplex(lp, &smcp) != 0) return UNSOLVED;
14.1033 + return SOLVED;
14.1034 + }
14.1035 +
14.1036 + LpGlpk::SolveExitStatus LpGlpk::solveDual() {
14.1037 + _clear_temporals();
14.1038 +
14.1039 + glp_smcp smcp;
14.1040 + glp_init_smcp(&smcp);
14.1041 +
14.1042 + switch (_message_level) {
14.1043 + case MESSAGE_NO_OUTPUT:
14.1044 + smcp.msg_lev = GLP_MSG_OFF;
14.1045 + break;
14.1046 + case MESSAGE_ERROR_MESSAGE:
14.1047 + smcp.msg_lev = GLP_MSG_ERR;
14.1048 + break;
14.1049 + case MESSAGE_NORMAL_OUTPUT:
14.1050 + smcp.msg_lev = GLP_MSG_ON;
14.1051 + break;
14.1052 + case MESSAGE_FULL_OUTPUT:
14.1053 + smcp.msg_lev = GLP_MSG_ALL;
14.1054 + break;
14.1055 + }
14.1056 + smcp.meth = GLP_DUAL;
14.1057 +
14.1058 + if (glp_simplex(lp, &smcp) != 0) return UNSOLVED;
14.1059 + return SOLVED;
14.1060 + }
14.1061 +
14.1062 + LpGlpk::Value LpGlpk::_getPrimal(int i) const {
14.1063 + return glp_get_col_prim(lp, i);
14.1064 + }
14.1065 +
14.1066 + LpGlpk::Value LpGlpk::_getDual(int i) const {
14.1067 + return glp_get_row_dual(lp, i);
14.1068 + }
14.1069 +
14.1070 + LpGlpk::Value LpGlpk::_getPrimalValue() const {
14.1071 + return glp_get_obj_val(lp);
14.1072 + }
14.1073 +
14.1074 + LpGlpk::VarStatus LpGlpk::_getColStatus(int i) const {
14.1075 + switch (glp_get_col_stat(lp, i)) {
14.1076 + case GLP_BS:
14.1077 + return BASIC;
14.1078 + case GLP_UP:
14.1079 + return UPPER;
14.1080 + case GLP_LO:
14.1081 + return LOWER;
14.1082 + case GLP_NF:
14.1083 + return FREE;
14.1084 + case GLP_NS:
14.1085 + return FIXED;
14.1086 + default:
14.1087 + LEMON_ASSERT(false, "Wrong column status");
14.1088 + return LpGlpk::VarStatus();
14.1089 + }
14.1090 + }
14.1091 +
14.1092 + LpGlpk::VarStatus LpGlpk::_getRowStatus(int i) const {
14.1093 + switch (glp_get_row_stat(lp, i)) {
14.1094 + case GLP_BS:
14.1095 + return BASIC;
14.1096 + case GLP_UP:
14.1097 + return UPPER;
14.1098 + case GLP_LO:
14.1099 + return LOWER;
14.1100 + case GLP_NF:
14.1101 + return FREE;
14.1102 + case GLP_NS:
14.1103 + return FIXED;
14.1104 + default:
14.1105 + LEMON_ASSERT(false, "Wrong row status");
14.1106 + return LpGlpk::VarStatus();
14.1107 + }
14.1108 + }
14.1109 +
14.1110 + LpGlpk::Value LpGlpk::_getPrimalRay(int i) const {
14.1111 + if (_primal_ray.empty()) {
14.1112 + int row_num = glp_get_num_rows(lp);
14.1113 + int col_num = glp_get_num_cols(lp);
14.1114 +
14.1115 + _primal_ray.resize(col_num + 1, 0.0);
14.1116 +
14.1117 + int index = glp_get_unbnd_ray(lp);
14.1118 + if (index != 0) {
14.1119 + // The primal ray is found in primal simplex second phase
14.1120 + LEMON_ASSERT((index <= row_num ? glp_get_row_stat(lp, index) :
14.1121 + glp_get_col_stat(lp, index - row_num)) != GLP_BS,
14.1122 + "Wrong primal ray");
14.1123 +
14.1124 + bool negate = glp_get_obj_dir(lp) == GLP_MAX;
14.1125 +
14.1126 + if (index > row_num) {
14.1127 + _primal_ray[index - row_num] = 1.0;
14.1128 + if (glp_get_col_dual(lp, index - row_num) > 0) {
14.1129 + negate = !negate;
14.1130 + }
14.1131 + } else {
14.1132 + if (glp_get_row_dual(lp, index) > 0) {
14.1133 + negate = !negate;
14.1134 + }
14.1135 + }
14.1136 +
14.1137 + std::vector<int> ray_indexes(row_num + 1);
14.1138 + std::vector<Value> ray_values(row_num + 1);
14.1139 + int ray_length = glp_eval_tab_col(lp, index, &ray_indexes.front(),
14.1140 + &ray_values.front());
14.1141 +
14.1142 + for (int i = 1; i <= ray_length; ++i) {
14.1143 + if (ray_indexes[i] > row_num) {
14.1144 + _primal_ray[ray_indexes[i] - row_num] = ray_values[i];
14.1145 + }
14.1146 + }
14.1147 +
14.1148 + if (negate) {
14.1149 + for (int i = 1; i <= col_num; ++i) {
14.1150 + _primal_ray[i] = - _primal_ray[i];
14.1151 + }
14.1152 + }
14.1153 + } else {
14.1154 + for (int i = 1; i <= col_num; ++i) {
14.1155 + _primal_ray[i] = glp_get_col_prim(lp, i);
14.1156 + }
14.1157 + }
14.1158 + }
14.1159 + return _primal_ray[i];
14.1160 + }
14.1161 +
14.1162 + LpGlpk::Value LpGlpk::_getDualRay(int i) const {
14.1163 + if (_dual_ray.empty()) {
14.1164 + int row_num = glp_get_num_rows(lp);
14.1165 +
14.1166 + _dual_ray.resize(row_num + 1, 0.0);
14.1167 +
14.1168 + int index = glp_get_unbnd_ray(lp);
14.1169 + if (index != 0) {
14.1170 + // The dual ray is found in dual simplex second phase
14.1171 + LEMON_ASSERT((index <= row_num ? glp_get_row_stat(lp, index) :
14.1172 + glp_get_col_stat(lp, index - row_num)) == GLP_BS,
14.1173 +
14.1174 + "Wrong dual ray");
14.1175 +
14.1176 + int idx;
14.1177 + bool negate = false;
14.1178 +
14.1179 + if (index > row_num) {
14.1180 + idx = glp_get_col_bind(lp, index - row_num);
14.1181 + if (glp_get_col_prim(lp, index - row_num) >
14.1182 + glp_get_col_ub(lp, index - row_num)) {
14.1183 + negate = true;
14.1184 + }
14.1185 + } else {
14.1186 + idx = glp_get_row_bind(lp, index);
14.1187 + if (glp_get_row_prim(lp, index) > glp_get_row_ub(lp, index)) {
14.1188 + negate = true;
14.1189 + }
14.1190 + }
14.1191 +
14.1192 + _dual_ray[idx] = negate ? - 1.0 : 1.0;
14.1193 +
14.1194 + glp_btran(lp, &_dual_ray.front());
14.1195 + } else {
14.1196 + double eps = 1e-7;
14.1197 + // The dual ray is found in primal simplex first phase
14.1198 + // We assume that the glpk minimizes the slack to get feasible solution
14.1199 + for (int i = 1; i <= row_num; ++i) {
14.1200 + int index = glp_get_bhead(lp, i);
14.1201 + if (index <= row_num) {
14.1202 + double res = glp_get_row_prim(lp, index);
14.1203 + if (res > glp_get_row_ub(lp, index) + eps) {
14.1204 + _dual_ray[i] = -1;
14.1205 + } else if (res < glp_get_row_lb(lp, index) - eps) {
14.1206 + _dual_ray[i] = 1;
14.1207 + } else {
14.1208 + _dual_ray[i] = 0;
14.1209 + }
14.1210 + _dual_ray[i] *= glp_get_rii(lp, index);
14.1211 + } else {
14.1212 + double res = glp_get_col_prim(lp, index - row_num);
14.1213 + if (res > glp_get_col_ub(lp, index - row_num) + eps) {
14.1214 + _dual_ray[i] = -1;
14.1215 + } else if (res < glp_get_col_lb(lp, index - row_num) - eps) {
14.1216 + _dual_ray[i] = 1;
14.1217 + } else {
14.1218 + _dual_ray[i] = 0;
14.1219 + }
14.1220 + _dual_ray[i] /= glp_get_sjj(lp, index - row_num);
14.1221 + }
14.1222 + }
14.1223 +
14.1224 + glp_btran(lp, &_dual_ray.front());
14.1225 +
14.1226 + for (int i = 1; i <= row_num; ++i) {
14.1227 + _dual_ray[i] /= glp_get_rii(lp, i);
14.1228 + }
14.1229 + }
14.1230 + }
14.1231 + return _dual_ray[i];
14.1232 + }
14.1233 +
14.1234 + LpGlpk::ProblemType LpGlpk::_getPrimalType() const {
14.1235 + if (glp_get_status(lp) == GLP_OPT)
14.1236 + return OPTIMAL;
14.1237 + switch (glp_get_prim_stat(lp)) {
14.1238 + case GLP_UNDEF:
14.1239 + return UNDEFINED;
14.1240 + case GLP_FEAS:
14.1241 + case GLP_INFEAS:
14.1242 + if (glp_get_dual_stat(lp) == GLP_NOFEAS) {
14.1243 + return UNBOUNDED;
14.1244 + } else {
14.1245 + return UNDEFINED;
14.1246 + }
14.1247 + case GLP_NOFEAS:
14.1248 + return INFEASIBLE;
14.1249 + default:
14.1250 + LEMON_ASSERT(false, "Wrong primal type");
14.1251 + return LpGlpk::ProblemType();
14.1252 + }
14.1253 + }
14.1254 +
14.1255 + LpGlpk::ProblemType LpGlpk::_getDualType() const {
14.1256 + if (glp_get_status(lp) == GLP_OPT)
14.1257 + return OPTIMAL;
14.1258 + switch (glp_get_dual_stat(lp)) {
14.1259 + case GLP_UNDEF:
14.1260 + return UNDEFINED;
14.1261 + case GLP_FEAS:
14.1262 + case GLP_INFEAS:
14.1263 + if (glp_get_prim_stat(lp) == GLP_NOFEAS) {
14.1264 + return UNBOUNDED;
14.1265 + } else {
14.1266 + return UNDEFINED;
14.1267 + }
14.1268 + case GLP_NOFEAS:
14.1269 + return INFEASIBLE;
14.1270 + default:
14.1271 + LEMON_ASSERT(false, "Wrong primal type");
14.1272 + return LpGlpk::ProblemType();
14.1273 + }
14.1274 + }
14.1275 +
14.1276 + void LpGlpk::presolver(bool b) {
14.1277 + lpx_set_int_parm(lp, LPX_K_PRESOL, b ? 1 : 0);
14.1278 + }
14.1279 +
14.1280 + void LpGlpk::messageLevel(MessageLevel m) {
14.1281 + _message_level = m;
14.1282 + }
14.1283 +
14.1284 + // MipGlpk members
14.1285 +
14.1286 + MipGlpk::MipGlpk()
14.1287 + : LpBase(), GlpkBase(), MipSolver() {
14.1288 + messageLevel(MESSAGE_NO_OUTPUT);
14.1289 + }
14.1290 +
14.1291 + MipGlpk::MipGlpk(const MipGlpk& other)
14.1292 + : LpBase(), GlpkBase(other), MipSolver() {
14.1293 + messageLevel(MESSAGE_NO_OUTPUT);
14.1294 + }
14.1295 +
14.1296 + void MipGlpk::_setColType(int i, MipGlpk::ColTypes col_type) {
14.1297 + switch (col_type) {
14.1298 + case INTEGER:
14.1299 + glp_set_col_kind(lp, i, GLP_IV);
14.1300 + break;
14.1301 + case REAL:
14.1302 + glp_set_col_kind(lp, i, GLP_CV);
14.1303 + break;
14.1304 + }
14.1305 + }
14.1306 +
14.1307 + MipGlpk::ColTypes MipGlpk::_getColType(int i) const {
14.1308 + switch (glp_get_col_kind(lp, i)) {
14.1309 + case GLP_IV:
14.1310 + case GLP_BV:
14.1311 + return INTEGER;
14.1312 + default:
14.1313 + return REAL;
14.1314 + }
14.1315 +
14.1316 + }
14.1317 +
14.1318 + MipGlpk::SolveExitStatus MipGlpk::_solve() {
14.1319 + glp_smcp smcp;
14.1320 + glp_init_smcp(&smcp);
14.1321 +
14.1322 + switch (_message_level) {
14.1323 + case MESSAGE_NO_OUTPUT:
14.1324 + smcp.msg_lev = GLP_MSG_OFF;
14.1325 + break;
14.1326 + case MESSAGE_ERROR_MESSAGE:
14.1327 + smcp.msg_lev = GLP_MSG_ERR;
14.1328 + break;
14.1329 + case MESSAGE_NORMAL_OUTPUT:
14.1330 + smcp.msg_lev = GLP_MSG_ON;
14.1331 + break;
14.1332 + case MESSAGE_FULL_OUTPUT:
14.1333 + smcp.msg_lev = GLP_MSG_ALL;
14.1334 + break;
14.1335 + }
14.1336 + smcp.meth = GLP_DUAL;
14.1337 +
14.1338 + if (glp_simplex(lp, &smcp) != 0) return UNSOLVED;
14.1339 + if (glp_get_status(lp) != GLP_OPT) return SOLVED;
14.1340 +
14.1341 + glp_iocp iocp;
14.1342 + glp_init_iocp(&iocp);
14.1343 +
14.1344 + switch (_message_level) {
14.1345 + case MESSAGE_NO_OUTPUT:
14.1346 + iocp.msg_lev = GLP_MSG_OFF;
14.1347 + break;
14.1348 + case MESSAGE_ERROR_MESSAGE:
14.1349 + iocp.msg_lev = GLP_MSG_ERR;
14.1350 + break;
14.1351 + case MESSAGE_NORMAL_OUTPUT:
14.1352 + iocp.msg_lev = GLP_MSG_ON;
14.1353 + break;
14.1354 + case MESSAGE_FULL_OUTPUT:
14.1355 + iocp.msg_lev = GLP_MSG_ALL;
14.1356 + break;
14.1357 + }
14.1358 +
14.1359 + if (glp_intopt(lp, &iocp) != 0) return UNSOLVED;
14.1360 + return SOLVED;
14.1361 + }
14.1362 +
14.1363 +
14.1364 + MipGlpk::ProblemType MipGlpk::_getType() const {
14.1365 + switch (glp_get_status(lp)) {
14.1366 + case GLP_OPT:
14.1367 + switch (glp_mip_status(lp)) {
14.1368 + case GLP_UNDEF:
14.1369 + return UNDEFINED;
14.1370 + case GLP_NOFEAS:
14.1371 + return INFEASIBLE;
14.1372 + case GLP_FEAS:
14.1373 + return FEASIBLE;
14.1374 + case GLP_OPT:
14.1375 + return OPTIMAL;
14.1376 + default:
14.1377 + LEMON_ASSERT(false, "Wrong problem type.");
14.1378 + return MipGlpk::ProblemType();
14.1379 + }
14.1380 + case GLP_NOFEAS:
14.1381 + return INFEASIBLE;
14.1382 + case GLP_INFEAS:
14.1383 + case GLP_FEAS:
14.1384 + if (glp_get_dual_stat(lp) == GLP_NOFEAS) {
14.1385 + return UNBOUNDED;
14.1386 + } else {
14.1387 + return UNDEFINED;
14.1388 + }
14.1389 + default:
14.1390 + LEMON_ASSERT(false, "Wrong problem type.");
14.1391 + return MipGlpk::ProblemType();
14.1392 + }
14.1393 + }
14.1394 +
14.1395 + MipGlpk::Value MipGlpk::_getSol(int i) const {
14.1396 + return glp_mip_col_val(lp, i);
14.1397 + }
14.1398 +
14.1399 + MipGlpk::Value MipGlpk::_getSolValue() const {
14.1400 + return glp_mip_obj_val(lp);
14.1401 + }
14.1402 +
14.1403 + MipGlpk* MipGlpk::_newSolver() const { return new MipGlpk; }
14.1404 + MipGlpk* MipGlpk::_cloneSolver() const {return new MipGlpk(*this); }
14.1405 +
14.1406 + const char* MipGlpk::_solverName() const { return "MipGlpk"; }
14.1407 +
14.1408 + void MipGlpk::messageLevel(MessageLevel m) {
14.1409 + _message_level = m;
14.1410 + }
14.1411
14.1412 } //END OF NAMESPACE LEMON
15.1 --- a/lemon/lp_glpk.h Tue Dec 02 21:40:33 2008 +0100
15.2 +++ b/lemon/lp_glpk.h Tue Dec 02 22:48:28 2008 +0100
15.3 @@ -35,88 +35,137 @@
15.4 namespace lemon {
15.5
15.6
15.7 - /// \brief Interface for the GLPK LP solver
15.8 + /// \brief Base interface for the GLPK LP and MIP solver
15.9 ///
15.10 - /// This class implements an interface for the GLPK LP solver.
15.11 - ///\ingroup lp_group
15.12 - class LpGlpk : virtual public LpSolverBase {
15.13 + /// This class implements the common interface of the GLPK LP and MIP solver.
15.14 + /// \ingroup lp_group
15.15 + class GlpkBase : virtual public LpBase {
15.16 protected:
15.17
15.18 typedef glp_prob LPX;
15.19 glp_prob* lp;
15.20 - bool solved;
15.21
15.22 - public:
15.23 -
15.24 - typedef LpSolverBase Parent;
15.25 -
15.26 - LpGlpk();
15.27 - LpGlpk(const LpGlpk &);
15.28 - ~LpGlpk();
15.29 + GlpkBase();
15.30 + GlpkBase(const GlpkBase&);
15.31 + virtual ~GlpkBase();
15.32
15.33 protected:
15.34 - virtual LpSolverBase* _newLp();
15.35 - virtual LpSolverBase* _copyLp();
15.36
15.37 virtual int _addCol();
15.38 virtual int _addRow();
15.39 +
15.40 virtual void _eraseCol(int i);
15.41 virtual void _eraseRow(int i);
15.42 - virtual void _getColName(int col, std::string & name) const;
15.43 - virtual void _setColName(int col, const std::string & name);
15.44 +
15.45 + virtual void _eraseColId(int i);
15.46 + virtual void _eraseRowId(int i);
15.47 +
15.48 + virtual void _getColName(int col, std::string& name) const;
15.49 + virtual void _setColName(int col, const std::string& name);
15.50 virtual int _colByName(const std::string& name) const;
15.51 - virtual void _setRowCoeffs(int i, ConstRowIterator b, ConstRowIterator e);
15.52 - virtual void _getRowCoeffs(int i, RowIterator b) const;
15.53 - virtual void _setColCoeffs(int i, ConstColIterator b, ConstColIterator e);
15.54 - virtual void _getColCoeffs(int i, ColIterator b) const;
15.55 +
15.56 + virtual void _getRowName(int row, std::string& name) const;
15.57 + virtual void _setRowName(int row, const std::string& name);
15.58 + virtual int _rowByName(const std::string& name) const;
15.59 +
15.60 + virtual void _setRowCoeffs(int i, ExprIterator b, ExprIterator e);
15.61 + virtual void _getRowCoeffs(int i, InsertIterator b) const;
15.62 +
15.63 + virtual void _setColCoeffs(int i, ExprIterator b, ExprIterator e);
15.64 + virtual void _getColCoeffs(int i, InsertIterator b) const;
15.65 +
15.66 virtual void _setCoeff(int row, int col, Value value);
15.67 virtual Value _getCoeff(int row, int col) const;
15.68
15.69 virtual void _setColLowerBound(int i, Value value);
15.70 virtual Value _getColLowerBound(int i) const;
15.71 +
15.72 virtual void _setColUpperBound(int i, Value value);
15.73 virtual Value _getColUpperBound(int i) const;
15.74
15.75 - virtual void _setRowBounds(int i, Value lower, Value upper);
15.76 - virtual void _getRowBounds(int i, Value &lb, Value &ub) const;
15.77 + virtual void _setRowLowerBound(int i, Value value);
15.78 + virtual Value _getRowLowerBound(int i) const;
15.79 +
15.80 + virtual void _setRowUpperBound(int i, Value value);
15.81 + virtual Value _getRowUpperBound(int i) const;
15.82 +
15.83 + virtual void _setObjCoeffs(ExprIterator b, ExprIterator e);
15.84 + virtual void _getObjCoeffs(InsertIterator b) const;
15.85 +
15.86 virtual void _setObjCoeff(int i, Value obj_coef);
15.87 virtual Value _getObjCoeff(int i) const;
15.88 - virtual void _clearObj();
15.89 +
15.90 + virtual void _setSense(Sense);
15.91 + virtual Sense _getSense() const;
15.92 +
15.93 + virtual void _clear();
15.94 +
15.95 + public:
15.96 +
15.97 + ///Pointer to the underlying GLPK data structure.
15.98 + LPX *lpx() {return lp;}
15.99 + ///Const pointer to the underlying GLPK data structure.
15.100 + const LPX *lpx() const {return lp;}
15.101 +
15.102 + ///Returns the constraint identifier understood by GLPK.
15.103 + int lpxRow(Row r) const { return rows(id(r)); }
15.104 +
15.105 + ///Returns the variable identifier understood by GLPK.
15.106 + int lpxCol(Col c) const { return cols(id(c)); }
15.107 +
15.108 + };
15.109 +
15.110 + /// \brief Interface for the GLPK LP solver
15.111 + ///
15.112 + /// This class implements an interface for the GLPK LP solver.
15.113 + ///\ingroup lp_group
15.114 + class LpGlpk : public GlpkBase, public LpSolver {
15.115 + public:
15.116
15.117 ///\e
15.118 + LpGlpk();
15.119 + ///\e
15.120 + LpGlpk(const LpGlpk&);
15.121 +
15.122 + private:
15.123 +
15.124 + mutable std::vector<double> _primal_ray;
15.125 + mutable std::vector<double> _dual_ray;
15.126 +
15.127 + void _clear_temporals();
15.128 +
15.129 + protected:
15.130 +
15.131 + virtual LpGlpk* _cloneSolver() const;
15.132 + virtual LpGlpk* _newSolver() const;
15.133 +
15.134 + virtual const char* _solverName() const;
15.135 +
15.136 + virtual SolveExitStatus _solve();
15.137 + virtual Value _getPrimal(int i) const;
15.138 + virtual Value _getDual(int i) const;
15.139 +
15.140 + virtual Value _getPrimalValue() const;
15.141 +
15.142 + virtual VarStatus _getColStatus(int i) const;
15.143 + virtual VarStatus _getRowStatus(int i) const;
15.144 +
15.145 + virtual Value _getPrimalRay(int i) const;
15.146 + virtual Value _getDualRay(int i) const;
15.147
15.148 ///\todo It should be clarified
15.149 ///
15.150 - virtual SolveExitStatus _solve();
15.151 - virtual Value _getPrimal(int i) const;
15.152 - virtual Value _getDual(int i) const;
15.153 - virtual Value _getPrimalValue() const;
15.154 - virtual bool _isBasicCol(int i) const;
15.155 - ///\e
15.156 -
15.157 - ///\todo It should be clarified
15.158 - ///
15.159 - virtual SolutionStatus _getPrimalStatus() const;
15.160 - virtual SolutionStatus _getDualStatus() const;
15.161 - virtual ProblemTypes _getProblemType() const;
15.162 -
15.163 - virtual void _setMax();
15.164 - virtual void _setMin();
15.165 -
15.166 - virtual bool _isMax() const;
15.167 + virtual ProblemType _getPrimalType() const;
15.168 + virtual ProblemType _getDualType() const;
15.169
15.170 public:
15.171 - ///Set the verbosity of the messages
15.172
15.173 - ///Set the verbosity of the messages
15.174 - ///
15.175 - ///\param m is the level of the messages output by the solver routines.
15.176 - ///The possible values are:
15.177 - ///- 0 --- no output (default value)
15.178 - ///- 1 --- error messages only
15.179 - ///- 2 --- normal output
15.180 - ///- 3 --- full output (includes informational messages)
15.181 - void messageLevel(int m);
15.182 + ///Solve with primal simplex
15.183 + SolveExitStatus solvePrimal();
15.184 +
15.185 + ///Solve with dual simplex
15.186 + SolveExitStatus solveDual();
15.187 +
15.188 ///Turns on or off the presolver
15.189
15.190 ///Turns on (\c b is \c true) or off (\c b is \c false) the presolver
15.191 @@ -124,15 +173,86 @@
15.192 ///The presolver is off by default.
15.193 void presolver(bool b);
15.194
15.195 - ///Pointer to the underlying GLPK data structure.
15.196 - LPX *lpx() {return lp;}
15.197 + ///Enum for \c messageLevel() parameter
15.198 + enum MessageLevel {
15.199 + /// no output (default value)
15.200 + MESSAGE_NO_OUTPUT = 0,
15.201 + /// error messages only
15.202 + MESSAGE_ERROR_MESSAGE = 1,
15.203 + /// normal output
15.204 + MESSAGE_NORMAL_OUTPUT = 2,
15.205 + /// full output (includes informational messages)
15.206 + MESSAGE_FULL_OUTPUT = 3
15.207 + };
15.208
15.209 - ///Returns the constraint identifier understood by GLPK.
15.210 - int lpxRow(Row r) { return _lpId(r); }
15.211 + private:
15.212
15.213 - ///Returns the variable identifier understood by GLPK.
15.214 - int lpxCol(Col c) { return _lpId(c); }
15.215 + MessageLevel _message_level;
15.216 +
15.217 + public:
15.218 +
15.219 + ///Set the verbosity of the messages
15.220 +
15.221 + ///Set the verbosity of the messages
15.222 + ///
15.223 + ///\param m is the level of the messages output by the solver routines.
15.224 + void messageLevel(MessageLevel m);
15.225 };
15.226 +
15.227 + /// \brief Interface for the GLPK MIP solver
15.228 + ///
15.229 + /// This class implements an interface for the GLPK MIP solver.
15.230 + ///\ingroup lp_group
15.231 + class MipGlpk : public GlpkBase, public MipSolver {
15.232 + public:
15.233 +
15.234 + ///\e
15.235 + MipGlpk();
15.236 + ///\e
15.237 + MipGlpk(const MipGlpk&);
15.238 +
15.239 + protected:
15.240 +
15.241 + virtual MipGlpk* _cloneSolver() const;
15.242 + virtual MipGlpk* _newSolver() const;
15.243 +
15.244 + virtual const char* _solverName() const;
15.245 +
15.246 + virtual ColTypes _getColType(int col) const;
15.247 + virtual void _setColType(int col, ColTypes col_type);
15.248 +
15.249 + virtual SolveExitStatus _solve();
15.250 + virtual ProblemType _getType() const;
15.251 + virtual Value _getSol(int i) const;
15.252 + virtual Value _getSolValue() const;
15.253 +
15.254 + ///Enum for \c messageLevel() parameter
15.255 + enum MessageLevel {
15.256 + /// no output (default value)
15.257 + MESSAGE_NO_OUTPUT = 0,
15.258 + /// error messages only
15.259 + MESSAGE_ERROR_MESSAGE = 1,
15.260 + /// normal output
15.261 + MESSAGE_NORMAL_OUTPUT = 2,
15.262 + /// full output (includes informational messages)
15.263 + MESSAGE_FULL_OUTPUT = 3
15.264 + };
15.265 +
15.266 + private:
15.267 +
15.268 + MessageLevel _message_level;
15.269 +
15.270 + public:
15.271 +
15.272 + ///Set the verbosity of the messages
15.273 +
15.274 + ///Set the verbosity of the messages
15.275 + ///
15.276 + ///\param m is the level of the messages output by the solver routines.
15.277 + void messageLevel(MessageLevel m);
15.278 + };
15.279 +
15.280 +
15.281 } //END OF NAMESPACE LEMON
15.282
15.283 #endif //LEMON_LP_GLPK_H
16.1 --- a/lemon/lp_skeleton.cc Tue Dec 02 21:40:33 2008 +0100
16.2 +++ b/lemon/lp_skeleton.cc Tue Dec 02 22:48:28 2008 +0100
16.3 @@ -22,166 +22,113 @@
16.4 ///\brief A skeleton file to implement LP solver interfaces
16.5 namespace lemon {
16.6
16.7 - LpSolverBase* LpSkeleton::_newLp()
16.8 - {
16.9 - LpSolverBase *tmp=0;
16.10 - return tmp;
16.11 - }
16.12 -
16.13 - LpSolverBase* LpSkeleton::_copyLp()
16.14 - {
16.15 - LpSolverBase *tmp=0;
16.16 - return tmp;
16.17 - }
16.18 -
16.19 - int LpSkeleton::_addCol()
16.20 + int SkeletonSolverBase::_addCol()
16.21 {
16.22 return ++col_num;
16.23 }
16.24
16.25 - int LpSkeleton::_addRow()
16.26 + int SkeletonSolverBase::_addRow()
16.27 {
16.28 return ++row_num;
16.29 }
16.30
16.31 - void LpSkeleton::_eraseCol(int ) {
16.32 + void SkeletonSolverBase::_eraseCol(int) {}
16.33 + void SkeletonSolverBase::_eraseRow(int) {}
16.34 +
16.35 + void SkeletonSolverBase::_getColName(int, std::string &) const {}
16.36 + void SkeletonSolverBase::_setColName(int, const std::string &) {}
16.37 + int SkeletonSolverBase::_colByName(const std::string&) const { return -1; }
16.38 +
16.39 + void SkeletonSolverBase::_getRowName(int, std::string &) const {}
16.40 + void SkeletonSolverBase::_setRowName(int, const std::string &) {}
16.41 + int SkeletonSolverBase::_rowByName(const std::string&) const { return -1; }
16.42 +
16.43 + void SkeletonSolverBase::_setRowCoeffs(int, ExprIterator, ExprIterator) {}
16.44 + void SkeletonSolverBase::_getRowCoeffs(int, InsertIterator) const {}
16.45 +
16.46 + void SkeletonSolverBase::_setColCoeffs(int, ExprIterator, ExprIterator) {}
16.47 + void SkeletonSolverBase::_getColCoeffs(int, InsertIterator) const {}
16.48 +
16.49 + void SkeletonSolverBase::_setCoeff(int, int, Value) {}
16.50 + SkeletonSolverBase::Value SkeletonSolverBase::_getCoeff(int, int) const
16.51 + { return 0; }
16.52 +
16.53 + void SkeletonSolverBase::_setColLowerBound(int, Value) {}
16.54 + SkeletonSolverBase::Value SkeletonSolverBase::_getColLowerBound(int) const
16.55 + { return 0; }
16.56 +
16.57 + void SkeletonSolverBase::_setColUpperBound(int, Value) {}
16.58 + SkeletonSolverBase::Value SkeletonSolverBase::_getColUpperBound(int) const
16.59 + { return 0; }
16.60 +
16.61 + void SkeletonSolverBase::_setRowLowerBound(int, Value) {}
16.62 + SkeletonSolverBase::Value SkeletonSolverBase::_getRowLowerBound(int) const
16.63 + { return 0; }
16.64 +
16.65 + void SkeletonSolverBase::_setRowUpperBound(int, Value) {}
16.66 + SkeletonSolverBase::Value SkeletonSolverBase::_getRowUpperBound(int) const
16.67 + { return 0; }
16.68 +
16.69 + void SkeletonSolverBase::_setObjCoeffs(ExprIterator, ExprIterator) {}
16.70 + void SkeletonSolverBase::_getObjCoeffs(InsertIterator) const {};
16.71 +
16.72 + void SkeletonSolverBase::_setObjCoeff(int, Value) {}
16.73 + SkeletonSolverBase::Value SkeletonSolverBase::_getObjCoeff(int) const
16.74 + { return 0; }
16.75 +
16.76 + void SkeletonSolverBase::_setSense(Sense) {}
16.77 + SkeletonSolverBase::Sense SkeletonSolverBase::_getSense() const
16.78 + { return MIN; }
16.79 +
16.80 + void SkeletonSolverBase::_clear() {
16.81 + row_num = col_num = 0;
16.82 }
16.83
16.84 - void LpSkeleton::_eraseRow(int) {
16.85 - }
16.86 + LpSkeleton::SolveExitStatus LpSkeleton::_solve() { return SOLVED; }
16.87
16.88 - void LpSkeleton::_getColName(int, std::string &) const {
16.89 - }
16.90 + LpSkeleton::Value LpSkeleton::_getPrimal(int) const { return 0; }
16.91 + LpSkeleton::Value LpSkeleton::_getDual(int) const { return 0; }
16.92 + LpSkeleton::Value LpSkeleton::_getPrimalValue() const { return 0; }
16.93
16.94 + LpSkeleton::Value LpSkeleton::_getPrimalRay(int) const { return 0; }
16.95 + LpSkeleton::Value LpSkeleton::_getDualRay(int) const { return 0; }
16.96
16.97 - void LpSkeleton::_setColName(int, const std::string &) {
16.98 - }
16.99 + LpSkeleton::ProblemType LpSkeleton::_getPrimalType() const
16.100 + { return UNDEFINED; }
16.101
16.102 - int LpSkeleton::_colByName(const std::string&) const { return -1; }
16.103 + LpSkeleton::ProblemType LpSkeleton::_getDualType() const
16.104 + { return UNDEFINED; }
16.105
16.106 + LpSkeleton::VarStatus LpSkeleton::_getColStatus(int) const
16.107 + { return BASIC; }
16.108
16.109 - void LpSkeleton::_setRowCoeffs(int, ConstRowIterator, ConstRowIterator) {
16.110 - }
16.111 + LpSkeleton::VarStatus LpSkeleton::_getRowStatus(int) const
16.112 + { return BASIC; }
16.113
16.114 - void LpSkeleton::_getRowCoeffs(int, RowIterator) const {
16.115 - }
16.116 + LpSkeleton* LpSkeleton::_newSolver() const
16.117 + { return static_cast<LpSkeleton*>(0); }
16.118
16.119 - void LpSkeleton::_setColCoeffs(int, ConstColIterator, ConstColIterator) {
16.120 - }
16.121 + LpSkeleton* LpSkeleton::_cloneSolver() const
16.122 + { return static_cast<LpSkeleton*>(0); }
16.123
16.124 - void LpSkeleton::_getColCoeffs(int, ColIterator) const {
16.125 - }
16.126 + const char* LpSkeleton::_solverName() const { return "LpSkeleton"; }
16.127
16.128 - void LpSkeleton::_setCoeff(int, int, Value )
16.129 - {
16.130 - }
16.131 + MipSkeleton::SolveExitStatus MipSkeleton::_solve()
16.132 + { return SOLVED; }
16.133
16.134 - LpSkeleton::Value LpSkeleton::_getCoeff(int, int) const
16.135 - {
16.136 - return 0;
16.137 - }
16.138 + MipSkeleton::Value MipSkeleton::_getSol(int) const { return 0; }
16.139 + MipSkeleton::Value MipSkeleton::_getSolValue() const { return 0; }
16.140
16.141 + MipSkeleton::ProblemType MipSkeleton::_getType() const
16.142 + { return UNDEFINED; }
16.143
16.144 - void LpSkeleton::_setColLowerBound(int, Value)
16.145 - {
16.146 - }
16.147 + MipSkeleton* MipSkeleton::_newSolver() const
16.148 + { return static_cast<MipSkeleton*>(0); }
16.149
16.150 - LpSkeleton::Value LpSkeleton::_getColLowerBound(int) const
16.151 - {
16.152 - return 0;
16.153 - }
16.154 + MipSkeleton* MipSkeleton::_cloneSolver() const
16.155 + { return static_cast<MipSkeleton*>(0); }
16.156
16.157 - void LpSkeleton::_setColUpperBound(int, Value)
16.158 - {
16.159 - }
16.160 -
16.161 - LpSkeleton::Value LpSkeleton::_getColUpperBound(int) const
16.162 - {
16.163 - return 0;
16.164 - }
16.165 -
16.166 -// void LpSkeleton::_setRowLowerBound(int, Value)
16.167 -// {
16.168 -// }
16.169 -
16.170 -// void LpSkeleton::_setRowUpperBound(int, Value)
16.171 -// {
16.172 -// }
16.173 -
16.174 - void LpSkeleton::_setRowBounds(int, Value, Value)
16.175 - {
16.176 - }
16.177 -
16.178 - void LpSkeleton::_getRowBounds(int, Value&, Value&) const
16.179 - {
16.180 - }
16.181 -
16.182 - void LpSkeleton::_setObjCoeff(int, Value)
16.183 - {
16.184 - }
16.185 -
16.186 - LpSkeleton::Value LpSkeleton::_getObjCoeff(int) const
16.187 - {
16.188 - return 0;
16.189 - }
16.190 -
16.191 - void LpSkeleton::_setMax()
16.192 - {
16.193 - }
16.194 -
16.195 - void LpSkeleton::_setMin()
16.196 - {
16.197 - }
16.198 -
16.199 - bool LpSkeleton::_isMax() const
16.200 - {
16.201 - return true;
16.202 - }
16.203 -
16.204 -
16.205 - void LpSkeleton::_clearObj()
16.206 - {
16.207 - }
16.208 -
16.209 - LpSkeleton::SolveExitStatus LpSkeleton::_solve()
16.210 - {
16.211 - return SOLVED;
16.212 - }
16.213 -
16.214 - LpSkeleton::Value LpSkeleton::_getPrimal(int) const
16.215 - {
16.216 - return 0;
16.217 - }
16.218 -
16.219 - LpSkeleton::Value LpSkeleton::_getDual(int) const
16.220 - {
16.221 - return 0;
16.222 - }
16.223 -
16.224 - LpSkeleton::Value LpSkeleton::_getPrimalValue() const
16.225 - {
16.226 - return 0;
16.227 - }
16.228 -
16.229 - LpSkeleton::SolutionStatus LpSkeleton::_getPrimalStatus() const
16.230 - {
16.231 - return UNDEFINED;
16.232 - }
16.233 -
16.234 - LpSkeleton::SolutionStatus LpSkeleton::_getDualStatus() const
16.235 - {
16.236 - return UNDEFINED;
16.237 - }
16.238 -
16.239 - LpSkeleton::ProblemTypes LpSkeleton::_getProblemType() const
16.240 - {
16.241 - return UNKNOWN;
16.242 - }
16.243 -
16.244 - bool LpSkeleton::_isBasicCol(int) const
16.245 - {
16.246 - return true;
16.247 - }
16.248 + const char* MipSkeleton::_solverName() const { return "MipSkeleton"; }
16.249
16.250 } //namespace lemon
16.251
17.1 --- a/lemon/lp_skeleton.h Tue Dec 02 21:40:33 2008 +0100
17.2 +++ b/lemon/lp_skeleton.h Tue Dec 02 22:48:28 2008 +0100
17.3 @@ -26,15 +26,14 @@
17.4 namespace lemon {
17.5
17.6 ///A skeleton class to implement LP solver interfaces
17.7 - class LpSkeleton :public LpSolverBase {
17.8 + class SkeletonSolverBase : public virtual LpBase {
17.9 int col_num,row_num;
17.10
17.11 protected:
17.12
17.13 - ///\e
17.14 - virtual LpSolverBase* _newLp();
17.15 - ///\e
17.16 - virtual LpSolverBase* _copyLp();
17.17 + SkeletonSolverBase()
17.18 + : col_num(-1), row_num(-1) {}
17.19 +
17.20 /// \e
17.21 virtual int _addCol();
17.22 /// \e
17.23 @@ -43,21 +42,29 @@
17.24 virtual void _eraseCol(int i);
17.25 /// \e
17.26 virtual void _eraseRow(int i);
17.27 +
17.28 /// \e
17.29 - virtual void _getColName(int col, std::string & name) const;
17.30 + virtual void _getColName(int col, std::string& name) const;
17.31 /// \e
17.32 - virtual void _setColName(int col, const std::string & name);
17.33 + virtual void _setColName(int col, const std::string& name);
17.34 /// \e
17.35 virtual int _colByName(const std::string& name) const;
17.36
17.37 /// \e
17.38 - virtual void _setRowCoeffs(int i, ConstRowIterator b, ConstRowIterator e);
17.39 + virtual void _getRowName(int row, std::string& name) const;
17.40 /// \e
17.41 - virtual void _getRowCoeffs(int i, RowIterator b) const;
17.42 + virtual void _setRowName(int row, const std::string& name);
17.43 /// \e
17.44 - virtual void _setColCoeffs(int i, ConstColIterator b, ConstColIterator e);
17.45 + virtual int _rowByName(const std::string& name) const;
17.46 +
17.47 /// \e
17.48 - virtual void _getColCoeffs(int i, ColIterator b) const;
17.49 + virtual void _setRowCoeffs(int i, ExprIterator b, ExprIterator e);
17.50 + /// \e
17.51 + virtual void _getRowCoeffs(int i, InsertIterator b) const;
17.52 + /// \e
17.53 + virtual void _setColCoeffs(int i, ExprIterator b, ExprIterator e);
17.54 + /// \e
17.55 + virtual void _getColCoeffs(int i, InsertIterator b) const;
17.56
17.57 /// Set one element of the coefficient matrix
17.58 virtual void _setCoeff(int row, int col, Value value);
17.59 @@ -87,42 +94,103 @@
17.60 /// Value or \ref INF.
17.61 virtual Value _getColUpperBound(int i) const;
17.62
17.63 -// /// The lower bound of a linear expression (row) have to be given by an
17.64 -// /// extended number of type Value, i.e. a finite number of type
17.65 -// /// Value or -\ref INF.
17.66 -// virtual void _setRowLowerBound(int i, Value value);
17.67 -// /// \e
17.68 -
17.69 -// /// The upper bound of a linear expression (row) have to be given by an
17.70 -// /// extended number of type Value, i.e. a finite number of type
17.71 -// /// Value or \ref INF.
17.72 -// virtual void _setRowUpperBound(int i, Value value);
17.73 -
17.74 - /// The lower and upper bound of a linear expression (row) have to be
17.75 - /// given by an
17.76 + /// The lower bound of a constraint (row) have to be given by an
17.77 /// extended number of type Value, i.e. a finite number of type
17.78 - /// Value or +/-\ref INF.
17.79 - virtual void _setRowBounds(int i, Value lb, Value ub);
17.80 + /// Value or -\ref INF.
17.81 + virtual void _setRowLowerBound(int i, Value value);
17.82 /// \e
17.83
17.84 + /// The lower bound of a constraint (row) is an
17.85 + /// extended number of type Value, i.e. a finite number of type
17.86 + /// Value or -\ref INF.
17.87 + virtual Value _getRowLowerBound(int i) const;
17.88
17.89 - /// The lower and the upper bound of
17.90 - /// a constraint (row) are
17.91 - /// extended numbers of type Value, i.e. finite numbers of type
17.92 - /// Value, -\ref INF or \ref INF.
17.93 - virtual void _getRowBounds(int i, Value &lb, Value &ub) const;
17.94 + /// The upper bound of a constraint (row) have to be given by an
17.95 + /// extended number of type Value, i.e. a finite number of type
17.96 + /// Value or \ref INF.
17.97 + virtual void _setRowUpperBound(int i, Value value);
17.98 /// \e
17.99
17.100 + /// The upper bound of a constraint (row) is an
17.101 + /// extended number of type Value, i.e. a finite number of type
17.102 + /// Value or \ref INF.
17.103 + virtual Value _getRowUpperBound(int i) const;
17.104
17.105 /// \e
17.106 - virtual void _clearObj();
17.107 + virtual void _setObjCoeffs(ExprIterator b, ExprIterator e);
17.108 + /// \e
17.109 + virtual void _getObjCoeffs(InsertIterator b) const;
17.110 +
17.111 /// \e
17.112 virtual void _setObjCoeff(int i, Value obj_coef);
17.113 -
17.114 /// \e
17.115 virtual Value _getObjCoeff(int i) const;
17.116
17.117 ///\e
17.118 + virtual void _setSense(Sense);
17.119 + ///\e
17.120 + virtual Sense _getSense() const;
17.121 +
17.122 + ///\e
17.123 + virtual void _clear();
17.124 +
17.125 + };
17.126 +
17.127 + /// \brief Interface for a skeleton LP solver
17.128 + ///
17.129 + /// This class implements an interface for a skeleton LP solver.
17.130 + ///\ingroup lp_group
17.131 + class LpSkeleton : public SkeletonSolverBase, public LpSolver {
17.132 + public:
17.133 + LpSkeleton() : SkeletonSolverBase(), LpSolver() {}
17.134 +
17.135 + protected:
17.136 +
17.137 + ///\e
17.138 + virtual SolveExitStatus _solve();
17.139 +
17.140 + ///\e
17.141 + virtual Value _getPrimal(int i) const;
17.142 + ///\e
17.143 + virtual Value _getDual(int i) const;
17.144 +
17.145 + ///\e
17.146 + virtual Value _getPrimalValue() const;
17.147 +
17.148 + ///\e
17.149 + virtual Value _getPrimalRay(int i) const;
17.150 + ///\e
17.151 + virtual Value _getDualRay(int i) const;
17.152 +
17.153 + ///\e
17.154 + virtual ProblemType _getPrimalType() const;
17.155 + ///\e
17.156 + virtual ProblemType _getDualType() const;
17.157 +
17.158 + ///\e
17.159 + virtual VarStatus _getColStatus(int i) const;
17.160 + ///\e
17.161 + virtual VarStatus _getRowStatus(int i) const;
17.162 +
17.163 + ///\e
17.164 + virtual LpSkeleton* _newSolver() const;
17.165 + ///\e
17.166 + virtual LpSkeleton* _cloneSolver() const;
17.167 + ///\e
17.168 + virtual const char* _solverName() const;
17.169 +
17.170 + };
17.171 +
17.172 + /// \brief Interface for a skeleton MIP solver
17.173 + ///
17.174 + /// This class implements an interface for a skeleton MIP solver.
17.175 + ///\ingroup lp_group
17.176 + class MipSkeleton : public SkeletonSolverBase, public MipSolver {
17.177 + public:
17.178 + MipSkeleton() : SkeletonSolverBase(), MipSolver() {}
17.179 +
17.180 + protected:
17.181 + ///\e
17.182
17.183 ///\bug Wrong interface
17.184 ///
17.185 @@ -132,50 +200,28 @@
17.186
17.187 ///\bug Wrong interface
17.188 ///
17.189 - virtual Value _getPrimal(int i) const;
17.190 + virtual Value _getSol(int i) const;
17.191
17.192 ///\e
17.193
17.194 ///\bug Wrong interface
17.195 ///
17.196 - virtual Value _getDual(int i) const;
17.197 + virtual Value _getSolValue() const;
17.198
17.199 ///\e
17.200
17.201 ///\bug Wrong interface
17.202 ///
17.203 - virtual Value _getPrimalValue() const;
17.204 + virtual ProblemType _getType() const;
17.205
17.206 ///\e
17.207 -
17.208 - ///\bug Wrong interface
17.209 - ///
17.210 - virtual SolutionStatus _getPrimalStatus() const;
17.211 -
17.212 - ////e
17.213 - virtual SolutionStatus _getDualStatus() const;
17.214 -
17.215 + virtual MipSkeleton* _newSolver() const;
17.216
17.217 ///\e
17.218 - virtual ProblemTypes _getProblemType() const;
17.219 + virtual MipSkeleton* _cloneSolver() const;
17.220 + ///\e
17.221 + virtual const char* _solverName() const;
17.222
17.223 - ///\e
17.224 - virtual void _setMax();
17.225 - ///\e
17.226 - virtual void _setMin();
17.227 -
17.228 - ///\e
17.229 - virtual bool _isMax() const;
17.230 -
17.231 -
17.232 -
17.233 - ///\e
17.234 - virtual bool _isBasicCol(int i) const;
17.235 -
17.236 -
17.237 -
17.238 - public:
17.239 - LpSkeleton() : LpSolverBase(), col_num(0), row_num(0) {}
17.240 };
17.241
17.242 } //namespace lemon
18.1 --- a/lemon/lp_soplex.cc Tue Dec 02 21:40:33 2008 +0100
18.2 +++ b/lemon/lp_soplex.cc Tue Dec 02 22:48:28 2008 +0100
18.3 @@ -16,8 +16,8 @@
18.4 *
18.5 */
18.6
18.7 -#include<iostream>
18.8 -#include<lemon/lp_soplex.h>
18.9 +#include <iostream>
18.10 +#include <lemon/lp_soplex.h>
18.11
18.12 #include <soplex/soplex.h>
18.13
18.14 @@ -26,54 +26,53 @@
18.15 ///\brief Implementation of the LEMON-SOPLEX lp solver interface.
18.16 namespace lemon {
18.17
18.18 - LpSoplex::LpSoplex() : LpSolverBase() {
18.19 - rows.setIdHandler(relocateIdHandler);
18.20 - cols.setIdHandler(relocateIdHandler);
18.21 + LpSoplex::LpSoplex() {
18.22 soplex = new soplex::SoPlex;
18.23 - solved = false;
18.24 }
18.25
18.26 LpSoplex::~LpSoplex() {
18.27 delete soplex;
18.28 }
18.29
18.30 - LpSoplex::LpSoplex(const LpSoplex& lp) : LpSolverBase() {
18.31 + LpSoplex::LpSoplex(const LpSoplex& lp) {
18.32 rows = lp.rows;
18.33 - rows.setIdHandler(relocateIdHandler);
18.34 -
18.35 cols = lp.cols;
18.36 - cols.setIdHandler(relocateIdHandler);
18.37
18.38 soplex = new soplex::SoPlex;
18.39 (*static_cast<soplex::SPxLP*>(soplex)) = *(lp.soplex);
18.40
18.41 - colNames = lp.colNames;
18.42 - invColNames = lp.invColNames;
18.43 + _col_names = lp._col_names;
18.44 + _col_names_ref = lp._col_names_ref;
18.45
18.46 - primal_value = lp.primal_value;
18.47 - dual_value = lp.dual_value;
18.48 + _row_names = lp._row_names;
18.49 + _row_names_ref = lp._row_names_ref;
18.50
18.51 }
18.52
18.53 - LpSolverBase* LpSoplex::_newLp() {
18.54 + void LpSoplex::_clear_temporals() {
18.55 + _primal_values.clear();
18.56 + _dual_values.clear();
18.57 + }
18.58 +
18.59 + LpSoplex* LpSoplex::_newSolver() const {
18.60 LpSoplex* newlp = new LpSoplex();
18.61 return newlp;
18.62 }
18.63
18.64 - LpSolverBase* LpSoplex::_copyLp() {
18.65 + LpSoplex* LpSoplex::_cloneSolver() const {
18.66 LpSoplex* newlp = new LpSoplex(*this);
18.67 return newlp;
18.68 }
18.69
18.70 + const char* LpSoplex::_solverName() const { return "LpSoplex"; }
18.71 +
18.72 int LpSoplex::_addCol() {
18.73 soplex::LPCol c;
18.74 c.setLower(-soplex::infinity);
18.75 c.setUpper(soplex::infinity);
18.76 soplex->addCol(c);
18.77
18.78 - colNames.push_back(std::string());
18.79 - primal_value.push_back(0.0);
18.80 - solved = false;
18.81 + _col_names.push_back(std::string());
18.82
18.83 return soplex->nCols() - 1;
18.84 }
18.85 @@ -84,8 +83,7 @@
18.86 r.setRhs(soplex::infinity);
18.87 soplex->addRow(r);
18.88
18.89 - dual_value.push_back(0.0);
18.90 - solved = false;
18.91 + _row_names.push_back(std::string());
18.92
18.93 return soplex->nRows() - 1;
18.94 }
18.95 @@ -93,56 +91,84 @@
18.96
18.97 void LpSoplex::_eraseCol(int i) {
18.98 soplex->removeCol(i);
18.99 - invColNames.erase(colNames[i]);
18.100 - colNames[i] = colNames.back();
18.101 - invColNames[colNames.back()] = i;
18.102 - colNames.pop_back();
18.103 - primal_value[i] = primal_value.back();
18.104 - primal_value.pop_back();
18.105 - solved = false;
18.106 + _col_names_ref.erase(_col_names[i]);
18.107 + _col_names[i] = _col_names.back();
18.108 + _col_names_ref[_col_names.back()] = i;
18.109 + _col_names.pop_back();
18.110 }
18.111
18.112 void LpSoplex::_eraseRow(int i) {
18.113 soplex->removeRow(i);
18.114 - dual_value[i] = dual_value.back();
18.115 - dual_value.pop_back();
18.116 - solved = false;
18.117 + _row_names_ref.erase(_row_names[i]);
18.118 + _row_names[i] = _row_names.back();
18.119 + _row_names_ref[_row_names.back()] = i;
18.120 + _row_names.pop_back();
18.121 + }
18.122 +
18.123 + void LpSoplex::_eraseColId(int i) {
18.124 + cols.eraseIndex(i);
18.125 + cols.relocateIndex(i, cols.maxIndex());
18.126 + }
18.127 + void LpSoplex::_eraseRowId(int i) {
18.128 + rows.eraseIndex(i);
18.129 + rows.relocateIndex(i, rows.maxIndex());
18.130 }
18.131
18.132 void LpSoplex::_getColName(int c, std::string &name) const {
18.133 - name = colNames[c];
18.134 + name = _col_names[c];
18.135 }
18.136
18.137 void LpSoplex::_setColName(int c, const std::string &name) {
18.138 - invColNames.erase(colNames[c]);
18.139 - colNames[c] = name;
18.140 + _col_names_ref.erase(_col_names[c]);
18.141 + _col_names[c] = name;
18.142 if (!name.empty()) {
18.143 - invColNames.insert(std::make_pair(name, c));
18.144 + _col_names_ref.insert(std::make_pair(name, c));
18.145 }
18.146 }
18.147
18.148 int LpSoplex::_colByName(const std::string& name) const {
18.149 std::map<std::string, int>::const_iterator it =
18.150 - invColNames.find(name);
18.151 - if (it != invColNames.end()) {
18.152 + _col_names_ref.find(name);
18.153 + if (it != _col_names_ref.end()) {
18.154 return it->second;
18.155 } else {
18.156 return -1;
18.157 }
18.158 }
18.159
18.160 + void LpSoplex::_getRowName(int r, std::string &name) const {
18.161 + name = _row_names[r];
18.162 + }
18.163
18.164 - void LpSoplex::_setRowCoeffs(int i, ConstRowIterator b, ConstRowIterator e) {
18.165 + void LpSoplex::_setRowName(int r, const std::string &name) {
18.166 + _row_names_ref.erase(_row_names[r]);
18.167 + _row_names[r] = name;
18.168 + if (!name.empty()) {
18.169 + _row_names_ref.insert(std::make_pair(name, r));
18.170 + }
18.171 + }
18.172 +
18.173 + int LpSoplex::_rowByName(const std::string& name) const {
18.174 + std::map<std::string, int>::const_iterator it =
18.175 + _row_names_ref.find(name);
18.176 + if (it != _row_names_ref.end()) {
18.177 + return it->second;
18.178 + } else {
18.179 + return -1;
18.180 + }
18.181 + }
18.182 +
18.183 +
18.184 + void LpSoplex::_setRowCoeffs(int i, ExprIterator b, ExprIterator e) {
18.185 for (int j = 0; j < soplex->nCols(); ++j) {
18.186 soplex->changeElement(i, j, 0.0);
18.187 }
18.188 - for(ConstRowIterator it = b; it != e; ++it) {
18.189 + for(ExprIterator it = b; it != e; ++it) {
18.190 soplex->changeElement(i, it->first, it->second);
18.191 }
18.192 - solved = false;
18.193 }
18.194
18.195 - void LpSoplex::_getRowCoeffs(int i, RowIterator b) const {
18.196 + void LpSoplex::_getRowCoeffs(int i, InsertIterator b) const {
18.197 const soplex::SVector& vec = soplex->rowVector(i);
18.198 for (int k = 0; k < vec.size(); ++k) {
18.199 *b = std::make_pair(vec.index(k), vec.value(k));
18.200 @@ -150,17 +176,16 @@
18.201 }
18.202 }
18.203
18.204 - void LpSoplex::_setColCoeffs(int j, ConstColIterator b, ConstColIterator e) {
18.205 + void LpSoplex::_setColCoeffs(int j, ExprIterator b, ExprIterator e) {
18.206 for (int i = 0; i < soplex->nRows(); ++i) {
18.207 soplex->changeElement(i, j, 0.0);
18.208 }
18.209 - for(ConstColIterator it = b; it != e; ++it) {
18.210 + for(ExprIterator it = b; it != e; ++it) {
18.211 soplex->changeElement(it->first, j, it->second);
18.212 }
18.213 - solved = false;
18.214 }
18.215
18.216 - void LpSoplex::_getColCoeffs(int i, ColIterator b) const {
18.217 + void LpSoplex::_getColCoeffs(int i, InsertIterator b) const {
18.218 const soplex::SVector& vec = soplex->colVector(i);
18.219 for (int k = 0; k < vec.size(); ++k) {
18.220 *b = std::make_pair(vec.index(k), vec.value(k));
18.221 @@ -170,7 +195,6 @@
18.222
18.223 void LpSoplex::_setCoeff(int i, int j, Value value) {
18.224 soplex->changeElement(i, j, value);
18.225 - solved = false;
18.226 }
18.227
18.228 LpSoplex::Value LpSoplex::_getCoeff(int i, int j) const {
18.229 @@ -178,8 +202,8 @@
18.230 }
18.231
18.232 void LpSoplex::_setColLowerBound(int i, Value value) {
18.233 + LEMON_ASSERT(value != INF, "Invalid bound");
18.234 soplex->changeLower(i, value != -INF ? value : -soplex::infinity);
18.235 - solved = false;
18.236 }
18.237
18.238 LpSoplex::Value LpSoplex::_getColLowerBound(int i) const {
18.239 @@ -188,8 +212,8 @@
18.240 }
18.241
18.242 void LpSoplex::_setColUpperBound(int i, Value value) {
18.243 + LEMON_ASSERT(value != -INF, "Invalid bound");
18.244 soplex->changeUpper(i, value != INF ? value : soplex::infinity);
18.245 - solved = false;
18.246 }
18.247
18.248 LpSoplex::Value LpSoplex::_getColUpperBound(int i) const {
18.249 @@ -197,48 +221,63 @@
18.250 return value != soplex::infinity ? value : INF;
18.251 }
18.252
18.253 - void LpSoplex::_setRowBounds(int i, Value lb, Value ub) {
18.254 - soplex->changeRange(i, lb != -INF ? lb : -soplex::infinity,
18.255 - ub != INF ? ub : soplex::infinity);
18.256 - solved = false;
18.257 + void LpSoplex::_setRowLowerBound(int i, Value lb) {
18.258 + LEMON_ASSERT(lb != INF, "Invalid bound");
18.259 + soplex->changeRange(i, lb != -INF ? lb : -soplex::infinity, soplex->rhs(i));
18.260 }
18.261 - void LpSoplex::_getRowBounds(int i, Value &lower, Value &upper) const {
18.262 - lower = soplex->lhs(i);
18.263 - if (lower == -soplex::infinity) lower = -INF;
18.264 - upper = soplex->rhs(i);
18.265 - if (upper == -soplex::infinity) upper = INF;
18.266 +
18.267 + LpSoplex::Value LpSoplex::_getRowLowerBound(int i) const {
18.268 + double res = soplex->lhs(i);
18.269 + return res == -soplex::infinity ? -INF : res;
18.270 + }
18.271 +
18.272 + void LpSoplex::_setRowUpperBound(int i, Value ub) {
18.273 + LEMON_ASSERT(ub != -INF, "Invalid bound");
18.274 + soplex->changeRange(i, soplex->lhs(i), ub != INF ? ub : soplex::infinity);
18.275 + }
18.276 +
18.277 + LpSoplex::Value LpSoplex::_getRowUpperBound(int i) const {
18.278 + double res = soplex->rhs(i);
18.279 + return res == soplex::infinity ? INF : res;
18.280 + }
18.281 +
18.282 + void LpSoplex::_setObjCoeffs(ExprIterator b, ExprIterator e) {
18.283 + for (int j = 0; j < soplex->nCols(); ++j) {
18.284 + soplex->changeObj(j, 0.0);
18.285 + }
18.286 + for (ExprIterator it = b; it != e; ++it) {
18.287 + soplex->changeObj(it->first, it->second);
18.288 + }
18.289 + }
18.290 +
18.291 + void LpSoplex::_getObjCoeffs(InsertIterator b) const {
18.292 + for (int j = 0; j < soplex->nCols(); ++j) {
18.293 + Value coef = soplex->obj(j);
18.294 + if (coef != 0.0) {
18.295 + *b = std::make_pair(j, coef);
18.296 + ++b;
18.297 + }
18.298 + }
18.299 }
18.300
18.301 void LpSoplex::_setObjCoeff(int i, Value obj_coef) {
18.302 soplex->changeObj(i, obj_coef);
18.303 - solved = false;
18.304 }
18.305
18.306 LpSoplex::Value LpSoplex::_getObjCoeff(int i) const {
18.307 return soplex->obj(i);
18.308 }
18.309
18.310 - void LpSoplex::_clearObj() {
18.311 - for (int i = 0; i < soplex->nCols(); ++i) {
18.312 - soplex->changeObj(i, 0.0);
18.313 - }
18.314 - solved = false;
18.315 - }
18.316 + LpSoplex::SolveExitStatus LpSoplex::_solve() {
18.317
18.318 - LpSoplex::SolveExitStatus LpSoplex::_solve() {
18.319 + _clear_temporals();
18.320 +
18.321 soplex::SPxSolver::Status status = soplex->solve();
18.322
18.323 - soplex::Vector pv(primal_value.size(), &primal_value[0]);
18.324 - soplex->getPrimal(pv);
18.325 -
18.326 - soplex::Vector dv(dual_value.size(), &dual_value[0]);
18.327 - soplex->getDual(dv);
18.328 -
18.329 switch (status) {
18.330 case soplex::SPxSolver::OPTIMAL:
18.331 case soplex::SPxSolver::INFEASIBLE:
18.332 case soplex::SPxSolver::UNBOUNDED:
18.333 - solved = true;
18.334 return SOLVED;
18.335 default:
18.336 return UNSOLVED;
18.337 @@ -246,28 +285,87 @@
18.338 }
18.339
18.340 LpSoplex::Value LpSoplex::_getPrimal(int i) const {
18.341 - return primal_value[i];
18.342 + if (_primal_values.empty()) {
18.343 + _primal_values.resize(soplex->nCols());
18.344 + soplex::Vector pv(_primal_values.size(), &_primal_values.front());
18.345 + soplex->getPrimal(pv);
18.346 + }
18.347 + return _primal_values[i];
18.348 }
18.349
18.350 LpSoplex::Value LpSoplex::_getDual(int i) const {
18.351 - return dual_value[i];
18.352 + if (_dual_values.empty()) {
18.353 + _dual_values.resize(soplex->nRows());
18.354 + soplex::Vector dv(_dual_values.size(), &_dual_values.front());
18.355 + soplex->getDual(dv);
18.356 + }
18.357 + return _dual_values[i];
18.358 }
18.359
18.360 LpSoplex::Value LpSoplex::_getPrimalValue() const {
18.361 return soplex->objValue();
18.362 }
18.363
18.364 - bool LpSoplex::_isBasicCol(int i) const {
18.365 - return soplex->getBasisColStatus(i) == soplex::SPxSolver::BASIC;
18.366 + LpSoplex::VarStatus LpSoplex::_getColStatus(int i) const {
18.367 + switch (soplex->getBasisColStatus(i)) {
18.368 + case soplex::SPxSolver::BASIC:
18.369 + return BASIC;
18.370 + case soplex::SPxSolver::ON_UPPER:
18.371 + return UPPER;
18.372 + case soplex::SPxSolver::ON_LOWER:
18.373 + return LOWER;
18.374 + case soplex::SPxSolver::FIXED:
18.375 + return FIXED;
18.376 + case soplex::SPxSolver::ZERO:
18.377 + return FREE;
18.378 + default:
18.379 + LEMON_ASSERT(false, "Wrong column status");
18.380 + return VarStatus();
18.381 + }
18.382 }
18.383
18.384 - LpSoplex::SolutionStatus LpSoplex::_getPrimalStatus() const {
18.385 - if (!solved) return UNDEFINED;
18.386 + LpSoplex::VarStatus LpSoplex::_getRowStatus(int i) const {
18.387 + switch (soplex->getBasisRowStatus(i)) {
18.388 + case soplex::SPxSolver::BASIC:
18.389 + return BASIC;
18.390 + case soplex::SPxSolver::ON_UPPER:
18.391 + return UPPER;
18.392 + case soplex::SPxSolver::ON_LOWER:
18.393 + return LOWER;
18.394 + case soplex::SPxSolver::FIXED:
18.395 + return FIXED;
18.396 + case soplex::SPxSolver::ZERO:
18.397 + return FREE;
18.398 + default:
18.399 + LEMON_ASSERT(false, "Wrong row status");
18.400 + return VarStatus();
18.401 + }
18.402 + }
18.403 +
18.404 + LpSoplex::Value LpSoplex::_getPrimalRay(int i) const {
18.405 + if (_primal_ray.empty()) {
18.406 + _primal_ray.resize(soplex->nCols());
18.407 + soplex::Vector pv(_primal_ray.size(), &_primal_ray.front());
18.408 + soplex->getDualfarkas(pv);
18.409 + }
18.410 + return _primal_ray[i];
18.411 + }
18.412 +
18.413 + LpSoplex::Value LpSoplex::_getDualRay(int i) const {
18.414 + if (_dual_ray.empty()) {
18.415 + _dual_ray.resize(soplex->nRows());
18.416 + soplex::Vector dv(_dual_ray.size(), &_dual_ray.front());
18.417 + soplex->getDualfarkas(dv);
18.418 + }
18.419 + return _dual_ray[i];
18.420 + }
18.421 +
18.422 + LpSoplex::ProblemType LpSoplex::_getPrimalType() const {
18.423 switch (soplex->status()) {
18.424 case soplex::SPxSolver::OPTIMAL:
18.425 return OPTIMAL;
18.426 case soplex::SPxSolver::UNBOUNDED:
18.427 - return INFINITE;
18.428 + return UNBOUNDED;
18.429 case soplex::SPxSolver::INFEASIBLE:
18.430 return INFEASIBLE;
18.431 default:
18.432 @@ -275,42 +373,51 @@
18.433 }
18.434 }
18.435
18.436 - LpSoplex::SolutionStatus LpSoplex::_getDualStatus() const {
18.437 - if (!solved) return UNDEFINED;
18.438 + LpSoplex::ProblemType LpSoplex::_getDualType() const {
18.439 switch (soplex->status()) {
18.440 case soplex::SPxSolver::OPTIMAL:
18.441 return OPTIMAL;
18.442 case soplex::SPxSolver::UNBOUNDED:
18.443 + return UNBOUNDED;
18.444 + case soplex::SPxSolver::INFEASIBLE:
18.445 return INFEASIBLE;
18.446 default:
18.447 return UNDEFINED;
18.448 }
18.449 }
18.450
18.451 - LpSoplex::ProblemTypes LpSoplex::_getProblemType() const {
18.452 - if (!solved) return UNKNOWN;
18.453 - switch (soplex->status()) {
18.454 - case soplex::SPxSolver::OPTIMAL:
18.455 - return PRIMAL_DUAL_FEASIBLE;
18.456 - case soplex::SPxSolver::UNBOUNDED:
18.457 - return PRIMAL_FEASIBLE_DUAL_INFEASIBLE;
18.458 - default:
18.459 - return UNKNOWN;
18.460 + void LpSoplex::_setSense(Sense sense) {
18.461 + switch (sense) {
18.462 + case MIN:
18.463 + soplex->changeSense(soplex::SPxSolver::MINIMIZE);
18.464 + break;
18.465 + case MAX:
18.466 + soplex->changeSense(soplex::SPxSolver::MAXIMIZE);
18.467 }
18.468 }
18.469
18.470 - void LpSoplex::_setMax() {
18.471 - soplex->changeSense(soplex::SPxSolver::MAXIMIZE);
18.472 - solved = false;
18.473 - }
18.474 - void LpSoplex::_setMin() {
18.475 - soplex->changeSense(soplex::SPxSolver::MINIMIZE);
18.476 - solved = false;
18.477 - }
18.478 - bool LpSoplex::_isMax() const {
18.479 - return soplex->spxSense() == soplex::SPxSolver::MAXIMIZE;
18.480 + LpSoplex::Sense LpSoplex::_getSense() const {
18.481 + switch (soplex->spxSense()) {
18.482 + case soplex::SPxSolver::MAXIMIZE:
18.483 + return MAX;
18.484 + case soplex::SPxSolver::MINIMIZE:
18.485 + return MIN;
18.486 + default:
18.487 + LEMON_ASSERT(false, "Wrong sense.");
18.488 + return LpSoplex::Sense();
18.489 + }
18.490 }
18.491
18.492 + void LpSoplex::_clear() {
18.493 + soplex->clear();
18.494 + _col_names.clear();
18.495 + _col_names_ref.clear();
18.496 + _row_names.clear();
18.497 + _row_names_ref.clear();
18.498 + cols.clear();
18.499 + rows.clear();
18.500 + _clear_temporals();
18.501 + }
18.502
18.503 } //namespace lemon
18.504
19.1 --- a/lemon/lp_soplex.h Tue Dec 02 21:40:33 2008 +0100
19.2 +++ b/lemon/lp_soplex.h Tue Dec 02 22:48:28 2008 +0100
19.3 @@ -43,26 +43,30 @@
19.4 /// developed at the Konrad-Zuse-Zentrum für Informationstechnik
19.5 /// Berlin (ZIB). You can find detailed information about it at the
19.6 /// <tt>http://soplex.zib.de</tt> address.
19.7 - class LpSoplex :virtual public LpSolverBase {
19.8 - protected:
19.9 -
19.10 - _lp_bits::RelocateIdHandler relocateIdHandler;
19.11 + class LpSoplex : public LpSolver {
19.12 + private:
19.13
19.14 soplex::SoPlex* soplex;
19.15 - bool solved;
19.16
19.17 - std::vector<std::string> colNames;
19.18 - std::map<std::string, int> invColNames;
19.19 + std::vector<std::string> _col_names;
19.20 + std::map<std::string, int> _col_names_ref;
19.21
19.22 - std::vector<Value> primal_value;
19.23 - std::vector<Value> dual_value;
19.24 + std::vector<std::string> _row_names;
19.25 + std::map<std::string, int> _row_names_ref;
19.26
19.27 + private:
19.28 +
19.29 + // these values cannot be retrieved element by element
19.30 + mutable std::vector<Value> _primal_values;
19.31 + mutable std::vector<Value> _dual_values;
19.32 +
19.33 + mutable std::vector<Value> _primal_ray;
19.34 + mutable std::vector<Value> _dual_ray;
19.35 +
19.36 + void _clear_temporals();
19.37
19.38 public:
19.39
19.40 - typedef LpSolverBase Parent;
19.41 -
19.42 -
19.43 /// \e
19.44 LpSoplex();
19.45 /// \e
19.46 @@ -72,48 +76,75 @@
19.47
19.48 protected:
19.49
19.50 - virtual LpSolverBase* _newLp();
19.51 - virtual LpSolverBase* _copyLp();
19.52 + virtual LpSoplex* _newSolver() const;
19.53 + virtual LpSoplex* _cloneSolver() const;
19.54 +
19.55 + virtual const char* _solverName() const;
19.56
19.57 virtual int _addCol();
19.58 virtual int _addRow();
19.59 +
19.60 virtual void _eraseCol(int i);
19.61 virtual void _eraseRow(int i);
19.62 - virtual void _getColName(int col, std::string & name) const;
19.63 - virtual void _setColName(int col, const std::string & name);
19.64 +
19.65 + virtual void _eraseColId(int i);
19.66 + virtual void _eraseRowId(int i);
19.67 +
19.68 + virtual void _getColName(int col, std::string& name) const;
19.69 + virtual void _setColName(int col, const std::string& name);
19.70 virtual int _colByName(const std::string& name) const;
19.71 - virtual void _setRowCoeffs(int i, ConstRowIterator b, ConstRowIterator e);
19.72 - virtual void _getRowCoeffs(int i, RowIterator b) const;
19.73 - virtual void _setColCoeffs(int i, ConstColIterator b, ConstColIterator e);
19.74 - virtual void _getColCoeffs(int i, ColIterator b) const;
19.75 +
19.76 + virtual void _getRowName(int row, std::string& name) const;
19.77 + virtual void _setRowName(int row, const std::string& name);
19.78 + virtual int _rowByName(const std::string& name) const;
19.79 +
19.80 + virtual void _setRowCoeffs(int i, ExprIterator b, ExprIterator e);
19.81 + virtual void _getRowCoeffs(int i, InsertIterator b) const;
19.82 +
19.83 + virtual void _setColCoeffs(int i, ExprIterator b, ExprIterator e);
19.84 + virtual void _getColCoeffs(int i, InsertIterator b) const;
19.85 +
19.86 virtual void _setCoeff(int row, int col, Value value);
19.87 virtual Value _getCoeff(int row, int col) const;
19.88 +
19.89 virtual void _setColLowerBound(int i, Value value);
19.90 virtual Value _getColLowerBound(int i) const;
19.91 virtual void _setColUpperBound(int i, Value value);
19.92 virtual Value _getColUpperBound(int i) const;
19.93 - virtual void _setRowBounds(int i, Value lower, Value upper);
19.94 - virtual void _getRowBounds(int i, Value &lower, Value &upper) const;
19.95 +
19.96 + virtual void _setRowLowerBound(int i, Value value);
19.97 + virtual Value _getRowLowerBound(int i) const;
19.98 + virtual void _setRowUpperBound(int i, Value value);
19.99 + virtual Value _getRowUpperBound(int i) const;
19.100 +
19.101 + virtual void _setObjCoeffs(ExprIterator b, ExprIterator e);
19.102 + virtual void _getObjCoeffs(InsertIterator b) const;
19.103 +
19.104 virtual void _setObjCoeff(int i, Value obj_coef);
19.105 virtual Value _getObjCoeff(int i) const;
19.106 - virtual void _clearObj();
19.107 +
19.108 + virtual void _setSense(Sense sense);
19.109 + virtual Sense _getSense() const;
19.110
19.111 virtual SolveExitStatus _solve();
19.112 virtual Value _getPrimal(int i) const;
19.113 virtual Value _getDual(int i) const;
19.114 +
19.115 virtual Value _getPrimalValue() const;
19.116 - virtual bool _isBasicCol(int i) const;
19.117
19.118 - virtual SolutionStatus _getPrimalStatus() const;
19.119 - virtual SolutionStatus _getDualStatus() const;
19.120 - virtual ProblemTypes _getProblemType() const;
19.121 + virtual Value _getPrimalRay(int i) const;
19.122 + virtual Value _getDualRay(int i) const;
19.123
19.124 + virtual VarStatus _getColStatus(int i) const;
19.125 + virtual VarStatus _getRowStatus(int i) const;
19.126
19.127 - virtual void _setMax();
19.128 - virtual void _setMin();
19.129 - virtual bool _isMax() const;
19.130 + virtual ProblemType _getPrimalType() const;
19.131 + virtual ProblemType _getDualType() const;
19.132 +
19.133 + virtual void _clear();
19.134
19.135 };
19.136 +
19.137 } //END OF NAMESPACE LEMON
19.138
19.139 #endif //LEMON_LP_SOPLEX_H
20.1 --- a/lemon/mip_cplex.cc Tue Dec 02 21:40:33 2008 +0100
20.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
20.3 @@ -1,141 +0,0 @@
20.4 -/* -*- mode: C++; indent-tabs-mode: nil; -*-
20.5 - *
20.6 - * This file is a part of LEMON, a generic C++ optimization library.
20.7 - *
20.8 - * Copyright (C) 2003-2008
20.9 - * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
20.10 - * (Egervary Research Group on Combinatorial Optimization, EGRES).
20.11 - *
20.12 - * Permission to use, modify and distribute this software is granted
20.13 - * provided that this copyright notice appears in all copies. For
20.14 - * precise terms see the accompanying LICENSE file.
20.15 - *
20.16 - * This software is provided "AS IS" with no warranty of any kind,
20.17 - * express or implied, and with no claim as to its suitability for any
20.18 - * purpose.
20.19 - *
20.20 - */
20.21 -
20.22 -///\file
20.23 -///\brief Implementation of the LEMON-CPLEX mip solver interface.
20.24 -
20.25 -#include <lemon/mip_cplex.h>
20.26 -
20.27 -extern "C" {
20.28 -#include <ilcplex/cplex.h>
20.29 -}
20.30 -
20.31 -namespace lemon {
20.32 -
20.33 - MipCplex::MipCplex() {
20.34 - //This is unnecessary: setting integrality constraints on
20.35 - //variables will set this, too
20.36 -
20.37 - ///\todo The constant CPXPROB_MIP is
20.38 - ///called CPXPROB_MILP in later versions
20.39 -#if CPX_VERSION < 800
20.40 - CPXchgprobtype( env, lp, CPXPROB_MIP);
20.41 -#else
20.42 - CPXchgprobtype( env, lp, CPXPROB_MILP);
20.43 -#endif
20.44 -
20.45 - }
20.46 -
20.47 - void MipCplex::_colType(int i, MipCplex::ColTypes col_type){
20.48 -
20.49 - // Note If a variable is to be changed to binary, a call to CPXchgbds
20.50 - // should also be made to change the bounds to 0 and 1.
20.51 -
20.52 - int indices[1];
20.53 - indices[0]=i;
20.54 - char ctype[1];
20.55 - switch (col_type){
20.56 - case INT:
20.57 - ctype[0]=CPX_INTEGER;//'I'
20.58 - break;
20.59 - case REAL:
20.60 - ctype[0]=CPX_CONTINUOUS ;//'C'
20.61 - break;
20.62 - default:;
20.63 - //FIXME problem
20.64 - }
20.65 - CPXchgctype (env, lp, 1, indices, ctype);
20.66 - }
20.67 -
20.68 - MipCplex::ColTypes MipCplex::_colType(int i) const {
20.69 -
20.70 - char ctype[1];
20.71 - CPXgetctype (env, lp, ctype, i, i);
20.72 - switch (ctype[0]){
20.73 -
20.74 - case CPX_INTEGER:
20.75 - return INT;
20.76 - case CPX_CONTINUOUS:
20.77 - return REAL;
20.78 - default:
20.79 - return REAL;//Error!
20.80 - }
20.81 -
20.82 - }
20.83 -
20.84 - LpCplex::SolveExitStatus MipCplex::_solve(){
20.85 -
20.86 - status = CPXmipopt (env, lp);
20.87 - if (status==0)
20.88 - return SOLVED;
20.89 - else
20.90 - return UNSOLVED;
20.91 -
20.92 - }
20.93 -
20.94 -
20.95 - LpCplex::SolutionStatus MipCplex::_getMipStatus() const {
20.96 -
20.97 - int stat = CPXgetstat(env, lp);
20.98 -
20.99 - //Fortunately, MIP statuses did not change for cplex 8.0
20.100 - switch (stat)
20.101 - {
20.102 - case CPXMIP_OPTIMAL:
20.103 - // Optimal integer solution has been found.
20.104 - case CPXMIP_OPTIMAL_TOL:
20.105 - // Optimal soluton with the tolerance defined by epgap or epagap has
20.106 - // been found.
20.107 - return OPTIMAL;
20.108 - //This also exists in later issues
20.109 - // case CPXMIP_UNBOUNDED:
20.110 - //return INFINITE;
20.111 - case CPXMIP_INFEASIBLE:
20.112 - return INFEASIBLE;
20.113 - default:
20.114 - return UNDEFINED;
20.115 - }
20.116 - //Unboundedness not treated well: the following is from cplex 9.0 doc
20.117 - // About Unboundedness
20.118 -
20.119 - // The treatment of models that are unbounded involves a few
20.120 - // subtleties. Specifically, a declaration of unboundedness means that
20.121 - // ILOG CPLEX has determined that the model has an unbounded
20.122 - // ray. Given any feasible solution x with objective z, a multiple of
20.123 - // the unbounded ray can be added to x to give a feasible solution
20.124 - // with objective z-1 (or z+1 for maximization models). Thus, if a
20.125 - // feasible solution exists, then the optimal objective is
20.126 - // unbounded. Note that ILOG CPLEX has not necessarily concluded that
20.127 - // a feasible solution exists. Users can call the routine CPXsolninfo
20.128 - // to determine whether ILOG CPLEX has also concluded that the model
20.129 - // has a feasible solution.
20.130 -
20.131 - }
20.132 -
20.133 - MipCplex::Value MipCplex::_getPrimal(int i) const {
20.134 - Value x;
20.135 - CPXgetmipx(env, lp, &x, i, i);
20.136 - return x;
20.137 - }
20.138 -
20.139 - MipCplex::Value MipCplex::_getPrimalValue() const {
20.140 - Value objval;
20.141 - CPXgetmipobjval(env, lp, &objval);
20.142 - return objval;
20.143 - }
20.144 -} //END OF NAMESPACE LEMON
21.1 --- a/lemon/mip_cplex.h Tue Dec 02 21:40:33 2008 +0100
21.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
21.3 @@ -1,61 +0,0 @@
21.4 -/* -*- mode: C++; indent-tabs-mode: nil; -*-
21.5 - *
21.6 - * This file is a part of LEMON, a generic C++ optimization library.
21.7 - *
21.8 - * Copyright (C) 2003-2008
21.9 - * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
21.10 - * (Egervary Research Group on Combinatorial Optimization, EGRES).
21.11 - *
21.12 - * Permission to use, modify and distribute this software is granted
21.13 - * provided that this copyright notice appears in all copies. For
21.14 - * precise terms see the accompanying LICENSE file.
21.15 - *
21.16 - * This software is provided "AS IS" with no warranty of any kind,
21.17 - * express or implied, and with no claim as to its suitability for any
21.18 - * purpose.
21.19 - *
21.20 - */
21.21 -
21.22 -#ifndef LEMON_MIP_CPLEX_H
21.23 -#define LEMON_MIP_CPLEX_H
21.24 -
21.25 -///\file
21.26 -///\brief Header of the LEMON-CPLEX mip solver interface.
21.27 -///\ingroup lp_group
21.28 -
21.29 -
21.30 -#include <lemon/lp_cplex.h>
21.31 -
21.32 -namespace lemon {
21.33 -
21.34 - /// \brief Interface for the CPLEX MIP solver
21.35 - ///
21.36 - /// This class implements an interface for the CPLEX MIP solver.
21.37 - ///\ingroup lp_group
21.38 - class MipCplex : public MipSolverBase, public LpCplex{
21.39 -
21.40 - public:
21.41 -
21.42 - typedef MipSolverBase ParentMip;
21.43 - typedef LpCplex ParentLp;
21.44 -
21.45 - MipCplex();
21.46 - //~MipCplex();
21.47 -
21.48 -
21.49 -
21.50 -
21.51 - protected:
21.52 -
21.53 - virtual ColTypes _colType(int col) const;
21.54 - virtual void _colType(int col, ColTypes col_type);
21.55 -
21.56 - virtual LpCplex::SolveExitStatus _solve();
21.57 - virtual LpCplex::SolutionStatus _getMipStatus() const;
21.58 - virtual ParentLp::Value _getPrimal(int i) const;
21.59 - virtual ParentLp::Value _getPrimalValue() const;
21.60 - };
21.61 -
21.62 -} //END OF NAMESPACE LEMON
21.63 -
21.64 -#endif // END OF LEMON_MIP_CPLEX_H
22.1 --- a/lemon/mip_glpk.cc Tue Dec 02 21:40:33 2008 +0100
22.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
22.3 @@ -1,154 +0,0 @@
22.4 -/* -*- mode: C++; indent-tabs-mode: nil; -*-
22.5 - *
22.6 - * This file is a part of LEMON, a generic C++ optimization library.
22.7 - *
22.8 - * Copyright (C) 2003-2008
22.9 - * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
22.10 - * (Egervary Research Group on Combinatorial Optimization, EGRES).
22.11 - *
22.12 - * Permission to use, modify and distribute this software is granted
22.13 - * provided that this copyright notice appears in all copies. For
22.14 - * precise terms see the accompanying LICENSE file.
22.15 - *
22.16 - * This software is provided "AS IS" with no warranty of any kind,
22.17 - * express or implied, and with no claim as to its suitability for any
22.18 - * purpose.
22.19 - *
22.20 - */
22.21 -
22.22 -///\file
22.23 -///\brief Implementation of the LEMON-GLPK mip solver interface.
22.24 -
22.25 -#include <lemon/mip_glpk.h>
22.26 -
22.27 -extern "C" {
22.28 -#include <glpk.h>
22.29 -}
22.30 -
22.31 -#if GLP_MAJOR_VERSION > 4 || (GLP_MAJOR_VERSION == 4 && GLP_MINOR_VERSION > 15)
22.32 -#define LEMON_glp(func) (glp_##func)
22.33 -#define LEMON_lpx(func) (lpx_##func)
22.34 -
22.35 -#define LEMON_GLP(def) (GLP_##def)
22.36 -#define LEMON_LPX(def) (LPX_##def)
22.37 -
22.38 -#else
22.39 -
22.40 -#define LEMON_glp(func) (lpx_##func)
22.41 -#define LEMON_lpx(func) (lpx_##func)
22.42 -
22.43 -#define LEMON_GLP(def) (LPX_##def)
22.44 -#define LEMON_LPX(def) (LPX_##def)
22.45 -
22.46 -#endif
22.47 -
22.48 -namespace lemon {
22.49 -
22.50 - MipGlpk::MipGlpk() {
22.51 -#if !(GLP_MAJOR_VERSION > 4 || \
22.52 - (GLP_MAJOR_VERSION == 4 && GLP_MINOR_VERSION > 15))
22.53 - LEMON_lpx(set_class)(lp,LEMON_GLP(MIP));
22.54 -#endif
22.55 - }
22.56 -
22.57 - void MipGlpk::_colType(int i, MipGlpk::ColTypes col_type){
22.58 - switch (col_type){
22.59 - case INT:
22.60 - LEMON_glp(set_col_kind)(lp,i,LEMON_GLP(IV));
22.61 - break;
22.62 - case REAL:
22.63 - LEMON_glp(set_col_kind)(lp,i,LEMON_GLP(CV));
22.64 - break;
22.65 - default:;
22.66 - //FIXME problem
22.67 - }
22.68 - }
22.69 -
22.70 - MipGlpk::ColTypes MipGlpk::_colType(int i) const {
22.71 - switch (LEMON_glp(get_col_kind)(lp,i)){
22.72 - case LEMON_GLP(IV):
22.73 - return INT;//Or binary
22.74 - case LEMON_GLP(CV):
22.75 - return REAL;
22.76 - default:
22.77 - return REAL;//Error!
22.78 - }
22.79 -
22.80 - }
22.81 -
22.82 - LpGlpk::SolveExitStatus MipGlpk::_solve() {
22.83 - int result = LEMON_lpx(simplex)(lp);
22.84 -
22.85 - // hack: mip does not contain integer variable
22.86 -#if GLP_MAJOR_VERSION == 4 && GLP_MINOR_VERSION == 16
22.87 - int tmp = -1;
22.88 - if (LEMON_glp(get_num_int(lp)) == 0) {
22.89 - tmp = LEMON_lpx(add_cols)(lp, 1);
22.90 - LEMON_glp(set_col_bnds)(lp, tmp, LEMON_GLP(FX), 0.0, 0.0);
22.91 - LEMON_glp(set_col_kind)(lp, tmp, LEMON_GLP(IV));
22.92 - }
22.93 -#endif
22.94 -
22.95 - if (LEMON_lpx(get_status)(lp)==LEMON_LPX(OPT)) {
22.96 - //Maybe we could try the routine lpx_intopt(lp), a revised
22.97 - //version of lpx_integer
22.98 -
22.99 - result = LEMON_lpx(integer)(lp);
22.100 - switch (result){
22.101 - case LEMON_LPX(E_OK):
22.102 - solved = true;
22.103 - break;
22.104 - default:
22.105 - solved = false;
22.106 - }
22.107 - } else {
22.108 - solved = false;
22.109 - }
22.110 -#if GLP_MAJOR_VERSION == 4 && GLP_MINOR_VERSION == 16
22.111 - if (tmp != -1) {
22.112 - int tmpa[2];
22.113 - tmpa[1] = tmp;
22.114 - LEMON_lpx(del_cols)(lp, 1, tmpa);
22.115 - }
22.116 -#endif
22.117 - return solved ? SOLVED : UNSOLVED;
22.118 - }
22.119 -
22.120 -
22.121 - LpGlpk::SolutionStatus MipGlpk::_getMipStatus() const {
22.122 -
22.123 - if (LEMON_lpx(get_status)(lp)==LEMON_LPX(OPT)){
22.124 - //Meg kell nezni: ha az LP is infinite, akkor ez is, ha az is
22.125 - //infeasible, akkor ez is, de ez lehet maskepp is infeasible.
22.126 - int stat= LEMON_lpx(mip_status)(lp);
22.127 -
22.128 - switch (stat) {
22.129 - case LEMON_LPX(I_UNDEF)://Undefined (no solve has been run yet)
22.130 - return UNDEFINED;
22.131 - case LEMON_LPX(I_NOFEAS)://There is no feasible integral solution
22.132 - return INFEASIBLE;
22.133 - // case LEMON_LPX(UNBND)://Unbounded
22.134 - // return INFINITE;
22.135 - case LEMON_LPX(I_FEAS)://Feasible
22.136 - return FEASIBLE;
22.137 - case LEMON_LPX(I_OPT)://Feasible
22.138 - return OPTIMAL;
22.139 - default:
22.140 - return UNDEFINED; //to avoid gcc warning
22.141 - //FIXME error
22.142 - }
22.143 - }
22.144 - else
22.145 - return UNDEFINED; //Maybe we could refine this: what does the LP
22.146 - //relaxation look like
22.147 -
22.148 - }
22.149 -
22.150 - MipGlpk::Value MipGlpk::_getPrimal(int i) const {
22.151 - return LEMON_glp(mip_col_val)(lp,i);
22.152 - }
22.153 -
22.154 - MipGlpk::Value MipGlpk::_getPrimalValue() const {
22.155 - return LEMON_glp(mip_obj_val)(lp);
22.156 - }
22.157 -} //END OF NAMESPACE LEMON
23.1 --- a/lemon/mip_glpk.h Tue Dec 02 21:40:33 2008 +0100
23.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
23.3 @@ -1,59 +0,0 @@
23.4 -/* -*- mode: C++; indent-tabs-mode: nil; -*-
23.5 - *
23.6 - * This file is a part of LEMON, a generic C++ optimization library.
23.7 - *
23.8 - * Copyright (C) 2003-2008
23.9 - * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
23.10 - * (Egervary Research Group on Combinatorial Optimization, EGRES).
23.11 - *
23.12 - * Permission to use, modify and distribute this software is granted
23.13 - * provided that this copyright notice appears in all copies. For
23.14 - * precise terms see the accompanying LICENSE file.
23.15 - *
23.16 - * This software is provided "AS IS" with no warranty of any kind,
23.17 - * express or implied, and with no claim as to its suitability for any
23.18 - * purpose.
23.19 - *
23.20 - */
23.21 -
23.22 -#ifndef LEMON_MIP_GLPK_H
23.23 -#define LEMON_MIP_GLPK_H
23.24 -
23.25 -///\file
23.26 -///\brief Header of the LEMON-GLPK mip solver interface.
23.27 -///\ingroup lp_group
23.28 -
23.29 -
23.30 -#include <lemon/lp_glpk.h>
23.31 -
23.32 -namespace lemon {
23.33 - /// \brief Interface for the GLPK MIP solver
23.34 - ///
23.35 - /// This class implements an interface for the GLPK MIP solver.
23.36 - ///\ingroup lp_group
23.37 - class MipGlpk : public MipSolverBase, public LpGlpk{
23.38 -
23.39 - public:
23.40 -
23.41 - typedef MipSolverBase ParentMip;
23.42 - typedef LpGlpk ParentLp;
23.43 -
23.44 - MipGlpk();
23.45 - //~MipGlpk();
23.46 -
23.47 -
23.48 -
23.49 - protected:
23.50 -
23.51 - virtual ColTypes _colType(int col) const;
23.52 - virtual void _colType(int col, ColTypes col_type);
23.53 -
23.54 - virtual LpGlpk::SolveExitStatus _solve();
23.55 - virtual LpGlpk::SolutionStatus _getMipStatus() const;
23.56 - virtual ParentLp::Value _getPrimal(int i) const;
23.57 - virtual ParentLp::Value _getPrimalValue() const;
23.58 - };
23.59 -
23.60 -} //END OF NAMESPACE LEMON
23.61 -
23.62 -#endif // END OF LEMON_MIP_GLPK_H
24.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
24.2 +++ b/m4/lx_check_clp.m4 Tue Dec 02 22:48:28 2008 +0100
24.3 @@ -0,0 +1,73 @@
24.4 +AC_DEFUN([LX_CHECK_CLP],
24.5 +[
24.6 + AC_ARG_WITH([clp],
24.7 +AS_HELP_STRING([--with-clp@<:@=PREFIX@:>@], [search for CLP under PREFIX or under the default search paths if PREFIX is not given @<:@default@:>@])
24.8 +AS_HELP_STRING([--without-clp], [disable checking for CLP]),
24.9 + [], [with_clp=yes])
24.10 +
24.11 + AC_ARG_WITH([clp-includedir],
24.12 +AS_HELP_STRING([--with-clp-includedir=DIR], [search for CLP headers in DIR]),
24.13 + [], [with_clp_includedir=no])
24.14 +
24.15 + AC_ARG_WITH([clp-libdir],
24.16 +AS_HELP_STRING([--with-clp-libdir=DIR], [search for CLP libraries in DIR]),
24.17 + [], [with_clp_libdir=no])
24.18 +
24.19 + lx_clp_found=no
24.20 + if test x"$with_clp" != x"no"; then
24.21 + AC_MSG_CHECKING([for CLP])
24.22 +
24.23 + if test x"$with_clp_includedir" != x"no"; then
24.24 + CLP_CXXFLAGS="-I$with_clp_includedir"
24.25 + elif test x"$with_clp" != x"yes"; then
24.26 + CLP_CXXFLAGS="-I$with_clp/include"
24.27 + fi
24.28 +
24.29 + if test x"$with_clp_libdir" != x"no"; then
24.30 + CLP_LDFLAGS="-L$with_clp_libdir"
24.31 + elif test x"$with_clp" != x"yes"; then
24.32 + CLP_LDFLAGS="-L$with_clp/lib"
24.33 + fi
24.34 + CLP_LIBS="-lClp -lCoinUtils -lm"
24.35 +
24.36 + lx_save_cxxflags="$CXXFLAGS"
24.37 + lx_save_ldflags="$LDFLAGS"
24.38 + lx_save_libs="$LIBS"
24.39 + CXXFLAGS="$CLP_CXXFLAGS"
24.40 + LDFLAGS="$CLP_LDFLAGS"
24.41 + LIBS="$CLP_LIBS"
24.42 +
24.43 + lx_clp_test_prog='
24.44 + #include <coin/ClpModel.hpp>
24.45 +
24.46 + int main(int argc, char** argv)
24.47 + {
24.48 + ClpModel clp;
24.49 + return 0;
24.50 + }'
24.51 +
24.52 + AC_LANG_PUSH(C++)
24.53 + AC_LINK_IFELSE([$lx_clp_test_prog], [lx_clp_found=yes], [lx_clp_found=no])
24.54 + AC_LANG_POP(C++)
24.55 +
24.56 + CXXFLAGS="$lx_save_cxxflags"
24.57 + LDFLAGS="$lx_save_ldflags"
24.58 + LIBS="$lx_save_libs"
24.59 +
24.60 + if test x"$lx_clp_found" = x"yes"; then
24.61 + AC_DEFINE([HAVE_CLP], [1], [Define to 1 if you have CLP.])
24.62 + lx_lp_found=yes
24.63 + AC_DEFINE([HAVE_LP], [1], [Define to 1 if you have any LP solver.])
24.64 + AC_MSG_RESULT([yes])
24.65 + else
24.66 + CLP_CXXFLAGS=""
24.67 + CLP_LDFLAGS=""
24.68 + CLP_LIBS=""
24.69 + AC_MSG_RESULT([no])
24.70 + fi
24.71 + fi
24.72 + CLP_LIBS="$CLP_LDFLAGS $CLP_LIBS"
24.73 + AC_SUBST(CLP_CXXFLAGS)
24.74 + AC_SUBST(CLP_LIBS)
24.75 + AM_CONDITIONAL([HAVE_CLP], [test x"$lx_clp_found" = x"yes"])
24.76 +])
25.1 --- a/m4/lx_check_glpk.m4 Tue Dec 02 21:40:33 2008 +0100
25.2 +++ b/m4/lx_check_glpk.m4 Tue Dec 02 22:48:28 2008 +0100
25.3 @@ -42,6 +42,11 @@
25.4 #include <glpk.h>
25.5 }
25.6
25.7 + #if (GLP_MAJOR_VERSION < 4) \
25.8 + || (GLP_MAJOR_VERSION == 4 && GLP_MINOR_VERSION < 33)
25.9 + #error Supported GLPK versions: 4.33 or above
25.10 + #endif
25.11 +
25.12 int main(int argc, char** argv)
25.13 {
25.14 LPX *lp;
26.1 --- a/test/lp_test.cc Tue Dec 02 21:40:33 2008 +0100
26.2 +++ b/test/lp_test.cc Tue Dec 02 22:48:28 2008 +0100
26.3 @@ -37,14 +37,16 @@
26.4 #include <lemon/lp_soplex.h>
26.5 #endif
26.6
26.7 +#ifdef HAVE_CLP
26.8 +#include <lemon/lp_clp.h>
26.9 +#endif
26.10 +
26.11 using namespace lemon;
26.12
26.13 -void lpTest(LpSolverBase & lp)
26.14 +void lpTest(LpSolver& lp)
26.15 {
26.16
26.17 -
26.18 -
26.19 - typedef LpSolverBase LP;
26.20 + typedef LpSolver LP;
26.21
26.22 std::vector<LP::Col> x(10);
26.23 // for(int i=0;i<10;i++) x.push_back(lp.addCol());
26.24 @@ -52,7 +54,6 @@
26.25 lp.colLowerBound(x,1);
26.26 lp.colUpperBound(x,1);
26.27 lp.colBounds(x,1,2);
26.28 -#ifndef GYORSITAS
26.29
26.30 std::vector<LP::Col> y(10);
26.31 lp.addColSet(y);
26.32 @@ -86,11 +87,11 @@
26.33 p5=lp.addCol();
26.34
26.35 e[p1]=2;
26.36 - e.constComp()=12;
26.37 + *e=12;
26.38 e[p1]+=2;
26.39 - e.constComp()+=12;
26.40 + *e+=12;
26.41 e[p1]-=2;
26.42 - e.constComp()-=12;
26.43 + *e-=12;
26.44
26.45 e=2;
26.46 e=2.2;
26.47 @@ -170,11 +171,11 @@
26.48 e[x[3]]=2;
26.49 e[x[3]]=4;
26.50 e[x[3]]=1;
26.51 - e.constComp()=12;
26.52 + *e=12;
26.53
26.54 - lp.addRow(LP::INF,e,23);
26.55 - lp.addRow(LP::INF,3.0*(x[1]+x[2]/2)-x[3],23);
26.56 - lp.addRow(LP::INF,3.0*(x[1]+x[2]*2-5*x[3]+12-x[4]/3)+2*x[4]-4,23);
26.57 + lp.addRow(-LP::INF,e,23);
26.58 + lp.addRow(-LP::INF,3.0*(x[1]+x[2]/2)-x[3],23);
26.59 + lp.addRow(-LP::INF,3.0*(x[1]+x[2]*2-5*x[3]+12-x[4]/3)+2*x[4]-4,23);
26.60
26.61 lp.addRow(x[1]+x[3]<=x[5]-3);
26.62 lp.addRow(-7<=x[1]+x[3]-12<=3);
26.63 @@ -183,21 +184,6 @@
26.64 std::ostringstream buf;
26.65
26.66
26.67 - //Checking the simplify function
26.68 -
26.69 -// //How to check the simplify function? A map gives no information
26.70 -// //on the question whether a given key is or is not stored in it, or
26.71 -// //it does?
26.72 -// Yes, it does, using the find() function.
26.73 - e=((p1+p2)+(p1-p2));
26.74 - e.simplify();
26.75 - buf << "Coeff. of p2 should be 0";
26.76 - // std::cout<<e[p1]<<e[p2]<<e[p3]<<std::endl;
26.77 - check(e.find(p2)==e.end(), buf.str());
26.78 -
26.79 -
26.80 -
26.81 -
26.82 e=((p1+p2)+(p1-0.99*p2));
26.83 //e.prettyPrint(std::cout);
26.84 //(e<=2).prettyPrint(std::cout);
26.85 @@ -209,7 +195,7 @@
26.86 tolerance=0.02;
26.87 e.simplify(tolerance);
26.88 buf << "Coeff. of p2 should be 0";
26.89 - check(e.find(p2)==e.end(), buf.str());
26.90 + check(const_cast<const LpSolver::Expr&>(e)[p2]==0, buf.str());
26.91
26.92
26.93 }
26.94 @@ -247,36 +233,33 @@
26.95 );
26.96 }
26.97
26.98 -#endif
26.99 }
26.100
26.101 -void solveAndCheck(LpSolverBase& lp, LpSolverBase::SolutionStatus stat,
26.102 +void solveAndCheck(LpSolver& lp, LpSolver::ProblemType stat,
26.103 double exp_opt) {
26.104 using std::string;
26.105 lp.solve();
26.106 - //int decimal,sign;
26.107 +
26.108 std::ostringstream buf;
26.109 - buf << "Primalstatus should be: " << int(stat);
26.110 + buf << "PrimalType should be: " << int(stat) << int(lp.primalType());
26.111
26.112 - // itoa(stat,buf1, 10);
26.113 - check(lp.primalStatus()==stat, buf.str());
26.114 + check(lp.primalType()==stat, buf.str());
26.115
26.116 - if (stat == LpSolverBase::OPTIMAL) {
26.117 + if (stat == LpSolver::OPTIMAL) {
26.118 std::ostringstream sbuf;
26.119 sbuf << "Wrong optimal value: the right optimum is " << exp_opt;
26.120 - check(std::abs(lp.primalValue()-exp_opt) < 1e-3, sbuf.str());
26.121 - //+ecvt(exp_opt,2)
26.122 + check(std::abs(lp.primal()-exp_opt) < 1e-3, sbuf.str());
26.123 }
26.124 }
26.125
26.126 -void aTest(LpSolverBase & lp)
26.127 +void aTest(LpSolver & lp)
26.128 {
26.129 - typedef LpSolverBase LP;
26.130 + typedef LpSolver LP;
26.131
26.132 //The following example is very simple
26.133
26.134 - typedef LpSolverBase::Row Row;
26.135 - typedef LpSolverBase::Col Col;
26.136 + typedef LpSolver::Row Row;
26.137 + typedef LpSolver::Col Col;
26.138
26.139
26.140 Col x1 = lp.addCol();
26.141 @@ -284,7 +267,7 @@
26.142
26.143
26.144 //Constraints
26.145 - Row upright=lp.addRow(x1+x2 <=1);
26.146 + Row upright=lp.addRow(x1+2*x2 <=1);
26.147 lp.addRow(x1+x2 >=-1);
26.148 lp.addRow(x1-x2 <=1);
26.149 lp.addRow(x1-x2 >=-1);
26.150 @@ -294,129 +277,126 @@
26.151 //Objective function
26.152 lp.obj(x1+x2);
26.153
26.154 - lp.max();
26.155 + lp.sense(lp.MAX);
26.156
26.157 //Testing the problem retrieving routines
26.158 check(lp.objCoeff(x1)==1,"First term should be 1 in the obj function!");
26.159 - check(lp.isMax(),"This is a maximization!");
26.160 + check(lp.sense() == lp.MAX,"This is a maximization!");
26.161 check(lp.coeff(upright,x1)==1,"The coefficient in question is 1!");
26.162 - // std::cout<<lp.colLowerBound(x1)<<std::endl;
26.163 - check( lp.colLowerBound(x1)==0,
26.164 - "The lower bound for variable x1 should be 0.");
26.165 - check( lp.colUpperBound(x1)==LpSolverBase::INF,
26.166 - "The upper bound for variable x1 should be infty.");
26.167 - LpSolverBase::Value lb,ub;
26.168 - lp.getRowBounds(upright,lb,ub);
26.169 - check( lb==-LpSolverBase::INF,
26.170 - "The lower bound for the first row should be -infty.");
26.171 - check( ub==1,"The upper bound for the first row should be 1.");
26.172 - LpSolverBase::Expr e = lp.row(upright);
26.173 - check( e.size() == 2, "The row retrieval gives back wrong expression.");
26.174 - check( e[x1] == 1, "The first coefficient should 1.");
26.175 - check( e[x2] == 1, "The second coefficient should 1.");
26.176 + check(lp.colLowerBound(x1)==0,
26.177 + "The lower bound for variable x1 should be 0.");
26.178 + check(lp.colUpperBound(x1)==LpSolver::INF,
26.179 + "The upper bound for variable x1 should be infty.");
26.180 + check(lp.rowLowerBound(upright) == -LpSolver::INF,
26.181 + "The lower bound for the first row should be -infty.");
26.182 + check(lp.rowUpperBound(upright)==1,
26.183 + "The upper bound for the first row should be 1.");
26.184 + LpSolver::Expr e = lp.row(upright);
26.185 + check(e[x1] == 1, "The first coefficient should 1.");
26.186 + check(e[x2] == 2, "The second coefficient should 1.");
26.187
26.188 - LpSolverBase::DualExpr de = lp.col(x1);
26.189 - check( de.size() == 4, "The col retrieval gives back wrong expression.");
26.190 + lp.row(upright, x1+x2 <=1);
26.191 + e = lp.row(upright);
26.192 + check(e[x1] == 1, "The first coefficient should 1.");
26.193 + check(e[x2] == 1, "The second coefficient should 1.");
26.194 +
26.195 + LpSolver::DualExpr de = lp.col(x1);
26.196 check( de[upright] == 1, "The first coefficient should 1.");
26.197
26.198 - LpSolverBase* clp = lp.copyLp();
26.199 + LpSolver* clp = lp.cloneSolver();
26.200
26.201 //Testing the problem retrieving routines
26.202 check(clp->objCoeff(x1)==1,"First term should be 1 in the obj function!");
26.203 - check(clp->isMax(),"This is a maximization!");
26.204 + check(clp->sense() == clp->MAX,"This is a maximization!");
26.205 check(clp->coeff(upright,x1)==1,"The coefficient in question is 1!");
26.206 // std::cout<<lp.colLowerBound(x1)<<std::endl;
26.207 - check( clp->colLowerBound(x1)==0,
26.208 - "The lower bound for variable x1 should be 0.");
26.209 - check( clp->colUpperBound(x1)==LpSolverBase::INF,
26.210 - "The upper bound for variable x1 should be infty.");
26.211 + check(clp->colLowerBound(x1)==0,
26.212 + "The lower bound for variable x1 should be 0.");
26.213 + check(clp->colUpperBound(x1)==LpSolver::INF,
26.214 + "The upper bound for variable x1 should be infty.");
26.215
26.216 - clp->getRowBounds(upright,lb,ub);
26.217 - check( lb==-LpSolverBase::INF,
26.218 - "The lower bound for the first row should be -infty.");
26.219 - check( ub==1,"The upper bound for the first row should be 1.");
26.220 + check(lp.rowLowerBound(upright)==-LpSolver::INF,
26.221 + "The lower bound for the first row should be -infty.");
26.222 + check(lp.rowUpperBound(upright)==1,
26.223 + "The upper bound for the first row should be 1.");
26.224 e = clp->row(upright);
26.225 - check( e.size() == 2, "The row retrieval gives back wrong expression.");
26.226 - check( e[x1] == 1, "The first coefficient should 1.");
26.227 - check( e[x2] == 1, "The second coefficient should 1.");
26.228 + check(e[x1] == 1, "The first coefficient should 1.");
26.229 + check(e[x2] == 1, "The second coefficient should 1.");
26.230
26.231 de = clp->col(x1);
26.232 - check( de.size() == 4, "The col retrieval gives back wrong expression.");
26.233 - check( de[upright] == 1, "The first coefficient should 1.");
26.234 + check(de[upright] == 1, "The first coefficient should 1.");
26.235
26.236 delete clp;
26.237
26.238 //Maximization of x1+x2
26.239 //over the triangle with vertices (0,0) (0,1) (1,0)
26.240 double expected_opt=1;
26.241 - solveAndCheck(lp, LpSolverBase::OPTIMAL, expected_opt);
26.242 + solveAndCheck(lp, LpSolver::OPTIMAL, expected_opt);
26.243
26.244 //Minimization
26.245 - lp.min();
26.246 + lp.sense(lp.MIN);
26.247 expected_opt=0;
26.248 - solveAndCheck(lp, LpSolverBase::OPTIMAL, expected_opt);
26.249 + solveAndCheck(lp, LpSolver::OPTIMAL, expected_opt);
26.250
26.251 //Vertex (-1,0) instead of (0,0)
26.252 - lp.colLowerBound(x1, -LpSolverBase::INF);
26.253 + lp.colLowerBound(x1, -LpSolver::INF);
26.254 expected_opt=-1;
26.255 - solveAndCheck(lp, LpSolverBase::OPTIMAL, expected_opt);
26.256 + solveAndCheck(lp, LpSolver::OPTIMAL, expected_opt);
26.257
26.258 //Erase one constraint and return to maximization
26.259 - lp.eraseRow(upright);
26.260 - lp.max();
26.261 - expected_opt=LpSolverBase::INF;
26.262 - solveAndCheck(lp, LpSolverBase::INFINITE, expected_opt);
26.263 + lp.erase(upright);
26.264 + lp.sense(lp.MAX);
26.265 + expected_opt=LpSolver::INF;
26.266 + solveAndCheck(lp, LpSolver::UNBOUNDED, expected_opt);
26.267
26.268 //Infeasibilty
26.269 lp.addRow(x1+x2 <=-2);
26.270 - solveAndCheck(lp, LpSolverBase::INFEASIBLE, expected_opt);
26.271 -
26.272 - //Change problem and forget to solve
26.273 - lp.min();
26.274 - check(lp.primalStatus()==LpSolverBase::UNDEFINED,
26.275 - "Primalstatus should be UNDEFINED");
26.276 -
26.277 -
26.278 -// lp.solve();
26.279 -// if (lp.primalStatus()==LpSolverBase::OPTIMAL){
26.280 -// std::cout<< "Z = "<<lp.primalValue()
26.281 -// << " (error = " << lp.primalValue()-expected_opt
26.282 -// << "); x1 = "<<lp.primal(x1)
26.283 -// << "; x2 = "<<lp.primal(x2)
26.284 -// <<std::endl;
26.285 -
26.286 -// }
26.287 -// else{
26.288 -// std::cout<<lp.primalStatus()<<std::endl;
26.289 -// std::cout<<"Optimal solution not found!"<<std::endl;
26.290 -// }
26.291 -
26.292 -
26.293 + solveAndCheck(lp, LpSolver::INFEASIBLE, expected_opt);
26.294
26.295 }
26.296
26.297 -
26.298 int main()
26.299 {
26.300 LpSkeleton lp_skel;
26.301 lpTest(lp_skel);
26.302
26.303 #ifdef HAVE_GLPK
26.304 - LpGlpk lp_glpk1,lp_glpk2;
26.305 - lpTest(lp_glpk1);
26.306 - aTest(lp_glpk2);
26.307 + {
26.308 + LpGlpk lp_glpk1,lp_glpk2;
26.309 + lpTest(lp_glpk1);
26.310 + aTest(lp_glpk2);
26.311 + }
26.312 #endif
26.313
26.314 #ifdef HAVE_CPLEX
26.315 - LpCplex lp_cplex1,lp_cplex2;
26.316 - lpTest(lp_cplex1);
26.317 - aTest(lp_cplex2);
26.318 + try {
26.319 + LpCplex lp_cplex1,lp_cplex2;
26.320 + lpTest(lp_cplex1);
26.321 + aTest(lp_cplex2);
26.322 + } catch (CplexEnv::LicenseError& error) {
26.323 +#ifdef LEMON_FORCE_CPLEX_CHECK
26.324 + check(false, error.what());
26.325 +#else
26.326 + std::cerr << error.what() << std::endl;
26.327 + std::cerr << "Cplex license check failed, lp check skipped" << std::endl;
26.328 +#endif
26.329 + }
26.330 #endif
26.331
26.332 #ifdef HAVE_SOPLEX
26.333 - LpSoplex lp_soplex1,lp_soplex2;
26.334 - lpTest(lp_soplex1);
26.335 - aTest(lp_soplex2);
26.336 + {
26.337 + LpSoplex lp_soplex1,lp_soplex2;
26.338 + lpTest(lp_soplex1);
26.339 + aTest(lp_soplex2);
26.340 + }
26.341 +#endif
26.342 +
26.343 +#ifdef HAVE_CLP
26.344 + {
26.345 + LpClp lp_clp1,lp_clp2;
26.346 + lpTest(lp_clp1);
26.347 + aTest(lp_clp2);
26.348 + }
26.349 #endif
26.350
26.351 return 0;
27.1 --- a/test/mip_test.cc Tue Dec 02 21:40:33 2008 +0100
27.2 +++ b/test/mip_test.cc Tue Dec 02 22:48:28 2008 +0100
27.3 @@ -24,45 +24,44 @@
27.4 #endif
27.5
27.6 #ifdef HAVE_CPLEX
27.7 -#include <lemon/mip_cplex.h>
27.8 +#include <lemon/lp_cplex.h>
27.9 #endif
27.10
27.11 #ifdef HAVE_GLPK
27.12 -#include <lemon/mip_glpk.h>
27.13 +#include <lemon/lp_glpk.h>
27.14 #endif
27.15
27.16
27.17 using namespace lemon;
27.18
27.19 -void solveAndCheck(MipSolverBase& lp, MipSolverBase::SolutionStatus stat,
27.20 +void solveAndCheck(MipSolver& mip, MipSolver::ProblemType stat,
27.21 double exp_opt) {
27.22 using std::string;
27.23
27.24 - lp.solve();
27.25 + mip.solve();
27.26 //int decimal,sign;
27.27 std::ostringstream buf;
27.28 - buf << "Primalstatus should be: " << int(stat)
27.29 - <<" and it is "<<int(lp.mipStatus());
27.30 + buf << "Type should be: " << int(stat)<<" and it is "<<int(mip.type());
27.31
27.32
27.33 // itoa(stat,buf1, 10);
27.34 - check(lp.mipStatus()==stat, buf.str());
27.35 + check(mip.type()==stat, buf.str());
27.36
27.37 - if (stat == MipSolverBase::OPTIMAL) {
27.38 + if (stat == MipSolver::OPTIMAL) {
27.39 std::ostringstream sbuf;
27.40 buf << "Wrong optimal value: the right optimum is " << exp_opt;
27.41 - check(std::abs(lp.primalValue()-exp_opt) < 1e-3, sbuf.str());
27.42 + check(std::abs(mip.solValue()-exp_opt) < 1e-3, sbuf.str());
27.43 //+ecvt(exp_opt,2)
27.44 }
27.45 }
27.46
27.47 -void aTest(MipSolverBase& mip)
27.48 +void aTest(MipSolver& mip)
27.49 {
27.50 //The following example is very simple
27.51
27.52
27.53 - typedef MipSolverBase::Row Row;
27.54 - typedef MipSolverBase::Col Col;
27.55 + typedef MipSolver::Row Row;
27.56 + typedef MipSolver::Col Col;
27.57
27.58
27.59
27.60 @@ -90,18 +89,18 @@
27.61 //Maximization of x1
27.62 //over the triangle with vertices (0,0),(4/5,2/5),(0,2)
27.63 double expected_opt=4.0/5.0;
27.64 - solveAndCheck(mip, MipSolverBase::OPTIMAL, expected_opt);
27.65 + solveAndCheck(mip, MipSolver::OPTIMAL, expected_opt);
27.66
27.67 //Restrict x2 to integer
27.68 - mip.colType(x2,MipSolverBase::INT);
27.69 + mip.colType(x2,MipSolver::INTEGER);
27.70 expected_opt=1.0/2.0;
27.71 - solveAndCheck(mip, MipSolverBase::OPTIMAL, expected_opt);
27.72 + solveAndCheck(mip, MipSolver::OPTIMAL, expected_opt);
27.73
27.74
27.75 //Restrict both to integer
27.76 - mip.colType(x1,MipSolverBase::INT);
27.77 + mip.colType(x1,MipSolver::INTEGER);
27.78 expected_opt=0;
27.79 - solveAndCheck(mip, MipSolverBase::OPTIMAL, expected_opt);
27.80 + solveAndCheck(mip, MipSolver::OPTIMAL, expected_opt);
27.81
27.82
27.83
27.84 @@ -112,13 +111,24 @@
27.85 {
27.86
27.87 #ifdef HAVE_GLPK
27.88 - MipGlpk mip1;
27.89 - aTest(mip1);
27.90 + {
27.91 + MipGlpk mip1;
27.92 + aTest(mip1);
27.93 + }
27.94 #endif
27.95
27.96 #ifdef HAVE_CPLEX
27.97 - MipCplex mip2;
27.98 - aTest(mip2);
27.99 + try {
27.100 + MipCplex mip2;
27.101 + aTest(mip2);
27.102 + } catch (CplexEnv::LicenseError& error) {
27.103 +#ifdef LEMON_FORCE_CPLEX_CHECK
27.104 + check(false, error.what());
27.105 +#else
27.106 + std::cerr << error.what() << std::endl;
27.107 + std::cerr << "Cplex license check failed, lp check skipped" << std::endl;
27.108 +#endif
27.109 + }
27.110 #endif
27.111
27.112 return 0;