lp.dox
changeset 55 edb7d5759e0d
parent 50 72867897fcba
child 57 18404ec968ca
equal deleted inserted replaced
4:7713ce582932 5:6e13db29f785
    42 Currently, the following linear and mixed integer programming packages are
    42 Currently, the following linear and mixed integer programming packages are
    43 supported: GLPK, Clp, Cbc, ILOG CPLEX and SoPlex.
    43 supported: GLPK, Clp, Cbc, ILOG CPLEX and SoPlex.
    44 However, additional wrapper classes for new solvers can also be implemented
    44 However, additional wrapper classes for new solvers can also be implemented
    45 quite easily.
    45 quite easily.
    46 
    46 
    47 In this section, we will show two examples. The first one shows how simple
    47 [SEC]sec_lp_basics[SEC] Basic LP Features
    48 it is to formalize and solve an LP problem in LEMON, while the second one
    48 
    49 shows how LEMON facilitates solving network optimization problems using LP
    49 The following example demonstrates how simple it is to formalize and solve
    50 solvers.
    50 an LP problem in LEMON. You can find the whole program in \ref lp_demo.cc.
    51 
    51 
    52 \code
    52 \dontinclude lp_demo.cc
    53   Lp lp;
    53 \skip Create
    54 
    54 \until }
    55   Lp::Col x1 = lp.addCol();
    55 \until }
    56   Lp::Col x2 = lp.addCol();
    56 
    57 
    57 \ref LpBase::Col "Lp::Col" type represents the columns, i.e. the (primal)
    58   lp.addRow(0 <= x1 + x2 <= 100);
    58 variables of the LP problem. The numerical operators can be used to form
    59   lp.addRow(2 * x1 <= x2 + 32);
    59 expressions from columns, which are required for specifying rows
    60 
    60 (constraints) and the objective function. Due to the suitable operator
    61   lp.colLowerBound(x1, 0);
    61 overloads, a problem can be described in C++ conveniently, directly as it is
    62   lp.colUpperBound(x2, 100);
       
    63 
       
    64   lp.max();
       
    65   lp.obj(10 * x1 + 6 * x2);
       
    66   lp.solve();
       
    67 
       
    68   std::cout << "Objective function value: " << lp.primal() << std::endl;
       
    69   std::cout << "x1 = " << lp.primal(x1) << std::endl;
       
    70   std::cout << "x2 = " << lp.primal(x2) << std::endl;
       
    71 \endcode
       
    72 
       
    73 \ref LpBase::Col "Lp::Col" type represents the variables in the LP problems,
       
    74 while \ref LpBase::Row "Lp::Row" represents the constraints. The numerical
       
    75 operators can be used to form expressions from columns and dual
       
    76 expressions from rows. Due to the suitable operator overloads,
       
    77 a problem can be described in C++ conveniently, directly as it is
       
    78 expressed in mathematics.
    62 expressed in mathematics.
    79 
    63 After specifying all the parameters of the problem, we can solve it using
       
    64 the \ref LpSolver::solve() "solve()" function. The status of the solution
       
    65 (namely OPTIMAL, UNBOUNDED, INFEASIBLE etc.) can be obtained using
       
    66 \ref LpSolver::primalType() "primalType()" and the results can be
       
    67 obtained using \ref LpSolver::primal() "primal()".
       
    68 
       
    69 The above problem has an optimal solution. If you execute this example,
       
    70 it will print out the following results.
       
    71 
       
    72 \code
       
    73   Objective function value: 67.5
       
    74   x1 = 7.5
       
    75   x2 = 10
       
    76 \endcode
       
    77 
       
    78 However, if you, for example, removed the lines that specify the rows,
       
    79 you would obtain an LP problem, for which the objective function value
       
    80 is unbounded over the feasible solutions. Thus the program would print
       
    81 out this line.
       
    82 
       
    83 \code
       
    84   Optimal solution found.
       
    85 \endcode
       
    86 
       
    87 If you would like to build linear expressions or constraints in more steps,
       
    88 then you can use the classes \ref LpBase::Expr "Lp::Expr" and
       
    89 \ref LpBase::Constr "Lp::Constr". For example, this line
       
    90 \code
       
    91   lp.addRow(x1 - 5 <= x2);
       
    92 \endcode
       
    93 can also be written as
       
    94 \code
       
    95   Lp::Expr e1, e2;
       
    96   e1 = x1;
       
    97   e1 -= 5;
       
    98   e2 = x2;
       
    99   Lp::Constr c = e1 <= e2;
       
   100   lp.addRow(c);
       
   101 \endcode
       
   102 
       
   103 These classes make it easy to build more complex expressions and constraints,
       
   104 e.g. using loops. For example, we can sum all the variables (columns) in an
       
   105 expression using the \ref LpBase::ColIt "Lp::ColIt" iterator, which can be
       
   106 used the same as node and arc iterators for graphs.
       
   107 
       
   108 \code
       
   109   Lp::Expr sum;
       
   110   for (Lp::ColIt col(lp); col != INVALID; ++col) {
       
   111     sum += col;
       
   112   }
       
   113 \endcode
       
   114 
       
   115 After solving the problem, you can query the value of any primal expression,
       
   116 not just the individual columns and the objective function.
       
   117 
       
   118 \todo Check this example after closing ticket #326.
       
   119 
       
   120 \code
       
   121   std::cout << lp.primal(sum) << std::endl;
       
   122 \endcode
       
   123 
       
   124 Of course, working with the dual problem is also supported by the LP
       
   125 interface. \ref LpBase::Row "Lp::Row" represents the rows, i.e. the dual
       
   126 variables of the LP problem.
       
   127 
       
   128 \code
       
   129   Lp::Row r = lp.addRow(x2 >= 3);
       
   130 \endcode
       
   131 
       
   132 The dual solutions of an LP problem can be obtained using the functions
       
   133 \ref LpSolver::dualType() "dualType()" and \ref LpSolver::dual "dual()"
       
   134 (after solving the problem).
       
   135 
       
   136 \code
       
   137   std::cout << lp.dual(r) << std::endl;
       
   138 \endcode
       
   139 
       
   140 \ref LpBase::DualExpr "Lp::DualExpr" can be used to build dual expressions
       
   141 from rows and \ref LpBase::RowIt "Lp::RowIt" can be used to list the rows.
       
   142 
       
   143 \code
       
   144   Lp::DualExpr dual_sum;
       
   145   for (Lp::RowIt row(lp); row != INVALID; ++row) {
       
   146     dual_sum += row;
       
   147   }
       
   148 \endcode
       
   149 
       
   150 The LP solver interface provides several other features, which are
       
   151 documented in the classes \ref LpBase and \ref LpSolver.
       
   152 For detailed documentation, see these classes in the reference manual.
       
   153 
       
   154 If you would like to use a specific solver instead of the default one,
       
   155 you can use \ref GlpkLp, \ref ClpLp, \ref CplexLp etc. instead of
       
   156 the class \ref Lp.
       
   157 
       
   158 
       
   159 [SEC]sec_lp_mip[SEC] Mixed Integer Programming
       
   160 
       
   161 LEMON also provides a similar high-level interface for mixed integer
       
   162 programming (MIP) solvers. The default MIP solver can be used through
       
   163 the class \ref Mip, while the concrete solvers are implemented in the
       
   164 classes \ref GlpkMip, \ref CbcMip, \ref CplexMip etc.
       
   165 
       
   166 The following example demonstrates the usage of the MIP solver interface.
       
   167 The whole program can be found in \ref mip_demo.cc.
       
   168 
       
   169 \dontinclude mip_demo.cc
       
   170 \skip Create
       
   171 \until }
       
   172 \until }
       
   173 
       
   174 \todo Check this demo file after closing ticket #326.
       
   175 E.g. could we write <tt>mip.sol()</tt> instead of <tt>mip.solValue()</tt>?
       
   176 Or could we write <tt>primalValue()</tt> for \c Lp in \c lp_demo.cc?
       
   177 
       
   178 In this program, the same problem is built as in the above example,
       
   179 with the exception that the variable \c x1 is specified to be
       
   180 \c INTEGER valued. \c x2 is set to \c REAL, which is the default option.
       
   181 
       
   182 \code
       
   183   // Set the type of the columns
       
   184   mip.colType(x1, Mip::INTEGER);
       
   185   mip.colType(x2, Mip::REAL);
       
   186 \endcode
       
   187 
       
   188 Because of this integrality requirement, the results will be different
       
   189 from the LP solution.
       
   190 
       
   191 \code
       
   192   Objective function value: 67
       
   193   x1 = 8
       
   194   x2 = 9
       
   195 \endcode
       
   196 
       
   197 The documnetation of the MIP solver interface can be found in the
       
   198 reference manual at the class \ref MipSolver. The common parts of the
       
   199 LP and MIP interfaces are docmented in their common ancestor class
       
   200 \ref LpBase.
       
   201 
       
   202 
       
   203 [SEC]sec_lp_optimization[SEC] Solving Complex Optimization Problems
       
   204 
       
   205 The LP and MIP solvers are powerful tools for solving various complex
       
   206 optimization problems, as well.
    80 The following example solves a maximum flow problem with linear
   207 The following example solves a maximum flow problem with linear
    81 programming. Several other graph optimization problems can also be
   208 programming, see the whole program in \re lp_maxflow_demo.cc.
    82 expressed as linear programs and this interface helps to solve them easily
   209 Several other graph optimization problems can also be expressed as
    83 (though usually not so efficiently as by a direct combinatorial method).
   210 linear programs and the interface provided in LEMON facilitates solving
    84 
   211 them easily (though usually not so efficiently as by a direct
    85 \code
   212 combinatorial method, if one exists). 
    86   Lp lp;
   213 
    87   ListDigraph::ArcMap<Lp::Col> f(g);
   214 \dontinclude lp_maxflow_demo.cc
    88   lp.addColSet(f);
   215 \skip DIGRAPH_TYPEDEFS
    89 
   216 \until solve()
    90   // Capacity constraints
   217 
    91   for (ListDigraph::ArcIt a(g); a != INVALID; ++a) {
   218 \note This problem can be solved much more efficiently using common
    92     lp.colLowerBound(f[a], 0);
   219 combinatorial optimization methods, such as the \ref Preflow
    93     lp.colUpperBound(f[a], capacity[a]);
   220 "preflow push-relabel algorithm".
    94   }
       
    95 
       
    96   // Flow conservation constraints
       
    97   for (ListDigraph::NodeIt n(g); n != INVALID; ++n) {
       
    98     if (n == src || n == trg) continue;
       
    99     Lp::Expr e;
       
   100     for (ListDigraph::OutArcIt a(g,n); a != INVALID; ++a) e += f[a];
       
   101     for (ListDigraph::InArcIt a(g,n); a != INVALID; ++a) e -= f[a];
       
   102     lp.addRow(e == 0);
       
   103   }
       
   104 
       
   105   // Objective function
       
   106   Lp::Expr o;
       
   107   for (ListDigraph::OutArcIt a(g,src); a != INVALID; ++a) o += f[a];
       
   108   for (ListDigraph::InArcIt a(g,src); a != INVALID; ++a) o -= f[a];
       
   109 
       
   110   lp.max();
       
   111   lp.obj(o);
       
   112   lp.solve();
       
   113 
       
   114   std::cout << "Max flow value: " << lp.primal() << std::endl;
       
   115 \endcode
       
   116 
   221 
   117 [TRAILER]
   222 [TRAILER]
   118 */
   223 */
   119 }
   224 }