Thorough redesign of the LP/MIP interface (#44)
authorBalazs Dezso <deba@inf.elte.hu>
Tue, 02 Dec 2008 22:48:28 +0100
changeset 459ed54c0d13df0
parent 458 7afc121e0689
child 460 76ec7bd57026
child 502 17cabb114d52
Thorough redesign of the LP/MIP interface (#44)

- Redesigned class structure
- Redesigned iterators
- Some functions in the basic interface redesigned
- More complete setting functions
- Ray retrieving functions
- Lot of improvements
- Cplex common env
- CLP macro definition to config.h.in
- Update lp.h to also use soplex and clp
- Remove default_solver_name
- New solverName() function in solvers
- Handle exceptions for MipCplex test
- Rename tolerance parameter to epsilon
- Rename MapIt to CoeffIt
- Lot of documentation improvements
- Various bugfixes
configure.ac
lemon/CMakeLists.txt
lemon/Makefile.am
lemon/bits/lp_id.h
lemon/bits/solver_bits.h
lemon/config.h.in
lemon/lp.h
lemon/lp_base.cc
lemon/lp_base.h
lemon/lp_clp.cc
lemon/lp_clp.h
lemon/lp_cplex.cc
lemon/lp_cplex.h
lemon/lp_glpk.cc
lemon/lp_glpk.h
lemon/lp_skeleton.cc
lemon/lp_skeleton.h
lemon/lp_soplex.cc
lemon/lp_soplex.h
lemon/mip_cplex.cc
lemon/mip_cplex.h
lemon/mip_glpk.cc
lemon/mip_glpk.h
m4/lx_check_clp.m4
m4/lx_check_glpk.m4
test/lp_test.cc
test/mip_test.cc
     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;