17double (*_powellFunc)(int,
double*,
void*);
19int _powell_func_calls;
22void _powell_linmin(
double *p,
double *xi,
int n,
double *fret,
int *itnr);
23double _powell_brent(
double ax,
double bx,
double cx,
double tol,
double *xmin,
25double _powell_f1dim(
double x,
int dim);
26void _powell_mnbrak(
double *ax,
double *bx,
double *cx,
double *fa,
double *fb,
29double _powell_sqr(
double x) {
return (x*x);}
30void _powell_shft(
double *a,
double *b,
double *c,
double *d) {*a=*b; *b=*c; *c=*d;}
31double _powell_fmax(
double a,
double b) {
return((a>b) ? a:b);}
57 double (*_fun)(
int,
double*,
void*),
67 double del, fp, fptt, t;
72 if(verbose>0) printf(
"in powell(,,%d,%g,%d,,)\n", parNr, ftol, *iterNr);
74 printf(
"Initial parameter guesses and deltas:\n");
75 for(i=0; i<parNr; i++) printf(
" %g %g\n", p[i], delta[i]);
78 if(p==NULL)
return(11);
79 if(delta==NULL)
return(12);
80 if(parNr<1)
return(21);
81 if(ftol<=0.0)
return(22);
82 if(ftol>=1.0)
return(23);
83 if((*iterNr)<1)
return(24);
87 _powellFuncData=fundata;
92 *fret=(*_powellFunc)(parNr, p, _powellFuncData);
93 if(verbose>10) printf(
"initial point fret=%g\n", *fret);
94 if(!isfinite(*fret)) {
95 if(verbose>0) printf(
"in powell(): objf failed at initial point.\n");
96 *fret=nan(
"");
return(2);
99 for(j=0; j<parNr; j++) origp[j]=pt[j]=p[j];
101 for(i=0; i<parNr; i++)
if(fabs(delta[i])<1.0e-20) fixed[i]=1;
else fixed[i]=0;
104 for(i=0; i<parNr; i++)
105 for(j=0; j<parNr; j++)
106 if(i==j) xi[i][j]=delta[i];
else xi[i][j]=0.0;
109 for(*iterNr=1; ; (*iterNr)++) {
110 if(verbose>2) printf(
" iteration %d\n", *iterNr);
111 fp=*fret; ibig=0; del=0.0;
114 for(i=0; i<parNr; i++) {
115 if(fixed[i])
continue;
116 for(j=0; j<parNr; j++)
if(fixed[j]) xit[j]=0.0;
else xit[j]=xi[j][i];
120 _powell_linmin(p, xit, parNr, fret, &pbIterNr);
121 if(verbose>3) printf(
"iterNr in _powell_linmin() with p%d: %d\n",
123 if(fabs(fptt-(*fret))>del) {del=fabs(fptt-(*fret)); ibig=i;}
125 if(verbose>20) printf(
"fret=%g fp=%g\n", *fret, fp);
129 if(2.0*fabs(fp-(*fret)) <= ftol*(fabs(fp)+fabs(*fret)))
break;
131 if(2.0*fabs(fp-(*fret)) <= ftol*(fabs(fp)+fabs(*fret))) {
132 if(ftol_reached>0 || (*iterNr)>=iterMax)
break;
else ftol_reached++;
133 }
else ftol_reached=0;
135 if((*iterNr)>=iterMax) {
136 if(verbose>0) printf(
"max iterations nr exceeded in powell().\n");
140 for(j=0; j<parNr; j++) {
141 ptt[j]=2.0*p[j]-pt[j]; xit[j]=p[j]-pt[j];
144 fptt=(*_powellFunc)(parNr, ptt, _powellFuncData); _powell_func_calls++;
146 t=2.0*(fp-2.0*(*fret)+fptt)*_powell_sqr(fp-(*fret)-del)-del*_powell_sqr(fp-fptt);
149 _powell_linmin(p, xit, parNr, fret, &pbIterNr);
150 if(verbose>3) printf(
"iterNr in _powell_linmin(): %d\n", pbIterNr);
151 for(j=0; j<parNr; j++) {
152 xi[j][ibig]=xi[j][parNr-1]; xi[j][parNr-1]=xit[j];}
157 printf(
"iterNr := %d\n", *iterNr);
158 printf(
"nr of function calls := %d\n", _powell_func_calls);
161 if(isnan(*fret) || !isfinite(*fret)) {
162 if(verbose>10) printf(
"powell() fails and returns the initial point.\n");
164 if(isnan(*fret)) printf(
" fret := NaN\n");
165 if(isfinite(*fret)) printf(
" fret := overflow/underflow\n");
168 for(j=0; j<parNr; j++) p[j]=origp[j];
170 *fret=(*_powellFunc)(parNr, p, _powellFuncData);
174 *fret=(*_powellFunc)(parNr, p, _powellFuncData);
175 if((*iterNr)>=iterMax)
return(1);
176 if(verbose>0) printf(
"out of powell() in good order.\n");
183void _powell_linmin(
double *p,
double *xi,
int n,
double *fret,
int *itnr)
186 double xx, xmin, fx, fb, fa, bx, ax;
189 for(i=0; i<n; i++) {_powell_pcom[i]=p[i]; _powell_xicom[i]=xi[i];}
191 _powell_mnbrak(&ax, &xx, &bx, &fa, &fx, &fb, n);
192 *fret=_powell_brent(ax, xx, bx, 2.0e-4, &xmin, itnr, n);
193 for(i=0; i<n; i++) {xi[i]*=xmin; p[i]+=xi[i];}
197 double ax,
double bx,
double cx,
double tol,
double *xmin,
int *itnr,
int dim
200 const double CGOLD = 0.3819660;
201 const double ZEPS = 1.0E-10;
203 double a, b, d=0.0, etemp, fu, fv, fw, fx, p, q, r;
204 double e=0.0, tol1, tol2, u, v, w, x, xm;
206 a=(ax<cx ? ax:cx); b=(ax>cx ? ax:cx); x=w=v=bx;
207 fw=fv=fx=_powell_f1dim(x, dim);
209 for(*itnr=0; *itnr<iterMax; (*itnr)++) {
210 xm=0.5*(a+b); tol2=2.0*(tol1=tol*fabs(x)+ZEPS);
211 if(fabs(x-xm)<=(tol2-0.5*(b-a))) {*xmin=x;
return(fx);}
213 r=(x-w)*(fx-fv); q=(x-v)*(fx-fw); p=(x-v)*q-(x-w)*r;
214 q=2.0*(q-r);
if(q>0.0) p=-p; q=fabs(q);
216 if(fabs(p)>=fabs(0.5*q*etemp) || p<=q*(a-x) || p>=q*(b-x))
217 d=CGOLD*(e=(x>=xm ? a-x:b-x));
220 if(u-a<tol2 || b-u<tol2) d=copysign(tol1, xm-x);
222 }
else {d=CGOLD*(e=(x>=xm ? a-x:b-x));}
223 u=(fabs(d)>=tol1 ? x+d : x+copysign(tol1, d));
224 fu=_powell_f1dim(u, dim);
226 if(u>=x) a=x;
else b=x;
227 _powell_shft(&v, &w, &x, &u); _powell_shft(&fv, &fw, &fx, &fu);
229 if(u<x) a=u;
else b=u;
230 if(fu<=fw || w==x) {v=w; w=u; fv=fw; fw=fu;}
231 else if(fu<=fv || v==x || v==w) {v=u; fv=fu;}
238double _powell_f1dim(
double x,
int dim)
243 for(i=0; i<_powell_ncom; i++) xt[i]=_powell_pcom[i]+x*_powell_xicom[i];
244 f=(*_powellFunc)(dim, xt, _powellFuncData); _powell_func_calls++;
249 double *ax,
double *bx,
double *cx,
double *fa,
double *fb,
252 const double GOLD = 1.618034;
253 const double GLIMIT = 100.0;
254 const double TINY = 1.0e-20;
255 double ulim, u, r, q, fu, dum=0.0;
257 *fa=_powell_f1dim(*ax, dim); *fb=_powell_f1dim(*bx, dim);
258 if(*fb>*fa) {_powell_shft(&dum, ax, bx, &dum); _powell_shft(&dum, fb, fa, &dum);}
259 *cx=(*bx)+GOLD*(*bx-*ax); *fc=_powell_f1dim(*cx, dim);
261 r=(*bx-*ax)*(*fb-*fc); q=(*bx-*cx)*(*fb-*fa);
262 u=(*bx)-((*bx-*cx)*q-(*bx-*ax)*r)/(2.0*copysign(_powell_fmax(fabs(q-r),TINY),q-r));
263 ulim=(*bx)+GLIMIT*(*cx-*bx);
264 if(((*bx)-u)*(u-(*cx)) > 0.0) {
265 fu=_powell_f1dim(u, dim);
266 if(fu < *fc) {*ax=(*bx); *bx=u; *fa=(*fb); *fb=fu;
return;}
267 else if(fu > *fb) {*cx=u; *fc=fu;
return;}
268 u=(*cx)+GOLD*(*cx-*bx);
269 fu=_powell_f1dim(u, dim);
270 }
else if((*cx-u)*(u-ulim) > 0.0) {
271 fu=_powell_f1dim(u, dim);
273 q=*cx+GOLD*(*cx-*bx); r=_powell_f1dim(u, dim);
274 _powell_shft(bx, cx, &u, &q); _powell_shft(fb, fc, &fu, &r);
276 }
else if((u-ulim)*(ulim-*cx) >= 0.0) {
277 u=ulim; fu=_powell_f1dim(u, dim);
279 u=(*cx)+GOLD*(*cx-*bx);
280 fu=_powell_f1dim(u, dim);
282 _powell_shft(ax, bx, cx, &u); _powell_shft(fa, fb, fc, &fu);
Header file for libtpcmodel.
int powell(double *p, double *delta, int parNr, double ftol, int *iterNr, double *fret, double(*_fun)(int, double *, void *), void *fundata, int verbose)