lp.dox
author Peter Kovacs <kpeter@inf.elte.hu>
Mon, 01 Mar 2010 02:30:00 +0100
changeset 58 10b6a5b7d4c0
parent 55 edb7d5759e0d
child 60 202688f8024a
permissions -rw-r--r--
Improve Algorithms section (it is still under construction)
kpeter@30
     1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
kpeter@30
     2
 *
kpeter@30
     3
 * This file is a part of LEMON, a generic C++ optimization library.
kpeter@30
     4
 *
kpeter@32
     5
 * Copyright (C) 2003-2010
kpeter@30
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
kpeter@30
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
kpeter@30
     8
 *
kpeter@30
     9
 * Permission to use, modify and distribute this software is granted
kpeter@30
    10
 * provided that this copyright notice appears in all copies. For
kpeter@30
    11
 * precise terms see the accompanying LICENSE file.
kpeter@30
    12
 *
kpeter@30
    13
 * This software is provided "AS IS" with no warranty of any kind,
kpeter@30
    14
 * express or implied, and with no claim as to its suitability for any
kpeter@30
    15
 * purpose.
kpeter@30
    16
 *
kpeter@30
    17
 */
kpeter@30
    18
kpeter@30
    19
namespace lemon {
kpeter@30
    20
/**
kpeter@30
    21
[PAGE]sec_lp[PAGE] Linear Programming Interface
kpeter@30
    22
kpeter@48
    23
Linear programming (LP) is one of the most important general methods of
kpeter@48
    24
operations research. Countless optimization problems can be formulated
kpeter@48
    25
and solved using LP techniques.
kpeter@48
    26
Therefore, developing efficient LP solvers has been of high practical
kpeter@48
    27
interest for a long time.
kpeter@48
    28
Nowadays various efficient LP solvers are available, including both
kpeter@48
    29
open source and commercial software packages.
kpeter@48
    30
Therefore, LEMON does not implement its own solver, but it features
kpeter@48
    31
wrapper classes for several known LP packages providing a common
kpeter@48
    32
high-level interface for all of them.
kpeter@30
    33
kpeter@48
    34
The advantage of this approach is twofold. First, our C++ interface is
kpeter@48
    35
more comfortable than the typical native interfaces of the solvers.
kpeter@48
    36
Second, changing the underlying solver in a certain application using
kpeter@48
    37
LEMON's LP interface needs no effort. So, for example, one may try her
kpeter@48
    38
idea using an open source solver, demonstrate its usability for a customer
kpeter@48
    39
and if it works well, but the performance should be improved, then the
kpeter@48
    40
customer may decide to purchase and use a better commercial solver.
kpeter@48
    41
kpeter@48
    42
Currently, the following linear and mixed integer programming packages are
kpeter@48
    43
supported: GLPK, Clp, Cbc, ILOG CPLEX and SoPlex.
kpeter@48
    44
However, additional wrapper classes for new solvers can also be implemented
kpeter@48
    45
quite easily.
kpeter@48
    46
kpeter@55
    47
[SEC]sec_lp_basics[SEC] Basic LP Features
kpeter@55
    48
kpeter@55
    49
The following example demonstrates how simple it is to formalize and solve
kpeter@55
    50
an LP problem in LEMON. You can find the whole program in \ref lp_demo.cc.
kpeter@55
    51
kpeter@55
    52
\dontinclude lp_demo.cc
kpeter@55
    53
\skip Create
kpeter@55
    54
\until }
kpeter@55
    55
\until }
kpeter@55
    56
kpeter@55
    57
\ref LpBase::Col "Lp::Col" type represents the columns, i.e. the (primal)
kpeter@55
    58
variables of the LP problem. The numerical operators can be used to form
kpeter@55
    59
expressions from columns, which are required for specifying rows
kpeter@55
    60
(constraints) and the objective function. Due to the suitable operator
kpeter@55
    61
overloads, a problem can be described in C++ conveniently, directly as it is
kpeter@55
    62
expressed in mathematics.
kpeter@55
    63
After specifying all the parameters of the problem, we can solve it using
kpeter@55
    64
the \ref LpSolver::solve() "solve()" function. The status of the solution
kpeter@55
    65
(namely OPTIMAL, UNBOUNDED, INFEASIBLE etc.) can be obtained using
kpeter@55
    66
\ref LpSolver::primalType() "primalType()" and the results can be
kpeter@55
    67
obtained using \ref LpSolver::primal() "primal()".
kpeter@55
    68
kpeter@55
    69
The above problem has an optimal solution. If you execute this example,
kpeter@55
    70
it will print out the following results.
kpeter@30
    71
kpeter@30
    72
\code
kpeter@55
    73
  Objective function value: 67.5
kpeter@55
    74
  x1 = 7.5
kpeter@55
    75
  x2 = 10
kpeter@30
    76
\endcode
kpeter@30
    77
kpeter@55
    78
However, if you, for example, removed the lines that specify the rows,
kpeter@55
    79
you would obtain an LP problem, for which the objective function value
kpeter@55
    80
is unbounded over the feasible solutions. Thus the program would print
kpeter@55
    81
out this line.
kpeter@30
    82
kpeter@30
    83
\code
kpeter@55
    84
  Optimal solution found.
kpeter@55
    85
\endcode
kpeter@30
    86
kpeter@55
    87
If you would like to build linear expressions or constraints in more steps,
kpeter@55
    88
then you can use the classes \ref LpBase::Expr "Lp::Expr" and
kpeter@55
    89
\ref LpBase::Constr "Lp::Constr". For example, this line
kpeter@55
    90
\code
kpeter@55
    91
  lp.addRow(x1 - 5 <= x2);
kpeter@55
    92
\endcode
kpeter@55
    93
can also be written as
kpeter@55
    94
\code
kpeter@55
    95
  Lp::Expr e1, e2;
kpeter@55
    96
  e1 = x1;
kpeter@55
    97
  e1 -= 5;
kpeter@55
    98
  e2 = x2;
kpeter@55
    99
  Lp::Constr c = e1 <= e2;
kpeter@55
   100
  lp.addRow(c);
kpeter@55
   101
\endcode
kpeter@55
   102
kpeter@55
   103
These classes make it easy to build more complex expressions and constraints,
kpeter@55
   104
e.g. using loops. For example, we can sum all the variables (columns) in an
kpeter@55
   105
expression using the \ref LpBase::ColIt "Lp::ColIt" iterator, which can be
kpeter@55
   106
used the same as node and arc iterators for graphs.
kpeter@55
   107
kpeter@55
   108
\code
kpeter@55
   109
  Lp::Expr sum;
kpeter@55
   110
  for (Lp::ColIt col(lp); col != INVALID; ++col) {
kpeter@55
   111
    sum += col;
kpeter@30
   112
  }
kpeter@55
   113
\endcode
kpeter@30
   114
kpeter@55
   115
After solving the problem, you can query the value of any primal expression,
kpeter@55
   116
not just the individual columns and the objective function.
kpeter@55
   117
kpeter@55
   118
\todo Check this example after closing ticket #326.
kpeter@55
   119
kpeter@55
   120
\code
kpeter@55
   121
  std::cout << lp.primal(sum) << std::endl;
kpeter@55
   122
\endcode
kpeter@55
   123
kpeter@55
   124
Of course, working with the dual problem is also supported by the LP
kpeter@55
   125
interface. \ref LpBase::Row "Lp::Row" represents the rows, i.e. the dual
kpeter@55
   126
variables of the LP problem.
kpeter@55
   127
kpeter@55
   128
\code
kpeter@55
   129
  Lp::Row r = lp.addRow(x2 >= 3);
kpeter@55
   130
\endcode
kpeter@55
   131
kpeter@55
   132
The dual solutions of an LP problem can be obtained using the functions
kpeter@55
   133
\ref LpSolver::dualType() "dualType()" and \ref LpSolver::dual "dual()"
kpeter@55
   134
(after solving the problem).
kpeter@55
   135
kpeter@55
   136
\code
kpeter@55
   137
  std::cout << lp.dual(r) << std::endl;
kpeter@55
   138
\endcode
kpeter@55
   139
kpeter@55
   140
\ref LpBase::DualExpr "Lp::DualExpr" can be used to build dual expressions
kpeter@55
   141
from rows and \ref LpBase::RowIt "Lp::RowIt" can be used to list the rows.
kpeter@55
   142
kpeter@55
   143
\code
kpeter@55
   144
  Lp::DualExpr dual_sum;
kpeter@55
   145
  for (Lp::RowIt row(lp); row != INVALID; ++row) {
kpeter@55
   146
    dual_sum += row;
kpeter@30
   147
  }
kpeter@55
   148
\endcode
kpeter@30
   149
kpeter@55
   150
The LP solver interface provides several other features, which are
kpeter@55
   151
documented in the classes \ref LpBase and \ref LpSolver.
kpeter@55
   152
For detailed documentation, see these classes in the reference manual.
kpeter@30
   153
kpeter@55
   154
If you would like to use a specific solver instead of the default one,
kpeter@55
   155
you can use \ref GlpkLp, \ref ClpLp, \ref CplexLp etc. instead of
kpeter@55
   156
the class \ref Lp.
kpeter@50
   157
kpeter@55
   158
kpeter@55
   159
[SEC]sec_lp_mip[SEC] Mixed Integer Programming
kpeter@55
   160
kpeter@55
   161
LEMON also provides a similar high-level interface for mixed integer
kpeter@55
   162
programming (MIP) solvers. The default MIP solver can be used through
kpeter@55
   163
the class \ref Mip, while the concrete solvers are implemented in the
kpeter@55
   164
classes \ref GlpkMip, \ref CbcMip, \ref CplexMip etc.
kpeter@55
   165
kpeter@55
   166
The following example demonstrates the usage of the MIP solver interface.
kpeter@55
   167
The whole program can be found in \ref mip_demo.cc.
kpeter@55
   168
kpeter@55
   169
\dontinclude mip_demo.cc
kpeter@55
   170
\skip Create
kpeter@55
   171
\until }
kpeter@55
   172
\until }
kpeter@55
   173
kpeter@55
   174
\todo Check this demo file after closing ticket #326.
kpeter@55
   175
E.g. could we write <tt>mip.sol()</tt> instead of <tt>mip.solValue()</tt>?
kpeter@55
   176
Or could we write <tt>primalValue()</tt> for \c Lp in \c lp_demo.cc?
kpeter@55
   177
kpeter@55
   178
In this program, the same problem is built as in the above example,
kpeter@55
   179
with the exception that the variable \c x1 is specified to be
kpeter@55
   180
\c INTEGER valued. \c x2 is set to \c REAL, which is the default option.
kpeter@55
   181
kpeter@55
   182
\code
kpeter@55
   183
  // Set the type of the columns
kpeter@55
   184
  mip.colType(x1, Mip::INTEGER);
kpeter@55
   185
  mip.colType(x2, Mip::REAL);
kpeter@30
   186
\endcode
kpeter@30
   187
kpeter@55
   188
Because of this integrality requirement, the results will be different
kpeter@55
   189
from the LP solution.
kpeter@55
   190
kpeter@55
   191
\code
kpeter@55
   192
  Objective function value: 67
kpeter@55
   193
  x1 = 8
kpeter@55
   194
  x2 = 9
kpeter@55
   195
\endcode
kpeter@55
   196
kpeter@57
   197
The documentation of the MIP solver interface can be found in the
kpeter@55
   198
reference manual at the class \ref MipSolver. The common parts of the
kpeter@57
   199
LP and MIP interfaces are documented in their common ancestor class
kpeter@55
   200
\ref LpBase.
kpeter@55
   201
kpeter@55
   202
kpeter@55
   203
[SEC]sec_lp_optimization[SEC] Solving Complex Optimization Problems
kpeter@55
   204
kpeter@55
   205
The LP and MIP solvers are powerful tools for solving various complex
kpeter@55
   206
optimization problems, as well.
kpeter@55
   207
The following example solves a maximum flow problem with linear
kpeter@55
   208
programming, see the whole program in \re lp_maxflow_demo.cc.
kpeter@55
   209
Several other graph optimization problems can also be expressed as
kpeter@55
   210
linear programs and the interface provided in LEMON facilitates solving
kpeter@55
   211
them easily (though usually not so efficiently as by a direct
kpeter@55
   212
combinatorial method, if one exists). 
kpeter@55
   213
kpeter@55
   214
\dontinclude lp_maxflow_demo.cc
kpeter@55
   215
\skip DIGRAPH_TYPEDEFS
kpeter@55
   216
\until solve()
kpeter@55
   217
kpeter@55
   218
\note This problem can be solved much more efficiently using common
kpeter@55
   219
combinatorial optimization methods, such as the \ref Preflow
kpeter@55
   220
"preflow push-relabel algorithm".
kpeter@55
   221
kpeter@30
   222
[TRAILER]
kpeter@30
   223
*/
kpeter@32
   224
}