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