Powell-Brent (Praxis) non-linear unconstrained optimization.
Praxis is a general purpose routine for the minimization of a function in several variables. The algorithm used is a modification of conjugate gradient search method by Powell, with changes by Brent, who gave an algol-w program, which served as a basis for this function.
74 {
75 int verbose=0;
if(status!=NULL) verbose=status->
verbose;
76 if(verbose>0) printf("%s()\n", __func__);
77 if(nlo==NULL) {
80 }
84 }
85
86
87
88 unsigned int fixedNr=0;
89 for(
unsigned int i=0; i<nlo->
totalNr; i++)
if(nlo->
xdelta[i]<=0.0) fixedNr++;
93 }
94
95
96
98 if(verbose>1) printf("macheps := %g\n", macheps);
99 double m2=sqrt(macheps);
100 double m4=sqrt(m2);
101 if(verbose>1) {
102 printf("m2 := %e\n", m2);
103 printf("m4 := %e\n", m4);
104 }
105 double small=macheps*macheps;
106 double vsmall=small*small;
107 double large=1.0/small;
108 double vlarge=1.0/vsmall;
109 if(verbose>1) {
110 printf("small := %e\n", small);
111 printf("vsmall := %e\n", vsmall);
112 printf("large := %e\n", large);
113 printf("vlarge := %e\n", vlarge);
114 }
115
116
117 double h=0.0, scbd=1.0, t=0.0, t2;
118 {
119 unsigned int i;
120 double min=nan(""), max=nan("");
124 if(isnan(min) || nlo->
xdelta[i]<min) min=nlo->
xdelta[i];
125 if(isnan(max) || nlo->
xdelta[i]>max) max=nlo->
xdelta[i];
126 }
127 h/=(double)(nlo->
totalNr-fixedNr);
128 t/=(double)(nlo->
totalNr-fixedNr);
129 if(verbose>2) {printf("xdelta_min := %g\nxdelta_max := %g\n", min, max); fflush(stdout);}
130 scbd+=log10(max/min);
131 t2=small+fabs(t); t=t2;
132 if(h<100.0*t) h=100.0*t;
133 }
134 if(verbose>1) {
135 printf("step := %g\n", h);
136 printf("scbd := %g\n", scbd);
137 printf("t(2) := %g\n", t);
138 fflush(stdout);
139 }
140 if(isnan(scbd)) {
143 }
144
145
146
147
148
149 int illc=0;
150
151
152 if(verbose>2) {printf("initializing\n"); fflush(stdout);}
153 unsigned int i, j, dim=nlo->
totalNr;
154 double ldfac; if(illc) ldfac=0.1; else ldfac=0.01;
155 unsigned int nl=0, kt=0;
156 unsigned int nf=0;
157 double dmin=small;
158 double ldt=h;
159 double d[dim], y[dim], z[dim];
160
161 double **v=malloc(dim*sizeof(double *)); if(v==NULL) {
164 }
165 for(i=0; i<dim; i++) {
166 v[i]=malloc(dim*sizeof(double));
167 if(v[i]==NULL) {
170 }
171 }
172
173 if(verbose>2) {printf("copying parameters\n"); fflush(stdout);}
174 double p[dim];
175 for(i=0; i<dim; i++) p[i]=nlo->
xfull[i];
176
177 for(i=0; i<dim; i++) {
178 d[i]=y[i]=z[i]=0.0;
179 for(j=0; j<dim; j++) v[i][j]=(i==j ? 1.0 : 0.0);
180 }
181 double qd0=0.0, q0[dim], q1[dim];
182 for(i=0; i<dim; i++) q1[i]=q0[i]=nlo->
xfull[i];
183
184
185
186 if(verbose>2) {printf("evaluating initial guess\n"); fflush(stdout);}
187 double fx, qf1;
189 nf++;
190 if(!isfinite(fx)) {
191 for(i=0; i<dim; i++) free(v[i]);
192 free(v);
195 }
196 if(verbose>1) {printf("initial_objfunc := %g\n", fx); fflush(stdout);}
197
198
199
200 double sf, s, dn, qd1=0.0;
201 int done=0, nLoop=0, ret=0;
202 while(!done) {
203 nLoop++;
204 if(verbose>2) {
205 printf("\n-------------------------------\nloop %d, with %d fcalls\n", nLoop, nf);
206 fflush(stdout);
207 }
208 sf=d[0]; s=d[0]=0.0;
209
210
211 ret=praxisMin(0, 2, &d[0], &s, fx, 0, &fx, v, dim, h, t,
212 macheps, m2, m4, small, dmin, ldt, &nl,
213 &nf, qd0, qd1, q0, q1,
215 if(ret) {
216 if(verbose>0) printf("Error %d in praxisMin()\n", ret);
217 for(i=0; i<dim; i++) free(v[i]);
218 free(v);
221 }
222
223 if((sf<=(0.9*d[0])) || ((0.9*sf)>=d[0])) for(i=1; i<dim; i++) d[i]=0.0;
224
225
226 unsigned int k, kl=0, k2;
227 double sl, df, f1, lds;
228 for(k=1; k<dim; k++) {
229 if(verbose>5) printf("direction %d\n", k);
230 for(i=0; i<dim; i++) y[i]=p[i];
231 sf=fx; if(kt>0) illc=1;
232 do {
233 kl=k; df=0.0;
234
235 if(illc) {
236 for(i=0; i<dim; i++) {
237 z[i]=(0.1*ldt+t2*pow(10.0,(
double)kt)) * (
drand()-0.5);
238 s=z[i]; for(j=0; j<dim; j++) p[j]+=s*v[j][i];
239 }
240
242 if(!isfinite(fx)) {
245 }
246 nf++;
247 }
248
249 for(k2=k; k2<dim; k2++) {
250 if(verbose>6) printf(" non-conjugate direction %d\n", k2);
251 sl=fx; s=0.0;
252 ret=praxisMin(k2, 2, &d[k2], &s, fx, 0, &fx, v, dim, h, t,
253 macheps, m2, m4, small, dmin, ldt, &nl,
254 &nf, qd0, qd1, q0, q1,
256 if(ret) {
257 if(verbose>0) printf("Error %d in praxisMin()\n", ret);
258 for(i=0; i<dim; i++) free(v[i]);
259 free(v);
262 }
263 if(illc) s=d[k2]*(s+z[k2])*(s+z[k2]); else s=sl-fx;
264 if(df<s) {df=s; kl=k2;}
265 }
266 if(illc) break;
267 if(df>=fabs(100.0*macheps*fx)) break;
268 illc=1;
269 } while(1);
270
271
272 for(k2=0; k2<k; k2++) {
273
274 if(verbose>6) printf(" conjugate direction %d\n", k2);
275 s=0.0;
276 ret=praxisMin(k2, 2, &d[k2], &s, fx, 0, &fx, v, dim, h, t,
277 macheps, m2, m4, small, dmin, ldt, &nl,
278 &nf, qd0, qd1, q0, q1,
280 if(ret) {
281 if(verbose>0) printf("Error %d in praxisMin()\n", ret);
282 for(i=0; i<dim; i++) free(v[i]);
283 free(v);
286 }
287 }
288 f1=fx; fx=sf; lds=0.0;
289 for(i=0; i<dim; i++) {
290 sl=p[i]; p[i]=y[i]; y[i]=sl-y[i]; sl=y[i]; lds+=sl*sl;
291 }
292 lds=sqrt(lds);
293 if(lds>small) {
294 for(i=kl-1; i>=k; i--) {
295 for(j=0; j<dim; j++) v[j][i+1]=v[j][i];
296 d[i+1]=d[i];
297 }
298 d[k]=0.0; for(i=0; i<dim; i++) v[i][k]=y[i]/lds;
299 ret=praxisMin(k, 4, &d[k], &lds, f1, 1, &fx, v, dim, h, t,
300 macheps, m2, m4, small, dmin, ldt, &nl,
301 &nf, qd0, qd1, q0, q1,
303 if(ret) {
304 if(verbose>0) printf("Error %d in praxisMin()\n", ret);
305 for(i=0; i<dim; i++) free(v[i]);
306 free(v);
309 }
310 if(lds<=0.0) {lds=-lds; for(i=0; i<dim; i++) v[i][k]=-v[i][k];}
311 }
312 ldt*=ldfac; if(ldt<lds) ldt=lds;
313 for(i=0, t2=0.0; i<dim; i++) t2+=p[i]*p[i];
314 t2=sqrt(t2); t2*=m2; t2+=t;
315
316 if(verbose>1) printf(" objfunc := %g\n", fx);
317
318
319 if(ldt>(0.5*t2)) kt=0; else kt++;
320 if(verbose>3 && kt>0) printf(" kt := %d\n", kt);
321 if(kt>ktm) {done=1; break;}
322
323 }
324 if(done) break;
325
326
327
328
329
330 if(dim<2) {
331 if(nf>1000) done=1;
332 continue;
333 }
334
335
336
337 {
338 double qa, qb, qc, qs, ql;
339 qs=fx; fx=qf1; qf1=qs;
340 for(i=0, qd1=0.0; i<dim; i++) {
341 qs=p[i]; ql=q1[i]; p[i]=ql; q1[i]=qs;
342 qd1+=(qs-ql)*(qs-ql);
343 }
344 qd1=sqrt(qd1); ql=qd1; qs=0.0;
345 if(qd0>0.0 && qd1>0.0 && nl>=3*dim*dim) {
346 ret=praxisMin(-1, 2, &qs, &ql, qf1, 1, &fx, v, dim, h, t,
347 macheps, m2, m4, small, dmin, ldt, &nl,
348 &nf, qd0, qd1, q0, q1,
350 if(ret) {
351 if(verbose>0) printf("Error %d in praxisMin()\n", ret);
352 for(i=0; i<dim; i++) free(v[i]);
353 free(v);
356 }
357 qa = ql*(ql-qd1)/(qd0*(qd0+qd1));
358 qb = (ql+qd0)*(qd1-ql)/(qd0*qd1);
359 qc = ql*(ql+qd0)/(qd1*(qd0+qd1));
360 } else {
361 fx=qf1; qa=qb=0.0; qc=1.0;
362 }
363 if(!isfinite(qa)) qa=0.0;
364 if(!isfinite(qb)) qb=0.0;
365 if(!isfinite(qc)) qc=1.0;
366 qd0=qd1;
367 for(i=0; i<dim; i++) {
368 qs=q0[i]; q0[i]=p[i];
369 p[i]=qa*s + qb*p[i] + qc*q1[i];
370 }
371 }
372 dn=0.0;
373 for(i=0; i<dim; i++) {d[i]=1.0/sqrt(d[i]); if(dn<d[i]) dn=d[i];}
374 for(j=0; j<dim; j++) {
375 s=d[j]/dn;
376 if(isfinite(s)) for(i=0; i<dim; i++) v[i][j]*=s;
377 }
378
379 if(scbd>1.0) {
380 s=vlarge;
381 for(i=0; i<dim; i++) {
382 sl=0.0;
383 for(j=0; j<dim; j++) sl+=v[i][j]*v[i][j];
384 z[i]=sqrt(sl); if(!isfinite(z[i]) || z[i]<m4) z[i]=m4;
385 if(s>z[i]) s=z[i];
386 }
387 for(i=0; i<dim; i++) {
388 sl=s/z[i]; z[i]=1.0/sl;
389 if(z[i]>scbd) {sl=1.0/scbd; z[i]=scbd;}
390 for(j=0; j<dim; j++) v[i][j]*=sl;
391 }
392 }
393
394
395 for(i=1; i<dim; i++) for(j=0; j<i; j++) {
396 s=v[i][j]; v[i][j]=v[j][i]; v[j][i]=s;
397 }
398
399
400
401 ret=praxisMinfit((int)dim, macheps, vsmall, v, d);
402 if(ret) {
403 if(verbose>0) printf("Error %d in praxisMinfit()\n", ret);
404 for(i=0; i<dim; i++) free(v[i]);
405 free(v);
408 }
409 if(scbd>1.0) {
410 for(i=0; i<dim; i++) {s=z[i]; for(j=0; j<dim; j++) v[i][j]*=s;}
411 for(i=0; i<dim; i++) {
412 s=0.0; for(j=0; j<dim; j++) s+=v[j][i]*v[j][i];
413 s=sqrt(s); d[i]*=s; s=1.0/s; for(j=0; j<dim; j++) v[j][i]*=s;
414 }
415 }
416 for(i=0; i<dim; i++) {
417 if((dn*d[i]) > large) d[i]=vsmall;
418 else if((dn*d[i]) < small) d[i]=vlarge;
419 else d[i]=pow(dn*d[i], -2.0);
420 }
421
422 praxisSort(d, v, dim);
423 dmin=d[dim-1]; if(dmin<small) dmin=small;
424 illc=(m2*d[0]) > dmin;
425
426
427
428
429 if(nf>1000) done=1;
430 }
431 if(verbose>1) printf("func_evals := %d\n", nf);
432
433
434
435 for(i=0; i<dim; i++) free(v[i]);
436 free(v);
437
438
439 for(i=0; i<dim; i++) nlo->
xfull[i]=p[i];
440
441
442
443 if(sf>0.0) sf=0.0;
444 if(kt>0) kt=0;
445 if(nl>0) nl=0;
446 if(ldfac>0.0) ldfac=0.0;
447 if(ktm>0) ktm=0;
448
449
451}
void statusSet(TPCSTATUS *s, const char *func, const char *srcfile, int srcline, tpcerror error)
double(* _fun)(int, double *, void *)
int verbose
Verbose level, used by statusPrint() etc.
@ TPCERROR_INVALID_VALUE
Invalid value.
@ TPCERROR_INVALID_PARNR
Invalid number of parameters.
@ TPCERROR_FAIL
General error.
@ TPCERROR_OUT_OF_MEMORY
Cannot allocate memory.
@ TPCERROR_NO_DATA
File contains no data.