Commit a9565011 authored by Alex Leontiev's avatar Alex Leontiev

Cleaning the code of simplex method

In particular, the following things are done:
*) Consistent tabulation of 4 spaces is ensured
*) New function dprintf() is introduced, so now printing of the debug
information can be turned on/off via the ALEX_DEBUG macro
*) Removed solveLP_aux namespace
*) All auxiliary functions are declared as static
*) The return codes of solveLP() are encapsulated in enum.
parent a4a5e98c
Linear Programming
==================
.. highlight:: cpp
optim::solveLP
--------------------
Solve given (non-integer) linear programming problem using the Simplex Algorithm (Simplex Method).
What we mean here by "linear programming problem" (or LP problem, for short) can be
formulated as:
.. math::
\mbox{Maximize } c\cdot x\\
\mbox{Subject to:}\\
Ax\leq b\\
x\geq 0
Where :math:`c` is fixed *1*-by-*n* row-vector, :math:`A` is fixed *m*-by-*n* matrix, :math:`b` is fixed *m*-by-*1* column vector and
:math:`x` is an arbitrary *n*-by-*1* column vector, which satisfies the constraints.
Simplex algorithm is one of many algorithms that are designed to handle this sort of problems efficiently. Although it is not optimal in theoretical
sense (there exist algorithms that can solve any problem written as above in polynomial type, while simplex method degenerates to exponential time
for some special cases), it is well-studied, easy to implement and is shown to work well for real-life purposes.
The particular implementation is taken almost verbatim from **Introduction to Algorithms, third edition**
by T. H. Cormen, C. E. Leiserson, R. L. Rivest and Clifford Stein. In particular, the Bland's rule
(`http://en.wikipedia.org/wiki/Bland%27s\_rule <http://en.wikipedia.org/wiki/Bland%27s_rule>`_) is used to prevent cycling.
.. ocv:function:: int optim::solveLP(const Mat& Func, const Mat& Constr, Mat& z)
:param Func: This row-vector corresponds to :math:`c` in the LP problem formulation (see above).
:param Constr: *m*-by-*n\+1* matrix, whose rightmost column corresponds to :math:`b` in formulation above and the remaining to :math:`A`.
:param z: The solution will be returned here as a row-vector - it corresponds to (transposed) :math:`c` in the formulation above.
:return: One of the return codes:
::
//!the return codes for solveLP() function
enum
{
SOLVELP_UNBOUNDED = -2, //problem is unbounded (target function can achieve arbitrary high values)
SOLVELP_UNFEASIBLE = -1, //problem is unfeasible (there are no points that satisfy all the constraints imposed)
SOLVELP_SINGLE = 0, //there is only one maximum for target function
SOLVELP_MULTI = 1 //there are multiple maxima for target function - the arbitrary one is returned
};
**************************************
optim. Generic numerical optimization
**************************************
.. highlight:: cpp
.. toctree::
:maxdepth: 2
linear_programming
......@@ -47,67 +47,77 @@
#include "opencv2/core.hpp"
#include "opencv2/core/mat.hpp"
/*! \namespace cv
Namespace where all the C++ OpenCV functionality resides
*/
//uncomment the next line to print the debug info
//#define ALEX_DEBUG
namespace cv{namespace optim
{
//! generic class for optimization algorithms */
class CV_EXPORTS Solver : public Algorithm /* Algorithm is the base OpenCV class */
{
public:
class CV_EXPORTS Function
{
public:
public:
class CV_EXPORTS Function
{
public:
virtual ~Function(){}
virtual double calc(InputArray args) const = 0;
};
class CV_EXPORTS Constraints
{
public:
};
class CV_EXPORTS Constraints
{
public:
virtual ~Constraints(){}
};
};
//! could be reused for all the generic algorithms like downhill simplex. Return value is the maximum value of a function*/
virtual double solve(const Function& F,const Constraints& C, OutputArray result) const = 0;
//! could be reused for all the generic algorithms like downhill simplex. Return value is the maximum value of a function*/
virtual double solve(const Function& F,const Constraints& C, OutputArray result) const = 0;
/*virtual void setTermCriteria(const TermCriteria& criteria) = 0;
virtual TermCriteria getTermCriteria() = 0;*/
/*virtual void setTermCriteria(const TermCriteria& criteria) = 0;
virtual TermCriteria getTermCriteria() = 0;*/
// more detailed API to be defined later ...
// more detailed API to be defined later ...
};
class CV_EXPORTS LPSolver : public Solver
{
public:
class CV_EXPORTS LPFunction:public Solver::Function
{
Mat z;
public:
//! Note, that this class is supposed to be immutable, so it's ok to make only a shallow copy of z_in.*/
LPFunction(Mat z_in):z(z_in){}
~LPFunction(){};
const Mat& getz()const{return z;}
double calc(InputArray args)const;
};
class CV_EXPORTS LPFunction:public Solver::Function
{
Mat z;
public:
//! Note, that this class is supposed to be immutable, so it's ok to make only a shallow copy of z_in.*/
LPFunction(Mat z_in):z(z_in){}
~LPFunction(){};
const Mat& getz()const{return z;}
double calc(InputArray args)const;
};
//!This class represents constraints for linear problem. There are two matrix stored: m-by-n matrix A and n-by-1 column-vector b.
//!What this represents is the set of constraints Ax\leq b and x\geq 0. It can be shown that any set of linear constraints can be converted
//!this form and **we shall create various constructors for this class that will perform these conversions**.
class CV_EXPORTS LPConstraints:public Solver::Constraints
{
Mat A,b;
public:
~LPConstraints(){};
//! Note, that this class is supposed to be immutable, so it's ok to make only a shallow copy of A_in and b_in.*/
LPConstraints(Mat A_in, Mat b_in):A(A_in),b(b_in){}
const Mat& getA()const{return A;}
const Mat& getb()const{return b;}
};
//!This class represents constraints for linear problem. There are two matrix stored: m-by-n matrix A and n-by-1 column-vector b.
//!What this represents is the set of constraints Ax\leq b and x\geq 0. It can be shown that any set of linear constraints can be converted
//!this form and **we shall create various constructors for this class that will perform these conversions**.
class CV_EXPORTS LPConstraints:public Solver::Constraints
{
Mat A,b;
public:
~LPConstraints(){};
//! Note, that this class is supposed to be immutable, so it's ok to make only a shallow copy of A_in and b_in.*/
LPConstraints(Mat A_in, Mat b_in):A(A_in),b(b_in){}
const Mat& getA()const{return A;}
const Mat& getb()const{return b;}
};
LPSolver(){}
double solve(const Function& F,const Constraints& C, OutputArray result)const;
LPSolver(){}
double solve(const Function& F,const Constraints& C, OutputArray result)const;
};
//!the return codes for solveLP() function
enum
{
SOLVELP_UNBOUNDED = -2, //problem is unbounded (target function can achieve arbitrary high values)
SOLVELP_UNFEASIBLE = -1, //problem is unfeasible (there are no points that satisfy all the constraints imposed)
SOLVELP_SINGLE = 0, //there is only one maximum for target function
SOLVELP_MULTI = 1 //there are multiple maxima for target function - the arbitrary one is returned
};
CV_EXPORTS_W int solveLP(const Mat& Func, const Mat& Constr, Mat& z);
}}// cv
......
This diff is collapsed.
#include "test_precomp.hpp"
#include "opencv2/optim.hpp"
TEST(Optim_LpSolver, regression_basic)
{
TEST(Optim_LpSolver, regression_basic){
cv::Mat A,B,z,etalon_z;
if(true){
......@@ -120,9 +119,10 @@ TEST(Optim_LpSolver, regression_cycling){
//
// ??how_check_multiple_solutions & pass_test - DONE
// Blands_rule - DONE
// (&1tests on cycling)
// (assert, assign) - DONE
//
// make_more_clear (assert, assign)
// (&1tests on cycling)
// make_more_clear
// wrap in OOP
//
// non-trivial tests
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment