Some interface was refined (most notably, the method for returning Hessian was removed and the method for getting gradient was added as optional to base Solver::Function class) and basic code for setters/getters was added. Now is the time for the real work on an algorithm.pull/1521/head
parent
eb1333d0a8
commit
581d454536
5 changed files with 157 additions and 12 deletions
@ -0,0 +1,11 @@ |
|||||||
|
Conjugate Gradient |
||||||
|
======================= |
||||||
|
|
||||||
|
.. highlight:: cpp |
||||||
|
|
||||||
|
optim::ConjGradSolver |
||||||
|
--------------------------------- |
||||||
|
|
||||||
|
.. ocv:class:: optim::ConjGradSolver |
||||||
|
|
||||||
|
This class is used |
@ -0,0 +1,77 @@ |
|||||||
|
#include "precomp.hpp" |
||||||
|
#include "debug.hpp" |
||||||
|
|
||||||
|
namespace cv{namespace optim{ |
||||||
|
|
||||||
|
class ConjGradSolverImpl : public ConjGradSolver |
||||||
|
{ |
||||||
|
public: |
||||||
|
Ptr<Function> getFunction() const; |
||||||
|
void setFunction(const Ptr<Function>& f); |
||||||
|
TermCriteria getTermCriteria() const; |
||||||
|
ConjGradSolverImpl(); |
||||||
|
void setTermCriteria(const TermCriteria& termcrit); |
||||||
|
double minimize(InputOutputArray x); |
||||||
|
protected: |
||||||
|
Ptr<Solver::Function> _Function; |
||||||
|
TermCriteria _termcrit; |
||||||
|
Mat_<double> d,r,buf_x,r_old; |
||||||
|
private: |
||||||
|
}; |
||||||
|
|
||||||
|
double ConjGradSolverImpl::minimize(InputOutputArray x){ |
||||||
|
CV_Assert(_Function.empty()==false); |
||||||
|
dprintf(("termcrit:\n\ttype: %d\n\tmaxCount: %d\n\tEPS: %g\n",_termcrit.type,_termcrit.maxCount,_termcrit.epsilon)); |
||||||
|
|
||||||
|
Mat x_mat=x.getMat(); |
||||||
|
CV_Assert(MIN(x_mat.rows,x_mat.cols)==1); |
||||||
|
int ndim=MAX(x_mat.rows,x_mat.cols); |
||||||
|
CV_Assert(x_mat.type()==CV_64FC1); |
||||||
|
|
||||||
|
d.create(1,ndim); |
||||||
|
r.create(1,ndim); |
||||||
|
r_old.create(1,ndim); |
||||||
|
|
||||||
|
Mat_<double> proxy_x; |
||||||
|
if(x_mat.rows>1){ |
||||||
|
buf_x.create(1,ndim); |
||||||
|
Mat_<double> proxy(ndim,1,(double*)buf_x.data); |
||||||
|
x_mat.copyTo(proxy); |
||||||
|
proxy_x=buf_x; |
||||||
|
}else{ |
||||||
|
proxy_x=x_mat; |
||||||
|
} |
||||||
|
|
||||||
|
//here everything goes. check that everything is setted properly
|
||||||
|
|
||||||
|
if(x_mat.rows>1){ |
||||||
|
Mat(ndim, 1, CV_64F, (double*)proxy_x.data).copyTo(x); |
||||||
|
} |
||||||
|
return 0.0; |
||||||
|
} |
||||||
|
ConjGradSolverImpl::ConjGradSolverImpl(){ |
||||||
|
_Function=Ptr<Function>(); |
||||||
|
} |
||||||
|
Ptr<Solver::Function> ConjGradSolverImpl::getFunction()const{ |
||||||
|
return _Function; |
||||||
|
} |
||||||
|
void ConjGradSolverImpl::setFunction(const Ptr<Function>& f){ |
||||||
|
_Function=f; |
||||||
|
} |
||||||
|
TermCriteria ConjGradSolverImpl::getTermCriteria()const{ |
||||||
|
return _termcrit; |
||||||
|
} |
||||||
|
void ConjGradSolverImpl::setTermCriteria(const TermCriteria& termcrit){ |
||||||
|
CV_Assert((termcrit.type==(TermCriteria::MAX_ITER+TermCriteria::EPS) && termcrit.epsilon>0 && termcrit.maxCount>0) || |
||||||
|
((termcrit.type==TermCriteria::MAX_ITER) && termcrit.maxCount>0)); |
||||||
|
_termcrit=termcrit; |
||||||
|
} |
||||||
|
// both minRange & minError are specified by termcrit.epsilon; In addition, user may specify the number of iterations that the algorithm does.
|
||||||
|
Ptr<ConjGradSolver> createConjGradSolver(const Ptr<Solver::Function>& f, TermCriteria termcrit){ |
||||||
|
ConjGradSolver *CG=new ConjGradSolverImpl(); |
||||||
|
CG->setFunction(f); |
||||||
|
CG->setTermCriteria(termcrit); |
||||||
|
return Ptr<ConjGradSolver>(CG); |
||||||
|
} |
||||||
|
}} |
||||||
|
|
@ -0,0 +1,61 @@ |
|||||||
|
#include "test_precomp.hpp" |
||||||
|
#include <cstdlib> |
||||||
|
|
||||||
|
static void mytest(cv::Ptr<cv::optim::ConjGradSolver> solver,cv::Ptr<cv::optim::Solver::Function> ptr_F,cv::Mat& x, |
||||||
|
cv::Mat& etalon_x,double etalon_res){ |
||||||
|
solver->setFunction(ptr_F); |
||||||
|
//int ndim=MAX(step.cols,step.rows);
|
||||||
|
double res=solver->minimize(x); |
||||||
|
std::cout<<"res:\n\t"<<res<<std::endl; |
||||||
|
std::cout<<"x:\n\t"<<x<<std::endl; |
||||||
|
std::cout<<"etalon_res:\n\t"<<etalon_res<<std::endl; |
||||||
|
std::cout<<"etalon_x:\n\t"<<etalon_x<<std::endl; |
||||||
|
double tol=solver->getTermCriteria().epsilon; |
||||||
|
ASSERT_TRUE(std::abs(res-etalon_res)<tol); |
||||||
|
/*for(cv::Mat_<double>::iterator it1=x.begin<double>(),it2=etalon_x.begin<double>();it1!=x.end<double>();it1++,it2++){
|
||||||
|
ASSERT_TRUE(std::abs((*it1)-(*it2))<tol); |
||||||
|
}*/ |
||||||
|
std::cout<<"--------------------------\n"; |
||||||
|
} |
||||||
|
|
||||||
|
class SphereF:public cv::optim::Solver::Function{ |
||||||
|
public: |
||||||
|
double calc(const double* x)const{ |
||||||
|
return x[0]*x[0]+x[1]*x[1]+x[2]*x[2]+x[3]*x[3]; |
||||||
|
} |
||||||
|
void getGradient(const double* x,double* grad){ |
||||||
|
for(int i=0;i<4;i++,grad++,x++){ |
||||||
|
grad[0]=2*x[0]; |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
//TODO: test transp/usual x
|
||||||
|
/*class RosenbrockF:public cv::optim::Solver::Function{
|
||||||
|
double calc(const double* x)const{ |
||||||
|
return 100*(x[1]-x[0]*x[0])*(x[1]-x[0]*x[0])+(1-x[0])*(1-x[0]); |
||||||
|
} |
||||||
|
};*/ |
||||||
|
|
||||||
|
TEST(Optim_ConjGrad, regression_basic){ |
||||||
|
cv::Ptr<cv::optim::ConjGradSolver> solver=cv::optim::createConjGradSolver(); |
||||||
|
#if 1 |
||||||
|
{ |
||||||
|
cv::Ptr<cv::optim::Solver::Function> ptr_F(new SphereF()); |
||||||
|
cv::Mat x=(cv::Mat_<double>(1,2)<<1.0,1.0), |
||||||
|
etalon_x=(cv::Mat_<double>(1,2)<<0.0,0.0); |
||||||
|
double etalon_res=0.0; |
||||||
|
return; |
||||||
|
mytest(solver,ptr_F,x,etalon_x,etalon_res); |
||||||
|
} |
||||||
|
#endif |
||||||
|
#if 0 |
||||||
|
{ |
||||||
|
cv::Ptr<cv::optim::Solver::Function> ptr_F(new RosenbrockF()); |
||||||
|
cv::Mat x=(cv::Mat_<double>(2,1)<<0.0,0.0), |
||||||
|
step=(cv::Mat_<double>(2,1)<<0.5,+0.5), |
||||||
|
etalon_x=(cv::Mat_<double>(2,1)<<1.0,1.0); |
||||||
|
double etalon_res=0.0; |
||||||
|
mytest(solver,ptr_F,x,step,etalon_x,etalon_res); |
||||||
|
} |
||||||
|
#endif |
||||||
|
} |
Loading…
Reference in new issue