Patch for Native Client builds.
[gromacs.git] / src / kernel / genalg.c
blob1e9abdc6d9a949564479982e5223b21ee2f3e73a
1 /*
2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5 * Copyright (c) 2001-2004, The GROMACS development team,
6 * check out http://www.gromacs.org for more information.
7 * Copyright (c) 2012,2013, by the GROMACS development team, led by
8 * David van der Spoel, Berk Hess, Erik Lindahl, and including many
9 * others, as listed in the AUTHORS file in the top-level source
10 * directory and at http://www.gromacs.org.
12 * GROMACS is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public License
14 * as published by the Free Software Foundation; either version 2.1
15 * of the License, or (at your option) any later version.
17 * GROMACS is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with GROMACS; if not, see
24 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
25 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 * If you want to redistribute modifications to GROMACS, please
28 * consider that scientific software is very special. Version
29 * control is crucial - bugs must be traceable. We will be happy to
30 * consider code for inclusion in the official distribution, but
31 * derived work must not be called official GROMACS. Details are found
32 * in the README & COPYING files - if they are missing, get the
33 * official version at http://www.gromacs.org.
35 * To help us fund GROMACS development, we humbly ask that you cite
36 * the research papers on the package. Check out http://www.gromacs.org.
38 /**H*O*C**************************************************************
39 ** **
40 ** No.!Version! Date ! Request ! Modification ! Author **
41 ** ---+-------+------+---------+---------------------------+------- **
42 ** 1 + 3.1 +5/18/95+ - + strategy DE/rand-to-best/1+ Storn **
43 ** + + + + included + **
44 ** 1 + 3.2 +6/06/95+C.Fleiner+ change loops into memcpy + Storn **
45 ** 2 + 3.2 +6/06/95+ - + update comments + Storn **
46 ** 1 + 3.3 +6/15/95+ K.Price + strategy DE/best/2 incl. + Storn **
47 ** 2 + 3.3 +6/16/95+ - + comments and beautifying + Storn **
48 ** 3 + 3.3 +7/13/95+ - + upper and lower bound for + Storn **
49 ** + + + + initialization + **
50 ** 1 + 3.4 +2/12/96+ - + increased printout prec. + Storn **
51 ** 1 + 3.5 +5/28/96+ - + strategies revisited + Storn **
52 ** 2 + 3.5 +5/28/96+ - + strategy DE/rand/2 incl. + Storn **
53 ** 1 + 3.6 +8/06/96+ K.Price + Binomial Crossover added + Storn **
54 ** 2 + 3.6 +9/30/96+ K.Price + cost variance output + Storn **
55 ** 3 + 3.6 +9/30/96+ - + alternative to ASSIGND + Storn **
56 ** 4 + 3.6 +10/1/96+ - + variable checking inserted + Storn **
57 ** 5 + 3.6 +10/1/96+ - + strategy indic. improved + Storn **
58 ** **
59 ***H*O*C*E***********************************************************/
61 /* Adopted for use in GROMACS by David van der Spoel, Oct 2001 */
62 #ifdef HAVE_CONFIG_H
63 #include <config.h>
64 #endif
66 #include <stdio.h>
67 #include <stdlib.h>
68 #include <math.h>
69 #ifdef HAVE_MEMORY_H
70 #include <memory.h>
71 #endif
72 #include "typedefs.h"
73 #include "smalloc.h"
74 #include "futil.h"
75 #include "genalg.h"
76 #include "gmx_fatal.h"
77 #include "random.h"
78 #include "txtdump.h"
79 #include "vec.h"
80 #include "main.h"
81 #include "gmxfio.h"
83 static const char *strat[] = {
84 "DE/best/1/exp", "DE/rand/1/exp",
85 "DE/rand-to-best/1/exp", "DE/best/2/exp",
86 "DE/rand/2/exp", "DE/best/1/bin",
87 "DE/rand/1/bin", "DE/rand-to-best/1/bin",
88 "DE/best/2/bin", "DE/rand/2/bin"
91 /*------------------------Macros----------------------------------------*/
92 static void assignd(int D, real a[], real b[])
94 int i;
96 for (i = 0; (i < D); i++)
98 a[i] = b[i];
102 static real **make2d(int n, int m)
104 int i;
105 real **r;
107 snew(r, n);
108 for (i = 0; (i < n); i++)
110 snew(r[i], m);
112 return r;
115 static void copy2range(int D, real c[], t_range r[])
117 int i;
119 for (i = 0; (i < D); i++)
121 /* Range check */
122 while (c[i] < r[i].rmin)
124 c[i] += r[i].dr;
126 while (c[i] > r[i].rmax)
128 c[i] -= r[i].dr;
130 /* if (c[i] < r[i].rmin)
131 c[i] = r[i].rmin;
132 if (c[i] > r[i].rmax)
133 c[i] = r[i].rmax;
135 r[i].rval = c[i];
139 t_genalg *init_ga(FILE *fplog, const char *infile, int D, t_range range[])
141 FILE *fpin_ptr;
142 t_genalg *ga;
143 double ff = 0, cr = 0;
144 int i, j;
146 /*------Initializations----------------------------*/
147 snew(ga, 1);
148 /*-----Read input data------------------------------------------------*/
149 fpin_ptr = gmx_fio_fopen(infile, "r");
150 if (fscanf(fpin_ptr, "%d", &ga->NP) != 1 || /*---choice of strategy---*/
151 fscanf(fpin_ptr, "%d", &ga->strategy) != 1 || /*---choice of strategy---*/
152 fscanf(fpin_ptr, "%lf", &ff) != 1 || /*---weight factor------------*/
153 fscanf(fpin_ptr, "%lf", &cr) != 1 || /*---crossing over factor-----*/
154 fscanf(fpin_ptr, "%d", &ga->seed) != 1 || /*---random seed----------*/
155 gmx_fio_fclose(fpin_ptr) != 1)
157 gmx_fatal(FARGS, "Error reading from file %s", infile);
160 ga->FF = ff;
161 ga->CR = cr;
162 ga->D = D;
163 ga->ipop = 0;
164 ga->gen = 0;
166 /* Allocate memory */
167 ga->pold = make2d(ga->NP, ga->D);
168 ga->pnew = make2d(ga->NP, ga->D);
169 snew(ga->tmp, ga->D);
170 snew(ga->best, ga->D);
171 snew(ga->bestit, ga->D);
172 snew(ga->cost, ga->NP);
173 snew(ga->msf, ga->NP);
174 snew(ga->pres, ga->NP);
175 snew(ga->scale, ga->NP);
176 snew(ga->energy, ga->NP);
178 /*-----Checking input variables for proper range--------------*/
179 if ((ga->CR < 0) || (ga->CR > 1.0))
181 gmx_fatal(FARGS, "CR=%f, should be ex [0,1]", ga->CR);
183 if (ga->seed <= 0)
185 gmx_fatal(FARGS, "seed=%d, should be > 0", ga->seed);
187 if ((ga->strategy < 0) || (ga->strategy > 10))
189 gmx_fatal(FARGS, "strategy=%d, should be ex {1-10}", ga->strategy);
192 /* spread initial population members */
193 for (i = 0; (i < ga->NP); i++)
195 for (j = 0; (j < ga->D); j++)
197 ga->pold[i][j] = value_rand(&(range[j]), &ga->seed);
201 fprintf(fplog, "-----------------------------------------------\n");
202 fprintf(fplog, "Genetic algorithm parameters\n");
203 fprintf(fplog, "-----------------------------------------------\n");
204 fprintf(fplog, "Number of variables: %d\n", ga->D);
205 fprintf(fplog, "Population size: %d\n", ga->NP);
206 fprintf(fplog, "Strategy: %s\n", strat[ga->strategy]);
207 fprintf(fplog, "Weight factor: %g\n", ga->FF);
208 fprintf(fplog, "Crossing over factor: %g\n", ga->CR);
209 fprintf(fplog, "Random seed: %d\n", ga->seed);
210 fprintf(fplog, "-----------------------------------------------\n");
212 return ga;
215 void update_ga(FILE *fpout_ptr, t_range range[], t_genalg *ga)
217 static int i_init = 0; /* Initialisation related stuff */
218 int i, j, L, n; /* counting variables */
219 int r1, r2, r3, r4, r5; /* placeholders for random indexes */
221 if (i_init < ga->NP)
223 /* Copy data for first force evaluation to range array */
224 copy2range(ga->D, ga->pold[i_init], range);
226 i_init++;
227 return;
229 else
231 /* Now starts real genetic stuff, a new trial set is made */
232 if (ga->ipop == ga->NP)
234 ga->gen++;
235 i = ga->ipop = 0;
237 else
239 i = ga->ipop;
242 do /* Pick a random population member */
243 { /* Endless loop for ga->NP < 2 !!! */
244 r1 = (int)(rando(&ga->seed)*ga->NP);
246 while (r1 == i);
248 do /* Pick a random population member */
249 { /* Endless loop for ga->NP < 3 !!! */
250 r2 = (int)(rando(&ga->seed)*ga->NP);
252 while ((r2 == i) || (r2 == r1));
256 /* Pick a random population member */
257 /* Endless loop for ga->NP < 4 !!! */
258 r3 = (int)(rando(&ga->seed)*ga->NP);
260 while ((r3 == i) || (r3 == r1) || (r3 == r2));
264 /* Pick a random population member */
265 /* Endless loop for ga->NP < 5 !!! */
266 r4 = (int)(rando(&ga->seed)*ga->NP);
268 while ((r4 == i) || (r4 == r1) || (r4 == r2) || (r4 == r3));
272 /* Pick a random population member */
273 /* Endless loop for ga->NP < 6 !!! */
274 r5 = (int)(rando(&ga->seed)*ga->NP);
276 while ((r5 == i) || (r5 == r1) || (r5 == r2) || (r5 == r3) || (r5 == r4));
279 /* Choice of strategy
280 * We have tried to come up with a sensible naming-convention: DE/x/y/z
281 * DE : stands for Differential Evolution
282 * x : a string which denotes the vector to be perturbed
283 * y : number of difference vectors taken for perturbation of x
284 * z : crossover method (exp = exponential, bin = binomial)
286 * There are some simple rules which are worth following:
287 * 1) ga->FF is usually between 0.5 and 1 (in rare cases > 1)
288 * 2) ga->CR is between 0 and 1 with 0., 0.3, 0.7 and 1. being worth to
289 * be tried first
290 * 3) To start off ga->NP = 10*ga->D is a reasonable choice. Increase ga->NP if
291 * misconvergence happens.
292 * 4) If you increase ga->NP, ga->FF usually has to be decreased
293 * 5) When the DE/ga->best... schemes fail DE/rand... usually works and
294 * vice versa
295 * EXPONENTIAL ga->CROSSOVER
296 *-------DE/ga->best/1/exp-------
297 *-------Our oldest strategy but still not bad. However, we have found several
298 *-------optimization problems where misconvergence occurs.
300 assignd(ga->D, ga->tmp, ga->pold[i]);
301 n = (int)(rando(&ga->seed)*ga->D);
302 L = 0;
304 switch (ga->strategy)
306 case 1:
307 /* strategy DE0 (not in our paper) */
310 ga->tmp[n] = ga->bestit[n] + ga->FF*(ga->pold[r2][n]-ga->pold[r3][n]);
311 n = (n+1)%ga->D;
312 L++;
314 while ((rando(&ga->seed) < ga->CR) && (L < ga->D));
315 break;
317 /* DE/rand/1/exp
318 * This is one of my favourite strategies. It works especially
319 * well when the ga->bestit[]"-schemes experience misconvergence.
320 * Try e.g. ga->FF=0.7 and ga->CR=0.5 * as a first guess.
322 case 2:
323 /* strategy DE1 in the techreport */
326 ga->tmp[n] = ga->pold[r1][n] + ga->FF*(ga->pold[r2][n]-ga->pold[r3][n]);
327 n = (n+1)%ga->D;
328 L++;
330 while ((rando(&ga->seed) < ga->CR) && (L < ga->D));
331 break;
333 /* DE/rand-to-ga->best/1/exp
334 * This strategy seems to be one of the ga->best strategies.
335 * Try ga->FF=0.85 and ga->CR=1.
336 * If you get misconvergence try to increase ga->NP.
337 * If this doesn't help you should play around with all three
338 * control variables.
340 case 3:
341 /* similar to DE2 but generally better */
344 ga->tmp[n] = ga->tmp[n] + ga->FF*(ga->bestit[n] - ga->tmp[n]) +
345 ga->FF*(ga->pold[r1][n]-ga->pold[r2][n]);
346 n = (n+1)%ga->D;
347 L++;
349 while ((rando(&ga->seed) < ga->CR) && (L < ga->D));
350 break;
352 /* DE/ga->best/2/exp is another powerful strategy worth trying */
353 case 4:
356 ga->tmp[n] = ga->bestit[n] +
357 (ga->pold[r1][n]+ga->pold[r2][n]-ga->pold[r3][n]-ga->pold[r4][n])*ga->FF;
358 n = (n+1)%ga->D;
359 L++;
361 while ((rando(&ga->seed) < ga->CR) && (L < ga->D));
362 break;
364 /*----DE/rand/2/exp seems to be a robust optimizer for many functions-----*/
365 case 5:
368 ga->tmp[n] = ga->pold[r5][n] +
369 (ga->pold[r1][n]+ga->pold[r2][n]-ga->pold[r3][n]-ga->pold[r4][n])*ga->FF;
370 n = (n+1)%ga->D;
371 L++;
373 while ((rando(&ga->seed) < ga->CR) && (L < ga->D));
374 break;
376 /*===Essentially same strategies but BINOMIAL ga->CROSSOVER===*/
378 /*-------DE/ga->best/1/bin------*/
379 case 6:
380 for (L = 0; L < ga->D; L++)
382 /* perform D binomial trials */
383 if ((rando(&ga->seed) < ga->CR) || (L == (ga->D-1)))
385 /* change at least one parameter */
386 ga->tmp[n] = ga->bestit[n] + ga->FF*(ga->pold[r2][n]-ga->pold[r3][n]);
388 n = (n+1)%ga->D;
390 break;
392 /*-------DE/rand/1/bin------*/
393 case 7:
394 for (L = 0; L < ga->D; L++)
396 /* perform D binomial trials */
397 if ((rando(&ga->seed) < ga->CR) || (L == (ga->D-1)))
399 /* change at least one parameter */
400 ga->tmp[n] = ga->pold[r1][n] + ga->FF*(ga->pold[r2][n]-ga->pold[r3][n]);
402 n = (n+1)%ga->D;
404 break;
406 /*-------DE/rand-to-ga->best/1/bin------*/
407 case 8:
408 for (L = 0; L < ga->D; L++)
410 /* perform ga->D binomial trials */
411 if ((rando(&ga->seed) < ga->CR) || (L == (ga->D-1)))
413 /* change at least one parameter */
414 ga->tmp[n] = ga->tmp[n] + ga->FF*(ga->bestit[n] - ga->tmp[n]) +
415 ga->FF*(ga->pold[r1][n]-ga->pold[r2][n]);
417 n = (n+1)%ga->D;
419 break;
421 /*-------DE/ga->best/2/bin------*/
422 case 9:
423 for (L = 0; L < ga->D; L++)
425 /* perform ga->D binomial trials */
426 if ((rando(&ga->seed) < ga->CR) || (L == (ga->D-1)))
428 /* change at least one parameter */
429 ga->tmp[n] = ga->bestit[n] +
430 (ga->pold[r1][n]+ga->pold[r2][n]-ga->pold[r3][n]-ga->pold[r4][n])*ga->FF;
432 n = (n+1)%ga->D;
434 break;
436 /*-------DE/rand/2/bin-------*/
437 default:
438 for (L = 0; L < ga->D; L++)
440 /* perform ga->D binomial trials */
441 if ((rando(&ga->seed) < ga->CR) || (L == (ga->D-1)))
443 /* change at least one parameter */
444 ga->tmp[n] = ga->pold[r5][n] +
445 (ga->pold[r1][n]+ga->pold[r2][n]-ga->pold[r3][n]-ga->pold[r4][n])*ga->FF;
447 n = (n+1)%ga->D;
449 break;
452 /*===Trial mutation now in ga->tmp[]. Test how good this choice really was.==*/
453 copy2range(ga->D, ga->tmp, range);
457 gmx_bool print_ga(FILE *fp, t_genalg *ga, real msf, tensor pres, rvec scale,
458 real energy, t_range range[], real tol)
460 static int nfeval = 0; /* number of function evaluations */
461 static gmx_bool bImproved;
462 real trial_cost;
463 real cvar; /* computes the cost variance */
464 real cmean; /* mean cost */
465 int i, j;
466 real **pswap;
468 trial_cost = cost(pres, msf, energy);
469 if (nfeval < ga->NP)
471 ga->cost[nfeval] = trial_cost;
472 ga->msf[nfeval] = msf;
473 ga->energy[nfeval] = energy;
474 copy_mat(pres, ga->pres[nfeval]);
475 copy_rvec(scale, ga->scale[nfeval]);
476 if (debug)
478 pr_rvec(debug, 0, "scale", scale, DIM, TRUE);
479 pr_rvec(debug, 0, "pold ", ga->pold[nfeval]+4, DIM, TRUE);
481 nfeval++;
482 return FALSE;
484 /* When we get here we have done an initial evaluation for all
485 * animals in the population
487 if (ga->ipop == 0)
489 bImproved = FALSE;
492 /* First iteration after first round of trials */
493 if (nfeval == ga->NP)
495 /* Evaluate who is ga->best */
496 ga->imin = 0;
497 for (j = 1; (j < ga->NP); j++)
499 if (ga->cost[j] < ga->cost[ga->imin])
501 ga->imin = j;
504 assignd(ga->D, ga->best, ga->pold[ga->imin]);
505 /* save best member ever */
506 assignd(ga->D, ga->bestit, ga->pold[ga->imin]);
507 /* save best member of generation */
510 if (trial_cost < ga->cost[ga->ipop])
512 if (trial_cost < ga->cost[ga->imin])
514 /* Was this a new minimum? */
515 /* if so, reset cmin to new low...*/
516 ga->imin = ga->ipop;
517 assignd(ga->D, ga->best, ga->tmp);
518 bImproved = TRUE;
520 /* improved objective function value ? */
521 ga->cost[ga->ipop] = trial_cost;
523 ga->msf[ga->ipop] = msf;
524 ga->energy[ga->ipop] = energy;
525 copy_mat(pres, ga->pres[ga->ipop]);
526 copy_rvec(scale, ga->scale[ga->ipop]);
528 assignd(ga->D, ga->pnew[ga->ipop], ga->tmp);
531 else
533 /* replace target with old value */
534 assignd(ga->D, ga->pnew[ga->ipop], ga->pold[ga->ipop]);
536 /* #define SCALE_DEBUG*/
537 #ifdef SCALE_DEBUG
538 if (ga->D > 5)
540 rvec dscale;
541 rvec_sub(ga->scale[ga->imin], &(ga->best[ga->D-3]), dscale);
542 if (norm(dscale) > 0)
544 pr_rvec(fp, 0, "scale", scale, DIM, TRUE);
545 pr_rvec(fp, 0, "best ", &(ga->best[ga->D-3]), DIM, TRUE);
546 fprintf(fp, "imin = %d, ipop = %d, nfeval = %d\n", ga->imin,
547 ga->ipop, nfeval);
548 gmx_fatal(FARGS, "Scale inconsistency");
551 #endif
553 /* Increase population member count */
554 ga->ipop++;
556 /* End mutation loop through population? */
557 if (ga->ipop == ga->NP)
559 /* Save ga->best population member of current iteration */
560 assignd(ga->D, ga->bestit, ga->best);
562 /* swap population arrays. New generation becomes old one */
563 pswap = ga->pold;
564 ga->pold = ga->pnew;
565 ga->pnew = pswap;
567 /*----Compute the energy variance (just for monitoring purposes)-----------*/
568 /* compute the mean value first */
569 cmean = 0.0;
570 for (j = 0; (j < ga->NP); j++)
572 cmean += ga->cost[j];
574 cmean = cmean/ga->NP;
576 /* now the variance */
577 cvar = 0.0;
578 for (j = 0; (j < ga->NP); j++)
580 cvar += sqr(ga->cost[j] - cmean);
582 cvar = cvar/(ga->NP-1);
584 /*----Output part----------------------------------------------------------*/
585 if (1 || bImproved || (nfeval == ga->NP))
587 fprintf(fp, "\nGen: %5d\n Cost: %12.3e <Cost>: %12.3e\n"
588 " Ener: %8.4f RMSF: %8.3f Pres: %8.1f %8.1f %8.1f (%8.1f)\n"
589 " Box-Scale: %15.10f %15.10f %15.10f\n",
590 ga->gen, ga->cost[ga->imin], cmean, ga->energy[ga->imin],
591 sqrt(ga->msf[ga->imin]), ga->pres[ga->imin][XX][XX],
592 ga->pres[ga->imin][YY][YY], ga->pres[ga->imin][ZZ][ZZ],
593 trace(ga->pres[ga->imin])/3.0,
594 ga->scale[ga->imin][XX], ga->scale[ga->imin][YY],
595 ga->scale[ga->imin][ZZ]);
597 for (j = 0; (j < ga->D); j++)
599 fprintf(fp, "\tbest[%d]=%-15.10f\n", j, ga->best[j]);
601 if (ga->cost[ga->imin] < tol)
603 for (i = 0; (i < ga->NP); i++)
605 fprintf(fp, "Animal: %3d Cost:%8.3f Ener: %8.3f RMSF: %8.3f%s\n",
606 i, ga->cost[i], ga->energy[i], sqrt(ga->msf[i]),
607 (i == ga->imin) ? " ***" : "");
608 for (j = 0; (j < ga->D); j++)
610 fprintf(fp, "\tParam[%d][%d]=%15.10g\n", i, j, ga->pold[i][j]);
613 return TRUE;
615 fflush(fp);
618 nfeval++;
620 return FALSE;