ok, so probably the failure in downhill simplex has been finally solved
This commit is contained in:
@@ -40,11 +40,13 @@
|
|||||||
//M*/
|
//M*/
|
||||||
#include "precomp.hpp"
|
#include "precomp.hpp"
|
||||||
|
|
||||||
/*#define dprintf(x) printf x
|
#if 0
|
||||||
#define print_matrix(x) print(x)*/
|
#define dprintf(x) printf x
|
||||||
|
#define print_matrix(x) print(x)
|
||||||
|
#else
|
||||||
#define dprintf(x)
|
#define dprintf(x)
|
||||||
#define print_matrix(x)
|
#define print_matrix(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
@@ -61,7 +63,7 @@ file C:\builds\master_PackSlave-w in32-vc12-shared\opencv\modules\core\include\o
|
|||||||
|
|
||||||
DownhillSolverImpl::innerDownhillSimplex something looks broken here:
|
DownhillSolverImpl::innerDownhillSimplex something looks broken here:
|
||||||
Mat_<double> coord_sum(1,ndim,0.0),buf(1,ndim,0.0),y(1,ndim,0.0);
|
Mat_<double> coord_sum(1,ndim,0.0),buf(1,ndim,0.0),y(1,ndim,0.0);
|
||||||
nfunk = 0;
|
fcount = 0;
|
||||||
for(i=0;i<ndim+1;++i)
|
for(i=0;i<ndim+1;++i)
|
||||||
{
|
{
|
||||||
y(i) = f->calc(p[i]);
|
y(i) = f->calc(p[i]);
|
||||||
@@ -153,7 +155,6 @@ public:
|
|||||||
// set dimensionality and make a deep copy of step
|
// set dimensionality and make a deep copy of step
|
||||||
Mat m = step.getMat();
|
Mat m = step.getMat();
|
||||||
dprintf(("m.cols=%d\nm.rows=%d\n", m.cols, m.rows));
|
dprintf(("m.cols=%d\nm.rows=%d\n", m.cols, m.rows));
|
||||||
CV_Assert( std::min(m.cols, m.rows) == 1 && m.type() == CV_64FC1 );
|
|
||||||
if( m.rows == 1 )
|
if( m.rows == 1 )
|
||||||
m.copyTo(_step);
|
m.copyTo(_step);
|
||||||
else
|
else
|
||||||
@@ -178,17 +179,19 @@ public:
|
|||||||
{
|
{
|
||||||
dprintf(("hi from minimize\n"));
|
dprintf(("hi from minimize\n"));
|
||||||
CV_Assert( !_Function.empty() );
|
CV_Assert( !_Function.empty() );
|
||||||
|
CV_Assert( std::min(_step.cols, _step.rows) == 1 &&
|
||||||
|
std::max(_step.cols, _step.rows) >= 2 &&
|
||||||
|
_step.type() == CV_64FC1 );
|
||||||
dprintf(("termcrit:\n\ttype: %d\n\tmaxCount: %d\n\tEPS: %g\n",_termcrit.type,_termcrit.maxCount,_termcrit.epsilon));
|
dprintf(("termcrit:\n\ttype: %d\n\tmaxCount: %d\n\tEPS: %g\n",_termcrit.type,_termcrit.maxCount,_termcrit.epsilon));
|
||||||
dprintf(("step\n"));
|
dprintf(("step\n"));
|
||||||
print_matrix(_step);
|
print_matrix(_step);
|
||||||
|
|
||||||
Mat x = x_.getMat();
|
Mat x = x_.getMat(), simplex;
|
||||||
Mat_<double> simplex;
|
|
||||||
|
|
||||||
createInitialSimplex(x, simplex, _step);
|
createInitialSimplex(x, simplex, _step);
|
||||||
int count = 0;
|
int count = 0;
|
||||||
double res = innerDownhillSimplex(simplex,_termcrit.epsilon, _termcrit.epsilon,
|
double res = innerDownhillSimplex(simplex,_termcrit.epsilon, _termcrit.epsilon,
|
||||||
count, _Function, _termcrit.maxCount);
|
count, _termcrit.maxCount);
|
||||||
dprintf(("%d iterations done\n",count));
|
dprintf(("%d iterations done\n",count));
|
||||||
|
|
||||||
if( !x.empty() )
|
if( !x.empty() )
|
||||||
@@ -208,7 +211,7 @@ protected:
|
|||||||
TermCriteria _termcrit;
|
TermCriteria _termcrit;
|
||||||
Mat _step;
|
Mat _step;
|
||||||
|
|
||||||
inline void updateCoordSum(const Mat_<double>& p, Mat_<double>& coord_sum)
|
inline void updateCoordSum(const Mat& p, Mat& coord_sum)
|
||||||
{
|
{
|
||||||
int i, j, m = p.rows, n = p.cols;
|
int i, j, m = p.rows, n = p.cols;
|
||||||
double* coord_sum_ = coord_sum.ptr<double>();
|
double* coord_sum_ = coord_sum.ptr<double>();
|
||||||
@@ -223,9 +226,13 @@ protected:
|
|||||||
for( j = 0; j < n; j++ )
|
for( j = 0; j < n; j++ )
|
||||||
coord_sum_[j] += p_i[j];
|
coord_sum_[j] += p_i[j];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dprintf(("\nupdated coord sum:\n"));
|
||||||
|
print_matrix(coord_sum);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void createInitialSimplex( const Mat& x0, Mat_<double>& simplex, Mat& step )
|
inline void createInitialSimplex( const Mat& x0, Mat& simplex, Mat& step )
|
||||||
{
|
{
|
||||||
int i, j, ndim = step.cols;
|
int i, j, ndim = step.cols;
|
||||||
Mat x = x0;
|
Mat x = x0;
|
||||||
@@ -234,7 +241,7 @@ protected:
|
|||||||
CV_Assert( (x.cols == 1 && x.rows == ndim) || (x.cols == ndim && x.rows == 1) );
|
CV_Assert( (x.cols == 1 && x.rows == ndim) || (x.cols == ndim && x.rows == 1) );
|
||||||
CV_Assert( x.type() == CV_32F || x.type() == CV_64F );
|
CV_Assert( x.type() == CV_32F || x.type() == CV_64F );
|
||||||
|
|
||||||
simplex.create(ndim + 1, ndim);
|
simplex.create(ndim + 1, ndim, CV_64F);
|
||||||
Mat simplex_0m(x.rows, x.cols, CV_64F, simplex.ptr<double>());
|
Mat simplex_0m(x.rows, x.cols, CV_64F, simplex.ptr<double>());
|
||||||
|
|
||||||
x.convertTo(simplex_0m, CV_64F);
|
x.convertTo(simplex_0m, CV_64F);
|
||||||
@@ -250,7 +257,7 @@ protected:
|
|||||||
for( j = 0; j < ndim; j++ )
|
for( j = 0; j < ndim; j++ )
|
||||||
simplex_0[j] -= 0.5*step_[j];
|
simplex_0[j] -= 0.5*step_[j];
|
||||||
|
|
||||||
dprintf(("this is simplex\n"));
|
dprintf(("\nthis is simplex\n"));
|
||||||
print_matrix(simplex);
|
print_matrix(simplex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -259,27 +266,24 @@ protected:
|
|||||||
|
|
||||||
The matrix p[ndim+1][1..ndim] represents ndim+1 vertices that
|
The matrix p[ndim+1][1..ndim] represents ndim+1 vertices that
|
||||||
form a simplex - each row is an ndim vector.
|
form a simplex - each row is an ndim vector.
|
||||||
On output, nfunk gives the number of function evaluations taken.
|
On output, fcount gives the number of function evaluations taken.
|
||||||
*/
|
*/
|
||||||
double innerDownhillSimplex( Mat_<double>& p,double MinRange,double MinError, int& nfunk,
|
double innerDownhillSimplex( Mat& p, double MinRange, double MinError, int& fcount, int nmax )
|
||||||
const Ptr<MinProblemSolver::Function>& f, int nmax )
|
|
||||||
{
|
{
|
||||||
int i, j, ndim = p.cols;
|
int i, j, ndim = p.cols;
|
||||||
Mat_<double> coord_sum(1, ndim), buf(1, ndim), y(1, ndim+1);
|
Mat coord_sum(1, ndim, CV_64F), buf(1, ndim, CV_64F), y(1, ndim+1, CV_64F);
|
||||||
double* y_ = y.ptr<double>();
|
double* y_ = y.ptr<double>();
|
||||||
|
|
||||||
nfunk = 0;
|
fcount = ndim+1;
|
||||||
|
|
||||||
for( i = 0; i <= ndim; i++ )
|
for( i = 0; i <= ndim; i++ )
|
||||||
y_[i] = f->calc(p[i]);
|
y_[i] = calc_f(p.ptr<double>(i));
|
||||||
|
|
||||||
nfunk = ndim+1;
|
|
||||||
updateCoordSum(p, coord_sum);
|
updateCoordSum(p, coord_sum);
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
/* find highest (worst), next-to-worst, and lowest
|
// find highest (worst), next-to-worst, and lowest
|
||||||
(best) points by going through all of them. */
|
// (best) points by going through all of them.
|
||||||
int ilo = 0, ihi, inhi;
|
int ilo = 0, ihi, inhi;
|
||||||
if( y_[0] > y_[1] )
|
if( y_[0] > y_[1] )
|
||||||
{
|
{
|
||||||
@@ -302,101 +306,145 @@ protected:
|
|||||||
else if (yval > y_[inhi] && i != ihi)
|
else if (yval > y_[inhi] && i != ihi)
|
||||||
inhi = i;
|
inhi = i;
|
||||||
}
|
}
|
||||||
CV_Assert( ilo != ihi && ilo != inhi && ihi != inhi );
|
CV_Assert( ihi != inhi );
|
||||||
dprintf(("this is y on iteration %d:\n",nfunk));
|
if( ilo == inhi || ilo == ihi )
|
||||||
|
{
|
||||||
|
for( i = 0; i <= ndim; i++ )
|
||||||
|
{
|
||||||
|
double yval = y_[i];
|
||||||
|
if( yval == y_[ilo] && i != ihi && i != inhi )
|
||||||
|
{
|
||||||
|
ilo = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dprintf(("\nthis is y on iteration %d:\n",fcount));
|
||||||
print_matrix(y);
|
print_matrix(y);
|
||||||
|
|
||||||
/* check stop criterion */
|
// check stop criterion
|
||||||
double error = fabs(y_[ihi] - y_[ilo]);
|
double error = fabs(y_[ihi] - y_[ilo]);
|
||||||
double range = 0;
|
double range = 0;
|
||||||
for( j = 0; j < ndim; j++ )
|
for( j = 0; j < ndim; j++ )
|
||||||
{
|
{
|
||||||
double minval, maxval;
|
double minval, maxval;
|
||||||
minval = maxval = p(0, j);
|
minval = maxval = p.at<double>(0, j);
|
||||||
for( i = 1; i <= ndim; i++ )
|
for( i = 1; i <= ndim; i++ )
|
||||||
{
|
{
|
||||||
double pval = p(i, j);
|
double pval = p.at<double>(i, j);
|
||||||
minval = std::min(minval, pval);
|
minval = std::min(minval, pval);
|
||||||
maxval = std::max(maxval, pval);
|
maxval = std::max(maxval, pval);
|
||||||
}
|
}
|
||||||
range = std::max(range, fabs(maxval - minval));
|
range = std::max(range, fabs(maxval - minval));
|
||||||
}
|
}
|
||||||
|
|
||||||
if( range <= MinRange || error <= MinError || nfunk >= nmax )
|
if( range <= MinRange || error <= MinError || fcount >= nmax )
|
||||||
{
|
{
|
||||||
/* Put best point and value in first slot. */
|
// Put best point and value in first slot.
|
||||||
std::swap(y(0), y(ilo));
|
std::swap(y_[0], y_[ilo]);
|
||||||
for( j = 0; j < ndim; j++ )
|
for( j = 0; j < ndim; j++ )
|
||||||
{
|
{
|
||||||
std::swap(p(0, j), p(ilo, j));
|
std::swap(p.at<double>(0, j), p.at<double>(ilo, j));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
nfunk += 2;
|
|
||||||
|
|
||||||
double ylo = y_[ilo], ynhi = y_[inhi];
|
double y_lo = y_[ilo], y_nhi = y_[inhi], y_hi = y_[ihi];
|
||||||
/* Begin a new iteration. First, reflect the worst point about the centroid of others */
|
// Begin a new iteration. First, reflect the worst point about the centroid of others
|
||||||
double ytry = tryNewPoint(p, y, coord_sum, f, ihi, -1.0, buf);
|
double alpha = -1.0;
|
||||||
if( ytry <= ylo )
|
double y_alpha = tryNewPoint(p, coord_sum, ihi, alpha, buf, fcount);
|
||||||
|
|
||||||
|
dprintf(("\ny_lo=%g, y_nhi=%g, y_hi=%g, y_alpha=%g, p_alpha:\n", y_lo, y_nhi, y_hi, y_alpha));
|
||||||
|
print_matrix(buf);
|
||||||
|
|
||||||
|
if( y_alpha < y_nhi )
|
||||||
{
|
{
|
||||||
/* If that's better than the best point, go twice as far in that direction */
|
if( y_alpha < y_lo )
|
||||||
ytry = tryNewPoint(p, y, coord_sum, f, ihi, 2.0, buf);
|
|
||||||
}
|
|
||||||
else if( ytry >= ynhi )
|
|
||||||
{
|
|
||||||
/* The new point is worse than the second-highest,
|
|
||||||
do not go so far in that direction */
|
|
||||||
double ysave = y(ihi);
|
|
||||||
ytry = tryNewPoint(p, y, coord_sum, f, ihi, 0.5, buf);
|
|
||||||
if (ytry >= ysave)
|
|
||||||
{
|
{
|
||||||
/* Can't seem to improve things. Contract the simplex to good point
|
// If that's better than the best point, go twice as far in that direction
|
||||||
in hope to find a simplex landscape. */
|
double beta = -2.0;
|
||||||
|
double y_beta = tryNewPoint(p, coord_sum, ihi, beta, buf, fcount);
|
||||||
|
dprintf(("\ny_beta=%g, p_beta:\n", y_beta));
|
||||||
|
print_matrix(buf);
|
||||||
|
if( y_beta < y_alpha )
|
||||||
|
{
|
||||||
|
alpha = beta;
|
||||||
|
y_alpha = y_beta;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
replacePoint(p, coord_sum, y, ihi, alpha, y_alpha);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// The new point is worse than the second-highest,
|
||||||
|
// do not go so far in that direction
|
||||||
|
double gamma = 0.5;
|
||||||
|
double y_gamma = tryNewPoint(p, coord_sum, ihi, gamma, buf, fcount);
|
||||||
|
dprintf(("\ny_gamma=%g, p_gamma:\n", y_gamma));
|
||||||
|
print_matrix(buf);
|
||||||
|
if( y_gamma < y_hi )
|
||||||
|
replacePoint(p, coord_sum, y, ihi, gamma, y_gamma);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Can't seem to improve things.
|
||||||
|
// Contract the simplex to good point
|
||||||
|
// in hope to find a simplex landscape.
|
||||||
for( i = 0; i <= ndim; i++ )
|
for( i = 0; i <= ndim; i++ )
|
||||||
{
|
{
|
||||||
if (i != ilo)
|
if (i != ilo)
|
||||||
{
|
{
|
||||||
for( j = 0; j < ndim; j++ )
|
for( j = 0; j < ndim; j++ )
|
||||||
p(i,j) = 0.5*(p(i,j) + p(ilo,j));
|
p.at<double>(i, j) = 0.5*(p.at<double>(i, j) + p.at<double>(ilo, j));
|
||||||
y(i)=f->calc(p.ptr<double>(i));
|
y_[i] = calc_f(p.ptr<double>(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
nfunk += ndim;
|
fcount += ndim;
|
||||||
updateCoordSum(p, coord_sum);
|
updateCoordSum(p, coord_sum);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else --(nfunk); /* correct nfunk */
|
dprintf(("\nthis is simplex on iteration %d\n",fcount));
|
||||||
dprintf(("this is simplex on iteration %d\n",nfunk));
|
|
||||||
print_matrix(p);
|
print_matrix(p);
|
||||||
} /* go to next iteration. */
|
}
|
||||||
return y(0);
|
return y_[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
inline double tryNewPoint(Mat_<double>& p, Mat_<double>& y, Mat_<double>& coord_sum,
|
inline double calc_f(const double* ptr)
|
||||||
const Ptr<MinProblemSolver::Function>& f, int ihi,
|
{
|
||||||
double fac, Mat_<double>& ptry)
|
double res = _Function->calc(ptr);
|
||||||
|
CV_Assert( !cvIsNaN(res) && !cvIsInf(res) );
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
double tryNewPoint( Mat& p, Mat& coord_sum, int ihi, double alpha_, Mat& ptry, int& fcount )
|
||||||
{
|
{
|
||||||
int j, ndim = p.cols;
|
int j, ndim = p.cols;
|
||||||
|
|
||||||
double fac1 = (1.0 - fac)/ndim;
|
double alpha = (1.0 - alpha_)/ndim;
|
||||||
double fac2 = fac1 - fac;
|
double beta = alpha - alpha_;
|
||||||
double* p_ihi = p.ptr<double>(ihi);
|
double* p_ihi = p.ptr<double>(ihi);
|
||||||
double* ptry_ = ptry.ptr<double>();
|
double* ptry_ = ptry.ptr<double>();
|
||||||
double* coord_sum_ = coord_sum.ptr<double>();
|
double* coord_sum_ = coord_sum.ptr<double>();
|
||||||
|
|
||||||
for( j = 0; j < ndim; j++ )
|
for( j = 0; j < ndim; j++ )
|
||||||
ptry_[j] = coord_sum_[j]*fac1 - p_ihi[j]*fac2;
|
ptry_[j] = coord_sum_[j]*alpha - p_ihi[j]*beta;
|
||||||
|
|
||||||
double ytry = f->calc(ptry_);
|
fcount++;
|
||||||
if (ytry < y(ihi))
|
return calc_f(ptry_);
|
||||||
{
|
}
|
||||||
y(ihi) = ytry;
|
|
||||||
for( j = 0; j < ndim; j++ )
|
|
||||||
p_ihi[j] = ptry_[j];
|
|
||||||
updateCoordSum(p, coord_sum);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ytry;
|
void replacePoint( Mat& p, Mat& coord_sum, Mat& y, int ihi, double alpha_, double ytry )
|
||||||
|
{
|
||||||
|
int j, ndim = p.cols;
|
||||||
|
|
||||||
|
double alpha = (1.0 - alpha_)/ndim;
|
||||||
|
double beta = alpha - alpha_;
|
||||||
|
double* p_ihi = p.ptr<double>(ihi);
|
||||||
|
double* coord_sum_ = coord_sum.ptr<double>();
|
||||||
|
|
||||||
|
for( j = 0; j < ndim; j++ )
|
||||||
|
p_ihi[j] = coord_sum_[j]*alpha - p_ihi[j]*beta;
|
||||||
|
y.at<double>(ihi) = ytry;
|
||||||
|
updateCoordSum(p, coord_sum);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -58,7 +58,7 @@ static void mytest(cv::Ptr<cv::ConjGradSolver> solver,cv::Ptr<cv::MinProblemSolv
|
|||||||
std::cout<<"--------------------------\n";
|
std::cout<<"--------------------------\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
class SphereF:public cv::MinProblemSolver::Function{
|
class SphereF_CG:public cv::MinProblemSolver::Function{
|
||||||
public:
|
public:
|
||||||
double calc(const double* x)const{
|
double calc(const double* x)const{
|
||||||
return x[0]*x[0]+x[1]*x[1]+x[2]*x[2]+x[3]*x[3];
|
return x[0]*x[0]+x[1]*x[1]+x[2]*x[2]+x[3]*x[3];
|
||||||
@@ -69,7 +69,7 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
class RosenbrockF:public cv::MinProblemSolver::Function{
|
class RosenbrockF_CG:public cv::MinProblemSolver::Function{
|
||||||
double calc(const double* x)const{
|
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]);
|
return 100*(x[1]-x[0]*x[0])*(x[1]-x[0]*x[0])+(1-x[0])*(1-x[0]);
|
||||||
}
|
}
|
||||||
@@ -83,7 +83,7 @@ TEST(DISABLED_Core_ConjGradSolver, regression_basic){
|
|||||||
cv::Ptr<cv::ConjGradSolver> solver=cv::ConjGradSolver::create();
|
cv::Ptr<cv::ConjGradSolver> solver=cv::ConjGradSolver::create();
|
||||||
#if 1
|
#if 1
|
||||||
{
|
{
|
||||||
cv::Ptr<cv::MinProblemSolver::Function> ptr_F(new SphereF());
|
cv::Ptr<cv::MinProblemSolver::Function> ptr_F(new SphereF_CG());
|
||||||
cv::Mat x=(cv::Mat_<double>(4,1)<<50.0,10.0,1.0,-10.0),
|
cv::Mat x=(cv::Mat_<double>(4,1)<<50.0,10.0,1.0,-10.0),
|
||||||
etalon_x=(cv::Mat_<double>(1,4)<<0.0,0.0,0.0,0.0);
|
etalon_x=(cv::Mat_<double>(1,4)<<0.0,0.0,0.0,0.0);
|
||||||
double etalon_res=0.0;
|
double etalon_res=0.0;
|
||||||
@@ -92,7 +92,7 @@ TEST(DISABLED_Core_ConjGradSolver, regression_basic){
|
|||||||
#endif
|
#endif
|
||||||
#if 1
|
#if 1
|
||||||
{
|
{
|
||||||
cv::Ptr<cv::MinProblemSolver::Function> ptr_F(new RosenbrockF());
|
cv::Ptr<cv::MinProblemSolver::Function> ptr_F(new RosenbrockF_CG());
|
||||||
cv::Mat x=(cv::Mat_<double>(2,1)<<0.0,0.0),
|
cv::Mat x=(cv::Mat_<double>(2,1)<<0.0,0.0),
|
||||||
etalon_x=(cv::Mat_<double>(2,1)<<1.0,1.0);
|
etalon_x=(cv::Mat_<double>(2,1)<<1.0,1.0);
|
||||||
double etalon_res=0.0;
|
double etalon_res=0.0;
|
||||||
|
Reference in New Issue
Block a user