Commit 6db2596c authored by Alex Leontiev's avatar Alex Leontiev

Convenience fixes

Attempting to fix issues pointed out by Vadim Pisarevsky during the pull
request review. In particular, the following things are done:
*) The mechanism of debug info printing is changed and made more
procedure-style than the previous macro-style
*) z in solveLP() is now returned as a column-vector
*) Func parameter of solveLP() is now allowed to be column-vector, in
which case it is understood to be the transpose of what we need
*) Func and Constr now can contain floats, not only doubles (in the
former case the conversion is done via convertTo())
*)different constructor to allocate space for z in solveLP() is used,
making the size of z more explicit (this is just a notation change, not
functional, both constructors are achieving the same goal)
*) (big) mat.hpp and iostream headers are moved to precomp-headers from
optim.hpp
parent e9b432b1
......@@ -28,11 +28,11 @@ by T. H. Cormen, C. E. Leiserson, R. L. Rivest and Clifford Stein. In particular
.. 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 Func: This row-vector corresponds to :math:`c` in the LP problem formulation (see above). It should contain 32- or 64-bit floating point numbers. As a convenience, column-vector may be also submitted, in the latter case it is understood to correspond to :math:`c^T`.
:param Constr: *m*-by-*n\+1* matrix, whose rightmost column corresponds to :math:`b` in formulation above and the remaining to :math:`A`.
:param Constr: *m*-by-*n\+1* matrix, whose rightmost column corresponds to :math:`b` in formulation above and the remaining to :math:`A`. It should containt 32- or 64-bit floating point numbers.
:param z: The solution will be returned here as a row-vector - it corresponds to (transposed) :math:`c` in the formulation above.
:param z: The solution will be returned here as a column-vector - it corresponds to :math:`c` in the formulation above. It will contain 64-bit floating point numbers.
:return: One of the return codes:
......
......@@ -43,10 +43,6 @@
#ifndef __OPENCV_OPTIM_HPP__
#define __OPENCV_OPTIM_HPP__
#include <iostream>
#include "opencv2/core.hpp"
#include "opencv2/core/mat.hpp"
//uncomment the next line to print the debug info
//#define ALEX_DEBUG
......
......@@ -9,39 +9,39 @@ using std::vector;
#ifdef ALEX_DEBUG
#define dprintf(x) printf x
#define print_matrix(x) do{\
printf("\ttype:%d vs %d,\tsize: %d-on-%d\n",(x).type(),CV_64FC1,(x).rows,(x).cols);\
for(int i=0;i<(x).rows;i++){\
printf("\t[");\
for(int j=0;j<(x).cols;j++){\
printf("%g, ",(x).at<double>(i,j));\
}\
printf("]\n");\
}\
}while(0)
#define print_simplex_state(c,b,v,N,B) do{\
printf("\tprint simplex state\n");\
\
printf("v=%g\n",(v));\
\
printf("here c goes\n");\
print_matrix((c));\
\
printf("non-basic: ");\
for (std::vector<int>::const_iterator it = (N).begin() ; it != (N).end(); ++it){\
printf("%d, ",*it);\
}\
printf("\n");\
\
printf("here b goes\n");\
print_matrix((b));\
printf("basic: ");\
\
for (std::vector<int>::const_iterator it = (B).begin() ; it != (B).end(); ++it){\
printf("%d, ",*it);\
}\
printf("\n");\
}while(0)
static void print_matrix(const Mat& x){
printf("\ttype:%d vs %d,\tsize: %d-on-%d\n",(x).type(),CV_64FC1,(x).rows,(x).cols);
for(int i=0;i<(x).rows;i++){
printf("\t[");
for(int j=0;j<(x).cols;j++){
printf("%g, ",(x).at<double>(i,j));
}
printf("]\n");
}
}
static void print_simplex_state(const Mat& c,const Mat& b,double v,const std::vector<int> N,const std::vector<int> B){
printf("\tprint simplex state\n");
printf("v=%g\n",(v));
printf("here c goes\n");
print_matrix((c));
printf("non-basic: ");
for (std::vector<int>::const_iterator it = (N).begin() ; it != (N).end(); ++it){
printf("%d, ",*it);
}
printf("\n");
printf("here b goes\n");
print_matrix((b));
printf("basic: ");
for (std::vector<int>::const_iterator it = (B).begin() ; it != (B).end(); ++it){
printf("%d, ",*it);
}
printf("\n");
}
#else
#define dprintf(x) do {} while (0)
#define print_matrix(x) do {} while (0)
......@@ -66,16 +66,36 @@ int solveLP(const Mat& Func, const Mat& Constr, Mat& z){
dprintf(("call to solveLP\n"));
//sanity check (size, type, no. of channels)
CV_Assert(Func.type()==CV_64FC1);
CV_Assert(Constr.type()==CV_64FC1);
CV_Assert(Func.rows==1);
CV_Assert(Constr.cols-Func.cols==1);
CV_Assert(Func.type()==CV_64FC1 || Func.type()==CV_32FC1);
CV_Assert(Constr.type()==CV_64FC1 || Constr.type()==CV_32FC1);
CV_Assert((Func.rows==1 && (Constr.cols-Func.cols==1))||
(Func.cols==1 && (Constr.cols-Func.rows==1)));
//copy arguments for we will shall modify them
Mat_<double> bigC=Mat_<double>(1,Func.cols+1),
Mat_<double> bigC=Mat_<double>(1,(Func.rows==1?Func.cols:Func.rows)+1),
bigB=Mat_<double>(Constr.rows,Constr.cols+1);
Func.copyTo(bigC.colRange(1,bigC.cols));
Constr.copyTo(bigB.colRange(1,bigB.cols));
if(Func.rows==1){
Func.convertTo(bigC.colRange(1,bigC.cols),CV_64FC1);
}else{
dprintf(("hi from other branch\n"));
Mat_<double> slice=bigC.colRange(1,bigC.cols);
MatIterator_<double> slice_iterator=slice.begin();
switch(Func.type()){
case CV_64FC1:
for(MatConstIterator_<double> it=Func.begin<double>();it!=Func.end<double>();it++,slice_iterator++){
* slice_iterator= *it;
}
break;
case CV_32FC1:
for(MatConstIterator_<float> it=Func.begin<float>();it!=Func.end<double>();it++,slice_iterator++){
* slice_iterator= *it;
}
break;
}
print_matrix(Func);
print_matrix(bigC);
}
Constr.convertTo(bigB.colRange(1,bigB.cols),CV_64FC1);
double v=0;
vector<int> N,B;
......@@ -91,8 +111,7 @@ int solveLP(const Mat& Func, const Mat& Constr, Mat& z){
}
//return the optimal solution
const int z_size[]={1,c.cols};
z.create(2,z_size,CV_64FC1);
z.create(c.cols,1,CV_64FC1);
MatIterator_<double> it=z.begin<double>();
for(int i=1;i<=c.cols;i++,it++){
std::vector<int>::iterator pos=B.begin();
......
......@@ -43,6 +43,8 @@
#ifndef __OPENCV_PRECOMP_H__
#define __OPENCV_PRECOMP_H__
#include "opencv2/core.hpp"
#include "opencv2/core/mat.hpp"
#include "opencv2/optim.hpp"
#endif
#include "test_precomp.hpp"
#include "opencv2/optim.hpp"
#include <iostream>
TEST(Optim_LpSolver, regression_basic){
cv::Mat A,B,z,etalon_z;
if(true){
//cormen's example #1
A=(cv::Mat_<double>(1,3)<<3,1,2);
A=(cv::Mat_<double>(3,1)<<3,1,2);
B=(cv::Mat_<double>(3,4)<<1,1,3,30,2,2,5,24,4,1,2,36);
std::cout<<"here A goes\n"<<A<<"\n";
cv::optim::solveLP(A,B,z);
std::cout<<"here z goes\n"<<z<<"\n";
etalon_z=(cv::Mat_<double>(1,3)<<8,4,0);
etalon_z=(cv::Mat_<double>(3,1)<<8,4,0);
ASSERT_EQ(cv::countNonZero(z!=etalon_z),0);
}
......@@ -22,7 +22,7 @@ TEST(Optim_LpSolver, regression_basic){
std::cout<<"here A goes\n"<<A<<"\n";
cv::optim::solveLP(A,B,z);
std::cout<<"here z goes\n"<<z<<"\n";
etalon_z=(cv::Mat_<double>(1,2)<<20,0);
etalon_z=(cv::Mat_<double>(2,1)<<20,0);
ASSERT_EQ(cv::countNonZero(z!=etalon_z),0);
}
......@@ -33,7 +33,7 @@ TEST(Optim_LpSolver, regression_basic){
std::cout<<"here A goes\n"<<A<<"\n";
cv::optim::solveLP(A,B,z);
std::cout<<"here z goes\n"<<z<<"\n";
etalon_z=(cv::Mat_<double>(1,2)<<1,0);
etalon_z=(cv::Mat_<double>(2,1)<<1,0);
ASSERT_EQ(cv::countNonZero(z!=etalon_z),0);
}
}
......@@ -48,7 +48,7 @@ TEST(Optim_LpSolver, regression_init_unfeasible){
std::cout<<"here A goes\n"<<A<<"\n";
cv::optim::solveLP(A,B,z);
std::cout<<"here z goes\n"<<z<<"\n";
etalon_z=(cv::Mat_<double>(1,3)<<1250,1000,0);
etalon_z=(cv::Mat_<double>(3,1)<<1250,1000,0);
ASSERT_EQ(cv::countNonZero(z!=etalon_z),0);
}
}
......@@ -71,7 +71,7 @@ TEST(Optim_LpSolver, regression_multiple_solutions){
if(true){
//trivial example with multiple solutions
A=(cv::Mat_<double>(1,2)<<1,1);
A=(cv::Mat_<double>(2,1)<<1,1);
B=(cv::Mat_<double>(1,3)<<1,1,1);
std::cout<<"here A goes\n"<<A<<"\n";
int res=cv::optim::solveLP(A,B,z);
......@@ -85,7 +85,7 @@ TEST(Optim_LpSolver, regression_multiple_solutions){
if(false){
//cormen's example from chapter about initialize_simplex
//online solver told it has inf many solutions, but I'm not sure
A=(cv::Mat_<double>(1,2)<<2,-1);
A=(cv::Mat_<double>(2,1)<<2,-1);
B=(cv::Mat_<double>(2,3)<<2,-1,2,1,-5,-4);
std::cout<<"here A goes\n"<<A<<"\n";
int res=cv::optim::solveLP(A,B,z);
......@@ -101,7 +101,7 @@ TEST(Optim_LpSolver, regression_cycling){
if(true){
//example with cycling from http://people.orie.cornell.edu/miketodd/or630/SimplexCyclingExample.pdf
A=(cv::Mat_<double>(1,4)<<10,-57,-9,-24);
A=(cv::Mat_<double>(4,1)<<10,-57,-9,-24);
B=(cv::Mat_<double>(3,5)<<0.5,-5.5,-2.5,9,0,0.5,-1.5,-0.5,1,0,1,0,0,0,1);
std::cout<<"here A goes\n"<<A<<"\n";
int res=cv::optim::solveLP(A,B,z);
......
......@@ -9,6 +9,8 @@
#ifndef __OPENCV_TEST_PRECOMP_HPP__
#define __OPENCV_TEST_PRECOMP_HPP__
#include "opencv2/core.hpp"
#include "opencv2/core/mat.hpp"
#include "opencv2/ts.hpp"
#include "opencv2/optim.hpp"
......
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