Topographical minimization algorithm, that searches the global minimum of a function using clusterization. Calls a local minimization algorithm. Based on an algorithm by Aimo Torn and Sami Viitanen.
66 {
67 int i, j, k, l, IDmin, itNr, samplNr, topoNr, badNr, nevals=0, ret;
68 double *delta, temp, min, *tempp, deltaf, tol;
70 int fixed_n, fitted_n;
71
72
73 if(verbose>0) {printf("in tgo()\n"); fflush(stdout);}
75 if(verbose>0) printf("local optimization routine: bobyqa\n");
76 } else {
77 if(verbose>0) printf("local optimization routine: powell\n");
78 }
79
80
81 if(lowlim==NULL || uplim==NULL || objf==NULL || dim<=0) return(1);
82 if(fmin==NULL || gmin==NULL) return(1);
83
84
85 for(i=0, fixed_n=0; i<dim; i++) if(uplim[i]<=lowlim[i]) fixed_n++;
86 fitted_n=dim-fixed_n;
87 if(verbose>1) printf("%d parameter(s) are fixed.\n", fixed_n);
88 if(fitted_n<1) return(1);
89
90
91 if(samNr<=0) samplNr=
TGO_SAMPLNR;
else samplNr=samNr;
92 if(samplNr&1) samplNr++;
93 if(neighNr>samplNr-1) neighNr=samplNr-1;
94 if(tgoNr<1) tgoNr=fitted_n;
95 if(verbose>1) {
96 printf("samplNr := %d\n", samplNr);
97 printf("neighNr := %d\n", neighNr);
98 printf("tgoNr := %d\n", tgoNr);
99 if(verbose>2) {
100 printf("iTGO limits: [%g,%g]", lowlim[0], uplim[0]);
101 for(i=1; i<dim; i++) printf(" [%g,%g]", lowlim[i], uplim[i]);
102 printf("\n");
103 }
104#ifdef OMP_NUM_THREADS
105 printf("OMP_NUM_THREADS := %d\n", OMP_NUM_THREADS);
106#endif
107 fflush(stdout);
108 }
109
110
112 if(sampled_points==NULL) return(2);
113 for(i=0; i<samplNr; i++) {
115 sampled_points[i].
fvalue=0.0;
116 }
117 delta=(double*)malloc(dim*sizeof(double));
118 tempp=(double*)malloc(samplNr*sizeof(double));
119 if(delta==NULL || tempp==NULL) {free(sampled_points); return(2);}
120
121
123
124
125
126
127 for(l=0; l<tgoNr; l++) {
128
129 if(verbose>2) {printf("TGO Loop # %d: \n", l+1); fflush(stdout);}
130
131
132
133
134
137 else
139 badNr=0;
140 for(i=0; i<samplNr; i++) if(sampled_points[i].topomin==0) {
141 sampled_points[i].
fvalue=objf(dim, sampled_points[i].par, objfData);
142
143
144 if(!isfinite(sampled_points[i].fvalue)) {
145 badNr++;
146 if(verbose>5) {
147 printf("this point did not give normal return value:\n");
148 for(k=0; k<dim; k++) printf(" %10.2e", sampled_points[i].par[k]);
149 printf("\n");
150 }
151 }
152 }
153 if(verbose>4 && badNr>0) printf("Nr of bad points: %d\n", badNr);
154
155 k=0; while(k<2 && badNr>0) {
156 badNr=0; k++;
157 for(i=0; i<samplNr; i++)
158 if(sampled_points[i].topomin==0 && !isfinite(sampled_points[i].fvalue)) {
159
162 else
164
165 sampled_points[i].
fvalue=objf(dim, sampled_points[i].par, objfData);
166 if(!isfinite(sampled_points[i].fvalue)) badNr++;
167 }
168 if(verbose>4 && badNr>0) printf("Nr of bad points: %d\n", badNr);
169 }
170
171 if(verbose>6) {
172 printf("Sampled points:\n");
173 for(j=0; j<samplNr; j++) {
174 printf("%d", j+1);
175 for(i=0; i<dim; i++) printf(" %e ", sampled_points[j].par[i]);
176 printf("=>%e\n", sampled_points[j].fvalue);
177 }
178 fflush(stdout);
179 }
180
181 if(l==0 && (samplNr-badNr)<=neighNr) {
182 if(verbose>0) {
183 printf("Error in TGO: invalid function return value from all points.\n");
184 fflush(stdout);
185 }
186 free(sampled_points); free(delta); free(tempp);
187 return(3);
188 }
189
190
191
192
193
194
195
196
197 for(i=0, topoNr=0; i<samplNr; i++) {
199
200 if(!isfinite(sampled_points[i].fvalue)) continue;
201
202
203 for(j=0; j<samplNr; j++) {
204 tempp[j]=1.0E+99;
205 if(i!=j) {
206 for(k=0, tempp[j]=0.0; k<dim; k++) {
207 deltaf=uplim[k]-lowlim[k]; if(deltaf<=0.0) continue;
208 temp=sampled_points[i].
par[k]-sampled_points[j].
par[k];
209 if(deltaf>1.0E-20) temp/=deltaf;
210 if(isfinite(temp)) tempp[j] += temp*temp;
211 }
212
213
214
215 }
216 }
217
218
219
220
221 for(k=0; k<dim; k++) sampled_points[i].delta[k]=0.0;
223 for(j=0; j<neighNr; j++) {
224 min=tempp[0]; IDmin=0;
225 for(k=1; k<samplNr; k++) {if(tempp[k]<min) {min=tempp[k]; IDmin=k;}}
226 tempp[IDmin]=1e+99;
227
228
229
230 if(isfinite(sampled_points[IDmin].fvalue) &&
231 sampled_points[IDmin].fvalue<sampled_points[i].fvalue) break;
232
233
234 for(k=0; k<dim; k++)
235 sampled_points[i].delta[k]+=
236 fabs(sampled_points[i].par[k]-sampled_points[IDmin].par[k]);
237 if(isfinite(sampled_points[IDmin].fvalue) &&
238 sampled_points[IDmin].fvalue>sampled_points[i].fvalrange)
240 }
241
242
243 if(j!=neighNr) continue;
244
245 sampled_points[i].
topomin=1; topoNr++;
246
247
248
249 for(k=0; k<dim; k++) sampled_points[i].delta[k]/=(double)neighNr;
250
252
253 }
254 if(verbose>2) {printf(" %d topographical minima\n", topoNr); fflush(stdout);}
255
256
257
258 if(topoNr==0) {
259 min=sampled_points[0].
fvalue; IDmin=0;
260 for(k=1; k<samplNr; k++)
261 if(!isfinite(min) || sampled_points[k].fvalue<min) {
262 min=sampled_points[k].
fvalue; IDmin=k;}
263 sampled_points[IDmin].
topomin=1;
264 for(k=0; k<dim; k++)
265 sampled_points[IDmin].delta[k]=0.1*(uplim[k]-lowlim[k]);
266 sampled_points[i].
fvalrange+=100.0*fabs(sampled_points[i].fvalue);
267 if(verbose>2) {
268 printf(" ; therefore minimum was set to point %d at %e\n",
269 IDmin, sampled_points[IDmin].fvalue);
270 fflush(stdout);
271 }
272 topoNr=1;
273 }
274 if(verbose>3) {
275 for(i=0, min=1e+99, IDmin=0; i<samplNr; i++)
276 if(sampled_points[i].topomin==1) {
277 if(isfinite(sampled_points[i].fvalue) && sampled_points[i].fvalue<min)
278 {
279 min=sampled_points[i].
fvalue; IDmin=i;
280 }
281 }
282 printf(" best topographical min:"); fflush(stdout);
283 for(k=0; k<dim; k++) printf(" %e", sampled_points[IDmin].par[k]);
284 printf(" => %e\n", sampled_points[IDmin].fvalue); fflush(stdout);
285 }
286
288
289 if(verbose>2) printf("local optimization for each TM\n");
290 for(i=0; i<samplNr; i++) if(sampled_points[i].topomin==1) {
291
292
293 for(k=0; k<dim; k++) delta[k]=0.1*sampled_points[i].delta[k];
294 if(verbose>3) printf("point %d: original fvalue=%.2e\n",
295 i+1, sampled_points[i].fvalue);
297 tol=1.0E-08;
298 ret=
bobyqa(dim, 0, sampled_points[i].par, lowlim, uplim, delta, 0.0, 1.0E-03,
299 1.0E-10, tol, tol, 2000, &nevals,
300 &sampled_points[i].fvalue, objf, objfData, NULL, verbose-3);
301 if(ret<0 && verbose>0) {
302 printf("bobyqa error %d\n", ret); fflush(stdout);}
303 if(ret<0 && ret!=BOBYQA_ROUNDOFF_LIMITED) {
304 free(sampled_points); free(delta); free(tempp);
305 return(5);
306 }
307 if(verbose>3) {
308 printf(" local opt => %.2e (nr of evals=%d)\n",
309 sampled_points[i].fvalue, nevals);
310 fflush(stdout);
311 }
312 } else {
313 itNr=40;
314 tol=1.0E-03;
316 ret=
powell(sampled_points[i].par, delta, dim, tol, &itNr,
317 &sampled_points[i].fvalue, objf, objfData, verbose-3);
318 if(ret>1 && verbose>0) {printf("powell error %d\n", ret); fflush(stdout);}
319 if(ret>3) {
320 free(sampled_points); free(delta); free(tempp);
321 return(5);
322 }
323 if(verbose>3) {
324 printf(" local opt => %.2e (itNr=%d)\n",
325 sampled_points[i].fvalue, itNr);
326 fflush(stdout);
327 }
328 }
329 }
330 }
331
332 }
333
334 if(verbose>1) {
335 if(verbose>2) printf("Final topographical minima and deltas\n");
336 else printf("Final topographical minima\n");
337 for(i=0; i<samplNr; i++) if(sampled_points[i].topomin==1) {
338 k=0; printf(" %3d: %.2e", i, sampled_points[i].par[k]);
339 for(k=1; k<dim; k++) printf(" %.2e", sampled_points[i].par[k]);
340 printf(" => %.2e\n", sampled_points[i].fvalue); fflush(stdout);
341 if(verbose>2) {
342 k=0; printf(" %.2e", sampled_points[i].delta[k]);
343 for(k=1; k<dim; k++) printf(" %.2e", sampled_points[i].delta[k]);
344 printf(" => %.2e\n", sampled_points[i].fvalrange); fflush(stdout);
345 }
346 }
347 }
348
350
351
352
353
354 if(verbose>2) {printf("Topographic minima:\n"); fflush(stdout);}
355 for(i=0; i<samplNr; i++) if(sampled_points[i].topomin==1) {
356
357 for(k=0; k<dim; k++) {
358 if(verbose>2) {printf("%e ", sampled_points[i].par[k]); fflush(stdout);}
359 delta[k]=0.1*sampled_points[i].
delta[k];
360 }
361 if(verbose>3) {printf("=> %e ", sampled_points[i].fvalue); fflush(stdout);}
363 tol=1.0E-09;
364 ret=
bobyqa(dim, 0, sampled_points[i].par, lowlim, uplim, delta, 0.0, 1.0E-03,
365 1.0E-10, tol, tol, 2000, &nevals,
366 &sampled_points[i].fvalue, objf, objfData, NULL, verbose-3);
367 if(ret<0 && verbose>0) {
368 printf("bobyqa error %d\n", ret); fflush(stdout);}
369 if(ret<0 && ret!=BOBYQA_ROUNDOFF_LIMITED) {
370 free(sampled_points); free(delta); free(tempp);
371 return(5);
372 }
373 if(verbose>2) {
374 printf("local opt 1st round point %d => %e (nr of evals=%d)\n",
375 i+1, sampled_points[i].fvalue, nevals);
376 fflush(stdout);
377 }
378 } else {
379 itNr=50;
380 tol=1.0E-03;
382 ret=
powell(sampled_points[i].par, delta, dim, tol, &itNr,
383 &sampled_points[i].fvalue, objf, objfData, verbose-3);
384 if(ret>1 && verbose>0) {printf("powell error %d\n", ret); fflush(stdout);}
385 if(ret>3) {
386 if(verbose>0) {printf("powell error %d\n", ret); fflush(stdout);}
387 free(sampled_points); free(delta); free(tempp);
388 return(5);
389 }
390 if(verbose>2) {
391 printf("=> %e (itNr=%d) ", sampled_points[i].fvalue, itNr);
392 fflush(stdout);
393 }
394 }
395 }
396 if(verbose>0) {
397 printf("Final topographical minima after local optimization\n");
398 for(i=0; i<samplNr; i++) if(sampled_points[i].topomin==1) {
399 k=0; printf(" %3d: %.2e", i, sampled_points[i].par[k]);
400 for(k=1; k<dim; k++) printf(" %.2e", sampled_points[i].par[k]);
401 printf(" => %.2e\n", sampled_points[i].fvalue); fflush(stdout);
402 }
403 }
404 }
405
406
407 for(i=0; i<samplNr; i++) if(sampled_points[i].topomin==1) {
408
409 for(k=0; k<dim; k++) delta[k]=0.1*sampled_points[i].delta[k];
411 tol=1.0E-10;
412 ret=
bobyqa(dim, 0, sampled_points[i].par, lowlim, uplim, delta, 0.0, 1.0E-05,
413 1.0E-10, tol, tol, 1000, &nevals,
414 &sampled_points[i].fvalue, objf, objfData, NULL, verbose-3);
415 if(ret<0 && verbose>0) {
416 printf("bobyqa error %d\n", ret); fflush(stdout);}
417 if(ret<0 && ret!=BOBYQA_ROUNDOFF_LIMITED) {
418 free(sampled_points); free(delta); free(tempp);
419 return(5);
420 }
421 if(verbose>2) {
422 printf("local opt 2nd round point %d => %e (nr of evals=%d)\n",
423 i+1, sampled_points[i].fvalue, nevals);
424 fflush(stdout);
425 }
426 } else {
427 itNr=40;
428 tol=1.0E-04;
430 ret=
powell(sampled_points[i].par, delta, dim, tol, &itNr,
431 &sampled_points[i].fvalue, objf, objfData, verbose-3);
432 if(ret>1 && verbose>0) {printf("powell error %d\n", ret); fflush(stdout);}
433 if(ret>3) {
434 free(sampled_points); free(delta); free(tempp);
435 return(6);
436 }
437 if(verbose>2) {
438 printf("=> %e (itNr=%d)\n", sampled_points[i].fvalue, itNr);
439 fflush(stdout);
440 }
441 }
442 }
443
444 if(verbose>0) {
445 printf("Final topographical minima after 2nd local optimization\n");
446 for(i=0; i<samplNr; i++) if(sampled_points[i].topomin==1) {
447 k=0; printf(" %3d: %.2e", i, sampled_points[i].par[k]);
448 for(k=1; k<dim; k++) printf(" %.2e", sampled_points[i].par[k]);
449 printf(" => %.2e\n", sampled_points[i].fvalue); fflush(stdout);
450 }
451 }
452
453
454
455
456
457
458
459 for(i=0, min=1e+99, IDmin=0; i<samplNr; i++) if(sampled_points[i].topomin==1) {
460 if(isfinite(sampled_points[i].fvalue) && sampled_points[i].fvalue<min) {
461 min=sampled_points[i].
fvalue; IDmin=i;}
462 }
463 if(verbose>1) {
464 printf("Best topographical minimum:");
465 for(k=0; k<dim; k++) printf("%e ", sampled_points[IDmin].par[k]);
466 printf("-> %e \n", sampled_points[IDmin].fvalue); fflush(stdout);
467 }
468
469
470 deltaf=0.01; tol=5.0E-04;
471 do {
472 for(k=0; k<dim; k++) delta[k]=deltaf*sampled_points[IDmin].delta[k];
473
475 ret=
bobyqa(dim, 0, sampled_points[IDmin].par, lowlim, uplim, delta, 0.0, tol,
476 1.0E-10, tol, tol, 5000, &nevals,
477 &sampled_points[IDmin].fvalue, objf, objfData, NULL, verbose-3);
478 if(ret<0 && verbose>0) {
479 printf("bobyqa error %d\n", ret); fflush(stdout);}
480 if(ret<0 && ret!=BOBYQA_ROUNDOFF_LIMITED) {
481 free(sampled_points); free(delta); free(tempp);
482 return(5);
483 }
484 if(verbose>2) {
485 printf("local opt of the best point with tol=%g => %e (nr of evals=%d)\n",
486 tol, sampled_points[IDmin].fvalue, nevals);
487 fflush(stdout);
488 }
489 itNr=nevals;
490 deltaf*=0.5; tol*=0.1;
491 } else {
492 itNr=100;
494 ret=
powell(sampled_points[IDmin].par, delta, dim, tol, &itNr,
495 &sampled_points[IDmin].fvalue, objf, objfData, verbose-3);
496 if(ret>1 && verbose>0) {printf("powell error %d\n", ret); fflush(stdout);}
497 if(ret>3) {
498 free(sampled_points); free(delta); free(tempp);
499 return(7);
500 }
501 if(verbose>1) {
502 printf(" powell once more with %d iteration(s) -> WSS=%e\n",
503 itNr, sampled_points[IDmin].fvalue);
504 fflush(stdout);
505 }
506
507 deltaf*=0.5; tol*=0.25;
508 }
509 } while(itNr>1 && deltaf>1.0E-05);
510
511
512
513
514 for(k=0; k<dim; k++) gmin[k]=sampled_points[IDmin].par[k];
515 *fmin=sampled_points[IDmin].
fvalue;
516 if(!isfinite(sampled_points[IDmin].fvalue)) {
517 if(verbose>0) {printf("TGO error: valid minimum value was not reached.\n");
518 fflush(stdout);}
519 free(sampled_points); free(delta); free(tempp); return(9);
520 }
521
522
523 free(sampled_points); free(delta); free(tempp);
524 if(verbose>0) {printf("out of tgo\n"); fflush(stdout);}
525 return(0);
526}
bobyqa_result bobyqa(int n, int npt, double *x, const double *xl, const double *xu, const double *dx, const double rhoend, double xtol_rel, double minf_max, double ftol_rel, double ftol_abs, int maxeval, int *nevals, double *minf, double(*f)(int n, double *x, void *objf_data), void *objf_data, double *working_space, int verbose)
unsigned int drandSeed(short int seed)
Make and optionally set the seed for rand(), drand, drandRange, and drandGaussian().
int powell(double *p, double *delta, int parNr, double ftol, int *iterNr, double *fret, double(*_fun)(int, double *, void *), void *fundata, int verbose)
void tgoRandomParameters(TGO_POINT *p, int parNr, int sNr, double *low, double *up)
void tgoRandomParametersST(TGO_POINT *p, int parNr, int sNr, double *low, double *up)