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
This commit is contained in:
parent
e9b432b1d9
commit
6db2596ca9
@ -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)
|
.. 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:
|
:return: One of the return codes:
|
||||||
|
|
||||||
|
@ -43,10 +43,6 @@
|
|||||||
#ifndef __OPENCV_OPTIM_HPP__
|
#ifndef __OPENCV_OPTIM_HPP__
|
||||||
#define __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
|
//uncomment the next line to print the debug info
|
||||||
//#define ALEX_DEBUG
|
//#define ALEX_DEBUG
|
||||||
|
|
||||||
|
@ -9,39 +9,39 @@ using std::vector;
|
|||||||
|
|
||||||
#ifdef ALEX_DEBUG
|
#ifdef ALEX_DEBUG
|
||||||
#define dprintf(x) printf x
|
#define dprintf(x) printf x
|
||||||
#define print_matrix(x) do{\
|
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);\
|
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++){\
|
for(int i=0;i<(x).rows;i++){
|
||||||
printf("\t[");\
|
printf("\t[");
|
||||||
for(int j=0;j<(x).cols;j++){\
|
for(int j=0;j<(x).cols;j++){
|
||||||
printf("%g, ",(x).at<double>(i,j));\
|
printf("%g, ",(x).at<double>(i,j));
|
||||||
}\
|
}
|
||||||
printf("]\n");\
|
printf("]\n");
|
||||||
}\
|
}
|
||||||
}while(0)
|
}
|
||||||
#define print_simplex_state(c,b,v,N,B) do{\
|
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("\tprint simplex state\n");
|
||||||
\
|
|
||||||
printf("v=%g\n",(v));\
|
printf("v=%g\n",(v));
|
||||||
\
|
|
||||||
printf("here c goes\n");\
|
printf("here c goes\n");
|
||||||
print_matrix((c));\
|
print_matrix((c));
|
||||||
\
|
|
||||||
printf("non-basic: ");\
|
printf("non-basic: ");
|
||||||
for (std::vector<int>::const_iterator it = (N).begin() ; it != (N).end(); ++it){\
|
for (std::vector<int>::const_iterator it = (N).begin() ; it != (N).end(); ++it){
|
||||||
printf("%d, ",*it);\
|
printf("%d, ",*it);
|
||||||
}\
|
}
|
||||||
printf("\n");\
|
printf("\n");
|
||||||
\
|
|
||||||
printf("here b goes\n");\
|
printf("here b goes\n");
|
||||||
print_matrix((b));\
|
print_matrix((b));
|
||||||
printf("basic: ");\
|
printf("basic: ");
|
||||||
\
|
|
||||||
for (std::vector<int>::const_iterator it = (B).begin() ; it != (B).end(); ++it){\
|
for (std::vector<int>::const_iterator it = (B).begin() ; it != (B).end(); ++it){
|
||||||
printf("%d, ",*it);\
|
printf("%d, ",*it);
|
||||||
}\
|
}
|
||||||
printf("\n");\
|
printf("\n");
|
||||||
}while(0)
|
}
|
||||||
#else
|
#else
|
||||||
#define dprintf(x) do {} while (0)
|
#define dprintf(x) do {} while (0)
|
||||||
#define print_matrix(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"));
|
dprintf(("call to solveLP\n"));
|
||||||
|
|
||||||
//sanity check (size, type, no. of channels)
|
//sanity check (size, type, no. of channels)
|
||||||
CV_Assert(Func.type()==CV_64FC1);
|
CV_Assert(Func.type()==CV_64FC1 || Func.type()==CV_32FC1);
|
||||||
CV_Assert(Constr.type()==CV_64FC1);
|
CV_Assert(Constr.type()==CV_64FC1 || Constr.type()==CV_32FC1);
|
||||||
CV_Assert(Func.rows==1);
|
CV_Assert((Func.rows==1 && (Constr.cols-Func.cols==1))||
|
||||||
CV_Assert(Constr.cols-Func.cols==1);
|
(Func.cols==1 && (Constr.cols-Func.rows==1)));
|
||||||
|
|
||||||
//copy arguments for we will shall modify them
|
//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);
|
bigB=Mat_<double>(Constr.rows,Constr.cols+1);
|
||||||
Func.copyTo(bigC.colRange(1,bigC.cols));
|
if(Func.rows==1){
|
||||||
Constr.copyTo(bigB.colRange(1,bigB.cols));
|
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;
|
double v=0;
|
||||||
vector<int> N,B;
|
vector<int> N,B;
|
||||||
|
|
||||||
@ -91,8 +111,7 @@ int solveLP(const Mat& Func, const Mat& Constr, Mat& z){
|
|||||||
}
|
}
|
||||||
|
|
||||||
//return the optimal solution
|
//return the optimal solution
|
||||||
const int z_size[]={1,c.cols};
|
z.create(c.cols,1,CV_64FC1);
|
||||||
z.create(2,z_size,CV_64FC1);
|
|
||||||
MatIterator_<double> it=z.begin<double>();
|
MatIterator_<double> it=z.begin<double>();
|
||||||
for(int i=1;i<=c.cols;i++,it++){
|
for(int i=1;i<=c.cols;i++,it++){
|
||||||
std::vector<int>::iterator pos=B.begin();
|
std::vector<int>::iterator pos=B.begin();
|
||||||
|
@ -43,6 +43,8 @@
|
|||||||
#ifndef __OPENCV_PRECOMP_H__
|
#ifndef __OPENCV_PRECOMP_H__
|
||||||
#define __OPENCV_PRECOMP_H__
|
#define __OPENCV_PRECOMP_H__
|
||||||
|
|
||||||
|
#include "opencv2/core.hpp"
|
||||||
|
#include "opencv2/core/mat.hpp"
|
||||||
#include "opencv2/optim.hpp"
|
#include "opencv2/optim.hpp"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
#include "test_precomp.hpp"
|
#include "test_precomp.hpp"
|
||||||
#include "opencv2/optim.hpp"
|
#include <iostream>
|
||||||
|
|
||||||
TEST(Optim_LpSolver, regression_basic){
|
TEST(Optim_LpSolver, regression_basic){
|
||||||
cv::Mat A,B,z,etalon_z;
|
cv::Mat A,B,z,etalon_z;
|
||||||
|
|
||||||
if(true){
|
if(true){
|
||||||
//cormen's example #1
|
//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);
|
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";
|
std::cout<<"here A goes\n"<<A<<"\n";
|
||||||
cv::optim::solveLP(A,B,z);
|
cv::optim::solveLP(A,B,z);
|
||||||
std::cout<<"here z goes\n"<<z<<"\n";
|
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);
|
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";
|
std::cout<<"here A goes\n"<<A<<"\n";
|
||||||
cv::optim::solveLP(A,B,z);
|
cv::optim::solveLP(A,B,z);
|
||||||
std::cout<<"here z goes\n"<<z<<"\n";
|
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);
|
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";
|
std::cout<<"here A goes\n"<<A<<"\n";
|
||||||
cv::optim::solveLP(A,B,z);
|
cv::optim::solveLP(A,B,z);
|
||||||
std::cout<<"here z goes\n"<<z<<"\n";
|
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);
|
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";
|
std::cout<<"here A goes\n"<<A<<"\n";
|
||||||
cv::optim::solveLP(A,B,z);
|
cv::optim::solveLP(A,B,z);
|
||||||
std::cout<<"here z goes\n"<<z<<"\n";
|
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);
|
ASSERT_EQ(cv::countNonZero(z!=etalon_z),0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -71,7 +71,7 @@ TEST(Optim_LpSolver, regression_multiple_solutions){
|
|||||||
|
|
||||||
if(true){
|
if(true){
|
||||||
//trivial example with multiple solutions
|
//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);
|
B=(cv::Mat_<double>(1,3)<<1,1,1);
|
||||||
std::cout<<"here A goes\n"<<A<<"\n";
|
std::cout<<"here A goes\n"<<A<<"\n";
|
||||||
int res=cv::optim::solveLP(A,B,z);
|
int res=cv::optim::solveLP(A,B,z);
|
||||||
@ -85,7 +85,7 @@ TEST(Optim_LpSolver, regression_multiple_solutions){
|
|||||||
if(false){
|
if(false){
|
||||||
//cormen's example from chapter about initialize_simplex
|
//cormen's example from chapter about initialize_simplex
|
||||||
//online solver told it has inf many solutions, but I'm not sure
|
//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);
|
B=(cv::Mat_<double>(2,3)<<2,-1,2,1,-5,-4);
|
||||||
std::cout<<"here A goes\n"<<A<<"\n";
|
std::cout<<"here A goes\n"<<A<<"\n";
|
||||||
int res=cv::optim::solveLP(A,B,z);
|
int res=cv::optim::solveLP(A,B,z);
|
||||||
@ -101,7 +101,7 @@ TEST(Optim_LpSolver, regression_cycling){
|
|||||||
|
|
||||||
if(true){
|
if(true){
|
||||||
//example with cycling from http://people.orie.cornell.edu/miketodd/or630/SimplexCyclingExample.pdf
|
//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);
|
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";
|
std::cout<<"here A goes\n"<<A<<"\n";
|
||||||
int res=cv::optim::solveLP(A,B,z);
|
int res=cv::optim::solveLP(A,B,z);
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
#ifndef __OPENCV_TEST_PRECOMP_HPP__
|
#ifndef __OPENCV_TEST_PRECOMP_HPP__
|
||||||
#define __OPENCV_TEST_PRECOMP_HPP__
|
#define __OPENCV_TEST_PRECOMP_HPP__
|
||||||
|
|
||||||
|
#include "opencv2/core.hpp"
|
||||||
|
#include "opencv2/core/mat.hpp"
|
||||||
#include "opencv2/ts.hpp"
|
#include "opencv2/ts.hpp"
|
||||||
#include "opencv2/optim.hpp"
|
#include "opencv2/optim.hpp"
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user