kpeter@30: /* -*- mode: C++; indent-tabs-mode: nil; -*-
kpeter@30: *
kpeter@30: * This file is a part of LEMON, a generic C++ optimization library.
kpeter@30: *
kpeter@32: * Copyright (C) 2003-2010
kpeter@30: * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
kpeter@30: * (Egervary Research Group on Combinatorial Optimization, EGRES).
kpeter@30: *
kpeter@30: * Permission to use, modify and distribute this software is granted
kpeter@30: * provided that this copyright notice appears in all copies. For
kpeter@30: * precise terms see the accompanying LICENSE file.
kpeter@30: *
kpeter@30: * This software is provided "AS IS" with no warranty of any kind,
kpeter@30: * express or implied, and with no claim as to its suitability for any
kpeter@30: * purpose.
kpeter@30: *
kpeter@30: */
kpeter@30:
kpeter@30: namespace lemon {
kpeter@30: /**
kpeter@30: [PAGE]sec_lp[PAGE] Linear Programming Interface
kpeter@30:
kpeter@48: Linear programming (LP) is one of the most important general methods of
kpeter@48: operations research. Countless optimization problems can be formulated
kpeter@48: and solved using LP techniques.
kpeter@48: Therefore, developing efficient LP solvers has been of high practical
kpeter@48: interest for a long time.
kpeter@48: Nowadays various efficient LP solvers are available, including both
kpeter@48: open source and commercial software packages.
kpeter@48: Therefore, LEMON does not implement its own solver, but it features
kpeter@48: wrapper classes for several known LP packages providing a common
kpeter@48: high-level interface for all of them.
kpeter@30:
kpeter@48: The advantage of this approach is twofold. First, our C++ interface is
kpeter@48: more comfortable than the typical native interfaces of the solvers.
kpeter@48: Second, changing the underlying solver in a certain application using
kpeter@48: LEMON's LP interface needs no effort. So, for example, one may try her
kpeter@48: idea using an open source solver, demonstrate its usability for a customer
kpeter@48: and if it works well, but the performance should be improved, then the
kpeter@48: customer may decide to purchase and use a better commercial solver.
kpeter@48:
kpeter@48: Currently, the following linear and mixed integer programming packages are
kpeter@48: supported: GLPK, Clp, Cbc, ILOG CPLEX and SoPlex.
kpeter@48: However, additional wrapper classes for new solvers can also be implemented
kpeter@48: quite easily.
kpeter@48:
kpeter@55: [SEC]sec_lp_basics[SEC] Basic LP Features
kpeter@55:
kpeter@55: The following example demonstrates how simple it is to formalize and solve
kpeter@55: an LP problem in LEMON. You can find the whole program in \ref lp_demo.cc.
kpeter@55:
kpeter@55: \dontinclude lp_demo.cc
kpeter@55: \skip Create
kpeter@55: \until }
kpeter@55: \until }
kpeter@55:
kpeter@55: \ref LpBase::Col "Lp::Col" type represents the columns, i.e. the (primal)
kpeter@55: variables of the LP problem. The numerical operators can be used to form
kpeter@55: expressions from columns, which are required for specifying rows
kpeter@55: (constraints) and the objective function. Due to the suitable operator
kpeter@55: overloads, a problem can be described in C++ conveniently, directly as it is
kpeter@55: expressed in mathematics.
kpeter@55: After specifying all the parameters of the problem, we can solve it using
kpeter@55: the \ref LpSolver::solve() "solve()" function. The status of the solution
kpeter@55: (namely OPTIMAL, UNBOUNDED, INFEASIBLE etc.) can be obtained using
kpeter@55: \ref LpSolver::primalType() "primalType()" and the results can be
kpeter@55: obtained using \ref LpSolver::primal() "primal()".
kpeter@55:
kpeter@55: The above problem has an optimal solution. If you execute this example,
kpeter@55: it will print out the following results.
kpeter@30:
kpeter@30: \code
kpeter@55: Objective function value: 67.5
kpeter@55: x1 = 7.5
kpeter@55: x2 = 10
kpeter@30: \endcode
kpeter@30:
kpeter@55: However, if you, for example, removed the lines that specify the rows,
kpeter@55: you would obtain an LP problem, for which the objective function value
kpeter@55: is unbounded over the feasible solutions. Thus the program would print
kpeter@55: out this line.
kpeter@30:
kpeter@30: \code
kpeter@55: Optimal solution found.
kpeter@55: \endcode
kpeter@30:
kpeter@55: If you would like to build linear expressions or constraints in more steps,
kpeter@55: then you can use the classes \ref LpBase::Expr "Lp::Expr" and
kpeter@55: \ref LpBase::Constr "Lp::Constr". For example, this line
kpeter@55: \code
kpeter@55: lp.addRow(x1 - 5 <= x2);
kpeter@55: \endcode
kpeter@55: can also be written as
kpeter@55: \code
kpeter@55: Lp::Expr e1, e2;
kpeter@55: e1 = x1;
kpeter@55: e1 -= 5;
kpeter@55: e2 = x2;
kpeter@55: Lp::Constr c = e1 <= e2;
kpeter@55: lp.addRow(c);
kpeter@55: \endcode
kpeter@55:
kpeter@55: These classes make it easy to build more complex expressions and constraints,
kpeter@55: e.g. using loops. For example, we can sum all the variables (columns) in an
kpeter@55: expression using the \ref LpBase::ColIt "Lp::ColIt" iterator, which can be
kpeter@55: used the same as node and arc iterators for graphs.
kpeter@55:
kpeter@55: \code
kpeter@55: Lp::Expr sum;
kpeter@55: for (Lp::ColIt col(lp); col != INVALID; ++col) {
kpeter@55: sum += col;
kpeter@30: }
kpeter@55: \endcode
kpeter@30:
kpeter@55: After solving the problem, you can query the value of any primal expression,
kpeter@55: not just the individual columns and the objective function.
kpeter@55:
kpeter@55: \todo Check this example after closing ticket #326.
kpeter@55:
kpeter@55: \code
kpeter@55: std::cout << lp.primal(sum) << std::endl;
kpeter@55: \endcode
kpeter@55:
kpeter@55: Of course, working with the dual problem is also supported by the LP
kpeter@55: interface. \ref LpBase::Row "Lp::Row" represents the rows, i.e. the dual
kpeter@55: variables of the LP problem.
kpeter@55:
kpeter@55: \code
kpeter@55: Lp::Row r = lp.addRow(x2 >= 3);
kpeter@55: \endcode
kpeter@55:
kpeter@55: The dual solutions of an LP problem can be obtained using the functions
kpeter@55: \ref LpSolver::dualType() "dualType()" and \ref LpSolver::dual "dual()"
kpeter@55: (after solving the problem).
kpeter@55:
kpeter@55: \code
kpeter@55: std::cout << lp.dual(r) << std::endl;
kpeter@55: \endcode
kpeter@55:
kpeter@55: \ref LpBase::DualExpr "Lp::DualExpr" can be used to build dual expressions
kpeter@55: from rows and \ref LpBase::RowIt "Lp::RowIt" can be used to list the rows.
kpeter@55:
kpeter@55: \code
kpeter@55: Lp::DualExpr dual_sum;
kpeter@55: for (Lp::RowIt row(lp); row != INVALID; ++row) {
kpeter@55: dual_sum += row;
kpeter@30: }
kpeter@55: \endcode
kpeter@30:
kpeter@55: The LP solver interface provides several other features, which are
kpeter@55: documented in the classes \ref LpBase and \ref LpSolver.
kpeter@55: For detailed documentation, see these classes in the reference manual.
kpeter@30:
kpeter@55: If you would like to use a specific solver instead of the default one,
kpeter@55: you can use \ref GlpkLp, \ref ClpLp, \ref CplexLp etc. instead of
kpeter@55: the class \ref Lp.
kpeter@50:
kpeter@55:
kpeter@55: [SEC]sec_lp_mip[SEC] Mixed Integer Programming
kpeter@55:
kpeter@55: LEMON also provides a similar high-level interface for mixed integer
kpeter@55: programming (MIP) solvers. The default MIP solver can be used through
kpeter@55: the class \ref Mip, while the concrete solvers are implemented in the
kpeter@55: classes \ref GlpkMip, \ref CbcMip, \ref CplexMip etc.
kpeter@55:
kpeter@55: The following example demonstrates the usage of the MIP solver interface.
kpeter@55: The whole program can be found in \ref mip_demo.cc.
kpeter@55:
kpeter@55: \dontinclude mip_demo.cc
kpeter@55: \skip Create
kpeter@55: \until }
kpeter@55: \until }
kpeter@55:
kpeter@55: \todo Check this demo file after closing ticket #326.
kpeter@55: E.g. could we write mip.sol() instead of mip.solValue()?
kpeter@55: Or could we write primalValue() for \c Lp in \c lp_demo.cc?
kpeter@55:
kpeter@55: In this program, the same problem is built as in the above example,
kpeter@55: with the exception that the variable \c x1 is specified to be
kpeter@55: \c INTEGER valued. \c x2 is set to \c REAL, which is the default option.
kpeter@55:
kpeter@55: \code
kpeter@55: // Set the type of the columns
kpeter@55: mip.colType(x1, Mip::INTEGER);
kpeter@55: mip.colType(x2, Mip::REAL);
kpeter@30: \endcode
kpeter@30:
kpeter@55: Because of this integrality requirement, the results will be different
kpeter@55: from the LP solution.
kpeter@55:
kpeter@55: \code
kpeter@55: Objective function value: 67
kpeter@55: x1 = 8
kpeter@55: x2 = 9
kpeter@55: \endcode
kpeter@55:
kpeter@55: The documnetation of the MIP solver interface can be found in the
kpeter@55: reference manual at the class \ref MipSolver. The common parts of the
kpeter@55: LP and MIP interfaces are docmented in their common ancestor class
kpeter@55: \ref LpBase.
kpeter@55:
kpeter@55:
kpeter@55: [SEC]sec_lp_optimization[SEC] Solving Complex Optimization Problems
kpeter@55:
kpeter@55: The LP and MIP solvers are powerful tools for solving various complex
kpeter@55: optimization problems, as well.
kpeter@55: The following example solves a maximum flow problem with linear
kpeter@55: programming, see the whole program in \re lp_maxflow_demo.cc.
kpeter@55: Several other graph optimization problems can also be expressed as
kpeter@55: linear programs and the interface provided in LEMON facilitates solving
kpeter@55: them easily (though usually not so efficiently as by a direct
kpeter@55: combinatorial method, if one exists).
kpeter@55:
kpeter@55: \dontinclude lp_maxflow_demo.cc
kpeter@55: \skip DIGRAPH_TYPEDEFS
kpeter@55: \until solve()
kpeter@55:
kpeter@55: \note This problem can be solved much more efficiently using common
kpeter@55: combinatorial optimization methods, such as the \ref Preflow
kpeter@55: "preflow push-relabel algorithm".
kpeter@55:
kpeter@30: [TRAILER]
kpeter@30: */
kpeter@32: }