Update copyright statements and change license to LGPL
[alexxy/gromacs.git] / src / kernel / genalg.c
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
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, 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.
11  *
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.
16  *
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.
21  *
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.
26  *
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.
34  *
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.
37  */
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***********************************************************/
60
61 /* Adopted for use in GROMACS by David van der Spoel, Oct 2001 */
62 #ifdef HAVE_CONFIG_H
63 #include <config.h>
64 #endif
65
66 #include <stdio.h>
67 #include <stdlib.h>
68 #include <math.h>
69 #include <memory.h>
70 #include "typedefs.h"
71 #include "smalloc.h"
72 #include "futil.h"
73 #include "genalg.h"
74 #include "gmx_fatal.h"
75 #include "random.h"
76 #include "txtdump.h"
77 #include "vec.h"
78 #include "main.h"
79 #include "gmxfio.h"
80
81 static const char  *strat[] = {
82   "DE/best/1/exp",          "DE/rand/1/exp",
83   "DE/rand-to-best/1/exp",  "DE/best/2/exp",
84   "DE/rand/2/exp",          "DE/best/1/bin",
85   "DE/rand/1/bin",          "DE/rand-to-best/1/bin",
86   "DE/best/2/bin",          "DE/rand/2/bin"
87 };
88
89 /*------------------------Macros----------------------------------------*/
90 static void assignd(int D,real a[],real b[])
91 {
92   int i;
93   
94   for(i=0; (i<D); i++)
95     a[i] = b[i];
96 }
97
98 static real **make2d(int n,int m)
99 {
100   int  i;
101   real **r;
102   
103   snew(r,n);
104   for(i=0;(i<n); i++)
105     snew(r[i],m);
106   return r;
107 }
108
109 static void copy2range(int D,real c[],t_range r[])
110 {
111   int i;
112   
113   for(i=0; (i<D); i++) {
114     /* Range check */
115     while (c[i] < r[i].rmin)
116       c[i] += r[i].dr;
117     while (c[i] > r[i].rmax)
118       c[i] -= r[i].dr;
119     /*    if (c[i] < r[i].rmin)
120           c[i] = r[i].rmin;
121           if (c[i] > r[i].rmax)
122           c[i] = r[i].rmax;
123     */
124     r[i].rval = c[i];
125   }
126 }
127
128 t_genalg *init_ga(FILE *fplog,const char *infile,int D,t_range range[])
129 {
130   FILE     *fpin_ptr;
131   t_genalg *ga;
132   double   ff=0,cr=0;
133   int      i,j;
134   
135   /*------Initializations----------------------------*/
136   snew(ga,1);
137   /*-----Read input data------------------------------------------------*/
138   fpin_ptr   = gmx_fio_fopen(infile,"r");
139   if ( fscanf(fpin_ptr,"%d",&ga->NP) != 1         ||         /*---choice of strategy---*/
140        fscanf(fpin_ptr,"%d",&ga->strategy) != 1   ||         /*---choice of strategy---*/
141        fscanf(fpin_ptr,"%lf",&ff) != 1            ||         /*---weight factor------------*/
142        fscanf(fpin_ptr,"%lf",&cr) != 1            ||         /*---crossing over factor-----*/
143        fscanf(fpin_ptr,"%d",&ga->seed) != 1       ||         /*---random seed----------*/
144        gmx_fio_fclose(fpin_ptr) != 1)
145   {
146       gmx_fatal(FARGS,"Error reading from file %s",infile);
147   }
148   
149   ga->FF   = ff;
150   ga->CR   = cr;
151   ga->D    = D;
152   ga->ipop = 0;
153   ga->gen  = 0;
154   
155   /* Allocate memory */
156   ga->pold = make2d(ga->NP,ga->D);
157   ga->pnew = make2d(ga->NP,ga->D);
158   snew(ga->tmp,ga->D);
159   snew(ga->best,ga->D);
160   snew(ga->bestit,ga->D);
161   snew(ga->cost,ga->NP);
162   snew(ga->msf,ga->NP);
163   snew(ga->pres,ga->NP);
164   snew(ga->scale,ga->NP);
165   snew(ga->energy,ga->NP);
166     
167   /*-----Checking input variables for proper range--------------*/
168   if ((ga->CR < 0) || (ga->CR > 1.0)) 
169     gmx_fatal(FARGS,"CR=%f, should be ex [0,1]",ga->CR);
170   if (ga->seed <= 0) 
171     gmx_fatal(FARGS,"seed=%d, should be > 0",ga->seed);
172   if ((ga->strategy < 0) || (ga->strategy > 10)) 
173     gmx_fatal(FARGS,"strategy=%d, should be ex {1-10}",ga->strategy);
174
175   /* spread initial population members */
176   for (i=0; (i<ga->NP); i++) {
177     for (j=0; (j<ga->D); j++) {
178       ga->pold[i][j] = value_rand(&(range[j]),&ga->seed);
179     }
180   }
181
182   fprintf(fplog,"-----------------------------------------------\n");  
183   fprintf(fplog,"Genetic algorithm parameters\n");
184   fprintf(fplog,"-----------------------------------------------\n");  
185   fprintf(fplog,"Number of variables:   %d\n",ga->D);
186   fprintf(fplog,"Population size:       %d\n",ga->NP);   
187   fprintf(fplog,"Strategy:              %s\n",strat[ga->strategy]);
188   fprintf(fplog,"Weight factor:         %g\n",ga->FF);
189   fprintf(fplog,"Crossing over factor:  %g\n",ga->CR);
190   fprintf(fplog,"Random seed:           %d\n",ga->seed);
191   fprintf(fplog,"-----------------------------------------------\n");  
192   
193   return ga;
194 }
195
196 void update_ga(FILE *fpout_ptr,t_range range[],t_genalg *ga)
197 {
198   static int  i_init=0;   /* Initialisation related stuff       */
199   int   i, j, L, n;      /* counting variables                 */
200   int   r1,r2,r3,r4,r5;  /* placeholders for random indexes    */
201
202   if (i_init < ga->NP) {
203     /* Copy data for first force evaluation to range array  */
204     copy2range(ga->D,ga->pold[i_init],range);
205     
206     i_init++;
207     return;
208   }
209   else {
210     /* Now starts real genetic stuff, a new trial set is made */
211     if (ga->ipop == ga->NP) {
212       ga->gen++;
213       i=ga->ipop=0;
214     }
215     else 
216       i=ga->ipop;
217
218     do {                        /* Pick a random population member */
219       /* Endless loop for ga->NP < 2 !!!     */
220       r1 = (int)(rando(&ga->seed)*ga->NP);
221     } while(r1==i);            
222       
223     do {                        /* Pick a random population member */
224       /* Endless loop for ga->NP < 3 !!!     */
225       r2 = (int)(rando(&ga->seed)*ga->NP);
226       } while((r2==i) || (r2==r1));
227     
228     do {  
229       /* Pick a random population member */
230       /* Endless loop for ga->NP < 4 !!!     */
231       r3 = (int)(rando(&ga->seed)*ga->NP);
232     } while((r3==i) || (r3==r1) || (r3==r2));
233     
234     do {
235       /* Pick a random population member */
236       /* Endless loop for ga->NP < 5 !!!     */
237       r4 = (int)(rando(&ga->seed)*ga->NP);
238     } while((r4==i) || (r4==r1) || (r4==r2) || (r4==r3));
239     
240     do {
241       /* Pick a random population member */
242       /* Endless loop for ga->NP < 6 !!!     */
243       r5 = (int)(rando(&ga->seed)*ga->NP);
244     } while((r5==i) || (r5==r1) || (r5==r2) || (r5==r3) || (r5==r4));
245     
246     
247     /* Choice of strategy
248      * We have tried to come up with a sensible naming-convention: DE/x/y/z
249      * DE :  stands for Differential Evolution
250      * x  :  a string which denotes the vector to be perturbed
251      * y  :  number of difference vectors taken for perturbation of x
252      * z  :  crossover method (exp = exponential, bin = binomial)
253      *
254      * There are some simple rules which are worth following:
255      * 1)  ga->FF is usually between 0.5 and 1 (in rare cases > 1)
256      * 2)  ga->CR is between 0 and 1 with 0., 0.3, 0.7 and 1. being worth to 
257      *     be tried first
258      * 3)  To start off ga->NP = 10*ga->D is a reasonable choice. Increase ga->NP if 
259      *     misconvergence happens.
260      * 4)  If you increase ga->NP, ga->FF usually has to be decreased
261      * 5)  When the DE/ga->best... schemes fail DE/rand... usually works and 
262      *     vice versa
263      * EXPONENTIAL ga->CROSSOVER
264      *-------DE/ga->best/1/exp-------
265      *-------Our oldest strategy but still not bad. However, we have found several
266      *-------optimization problems where misconvergence occurs.
267      */
268     assignd(ga->D,ga->tmp,ga->pold[i]);
269     n = (int)(rando(&ga->seed)*ga->D);
270     L = 0;
271     
272     switch (ga->strategy) {
273     case 1:
274       /* strategy DE0 (not in our paper) */
275       do {                       
276         ga->tmp[n] = ga->bestit[n] + ga->FF*(ga->pold[r2][n]-ga->pold[r3][n]);
277         n = (n+1)%ga->D;
278         L++;
279       } while((rando(&ga->seed) < ga->CR) && (L < ga->D));
280       break;
281       
282       /* DE/rand/1/exp
283        * This is one of my favourite strategies. It works especially 
284        * well when the ga->bestit[]"-schemes experience misconvergence. 
285        * Try e.g. ga->FF=0.7 and ga->CR=0.5 * as a first guess.
286        */
287     case 2:
288       /* strategy DE1 in the techreport */
289       do {                       
290         ga->tmp[n] = ga->pold[r1][n] + ga->FF*(ga->pold[r2][n]-ga->pold[r3][n]);
291         n = (n+1)%ga->D;
292         L++;
293       } while((rando(&ga->seed) < ga->CR) && (L < ga->D));
294       break;
295       
296       /* DE/rand-to-ga->best/1/exp 
297        * This strategy seems to be one of the ga->best strategies. 
298        * Try ga->FF=0.85 and ga->CR=1.
299        * If you get misconvergence try to increase ga->NP. 
300        * If this doesn't help you should play around with all three 
301        * control variables.
302        */
303     case 3:
304       /* similar to DE2 but generally better */
305       do {                       
306         ga->tmp[n] = ga->tmp[n] + ga->FF*(ga->bestit[n] - ga->tmp[n]) + 
307           ga->FF*(ga->pold[r1][n]-ga->pold[r2][n]);
308         n = (n+1)%ga->D;
309         L++;
310       } while((rando(&ga->seed) < ga->CR) && (L < ga->D));
311       break;
312       
313       /* DE/ga->best/2/exp is another powerful strategy worth trying */
314     case 4:
315       do {                           
316         ga->tmp[n] = ga->bestit[n] + 
317           (ga->pold[r1][n]+ga->pold[r2][n]-ga->pold[r3][n]-ga->pold[r4][n])*ga->FF;
318         n = (n+1)%ga->D;
319         L++;
320       } while((rando(&ga->seed) < ga->CR) && (L < ga->D));
321       break;
322       
323       /*----DE/rand/2/exp seems to be a robust optimizer for many functions-----*/
324     case 5:
325       do {                           
326         ga->tmp[n] = ga->pold[r5][n] + 
327           (ga->pold[r1][n]+ga->pold[r2][n]-ga->pold[r3][n]-ga->pold[r4][n])*ga->FF;
328         n = (n+1)%ga->D;
329         L++;
330       } while((rando(&ga->seed) < ga->CR) && (L < ga->D));
331       break;
332       
333       /*===Essentially same strategies but BINOMIAL ga->CROSSOVER===*/
334       
335       /*-------DE/ga->best/1/bin------*/
336     case 6:
337       for (L=0; L<ga->D; L++) {
338         /* perform D binomial trials */
339         if ((rando(&ga->seed) < ga->CR) || (L == (ga->D-1))) {
340           /* change at least one parameter */
341             ga->tmp[n] = ga->bestit[n] + ga->FF*(ga->pold[r2][n]-ga->pold[r3][n]);
342         }
343         n = (n+1)%ga->D;
344       }
345       break;
346       
347       /*-------DE/rand/1/bin------*/
348     case 7:
349       for (L=0; L<ga->D; L++) {
350         /* perform D binomial trials */
351         if ((rando(&ga->seed) < ga->CR) || (L == (ga->D-1))) {
352           /* change at least one parameter */
353           ga->tmp[n] = ga->pold[r1][n] + ga->FF*(ga->pold[r2][n]-ga->pold[r3][n]);
354         }
355         n = (n+1)%ga->D;
356       }
357       break;
358       
359       /*-------DE/rand-to-ga->best/1/bin------*/
360     case 8:
361       for (L=0; L<ga->D; L++) {
362         /* perform ga->D binomial trials */
363         if ((rando(&ga->seed) < ga->CR) || (L == (ga->D-1))) {
364           /* change at least one parameter */
365           ga->tmp[n] = ga->tmp[n] + ga->FF*(ga->bestit[n] - ga->tmp[n]) + 
366             ga->FF*(ga->pold[r1][n]-ga->pold[r2][n]);
367         }
368         n = (n+1)%ga->D;
369       }
370       break;
371       
372       /*-------DE/ga->best/2/bin------*/
373     case 9:
374       for (L=0; L<ga->D; L++) {
375         /* perform ga->D binomial trials */
376         if ((rando(&ga->seed) < ga->CR) || (L == (ga->D-1))) {
377           /* change at least one parameter */
378           ga->tmp[n] = ga->bestit[n] + 
379             (ga->pold[r1][n]+ga->pold[r2][n]-ga->pold[r3][n]-ga->pold[r4][n])*ga->FF;
380         }
381         n = (n+1)%ga->D;
382       }
383       break;
384       
385       /*-------DE/rand/2/bin-------*/
386     default:
387       for (L=0; L<ga->D; L++) {
388         /* perform ga->D binomial trials */
389         if ((rando(&ga->seed) < ga->CR) || (L == (ga->D-1))) {
390           /* change at least one parameter */
391           ga->tmp[n] = ga->pold[r5][n] + 
392             (ga->pold[r1][n]+ga->pold[r2][n]-ga->pold[r3][n]-ga->pold[r4][n])*ga->FF;
393         }
394         n = (n+1)%ga->D;
395       }
396       break;
397     }
398     
399     /*===Trial mutation now in ga->tmp[]. Test how good this choice really was.==*/
400     copy2range(ga->D,ga->tmp,range);
401   }     
402 }
403
404 gmx_bool print_ga(FILE *fp,t_genalg *ga,real msf,tensor pres,rvec scale,
405               real energy,t_range range[],real tol)
406 {
407   static int nfeval=0;          /* number of function evaluations     */
408   static gmx_bool bImproved;
409   real trial_cost;
410   real cvar;            /* computes the cost variance         */
411   real cmean;           /* mean cost                          */
412   int  i,j;
413   real **pswap;
414   
415   trial_cost = cost(pres,msf,energy);
416   if (nfeval < ga->NP) {
417     ga->cost[nfeval]   = trial_cost;
418     ga->msf[nfeval]    = msf;
419     ga->energy[nfeval] = energy;
420     copy_mat(pres,ga->pres[nfeval]);
421     copy_rvec(scale,ga->scale[nfeval]);
422     if (debug) {
423       pr_rvec(debug,0,"scale",scale,DIM,TRUE);
424       pr_rvec(debug,0,"pold ",ga->pold[nfeval]+4,DIM,TRUE);
425     }
426     nfeval++;
427     return FALSE;
428   }
429   /* When we get here we have done an initial evaluation for all
430    * animals in the population
431    */
432   if (ga->ipop == 0)
433     bImproved = FALSE;
434     
435   /* First iteration after first round of trials */
436   if (nfeval == ga->NP) {
437     /* Evaluate who is ga->best */  
438     ga->imin = 0;
439     for (j=1; (j<ga->NP); j++) {
440       if (ga->cost[j] < ga->cost[ga->imin]) 
441         ga->imin = j;
442     }
443     assignd(ga->D,ga->best,ga->pold[ga->imin]);   
444     /* save best member ever          */
445     assignd(ga->D,ga->bestit,ga->pold[ga->imin]); 
446     /* save best member of generation */
447   }
448   
449   if (trial_cost < ga->cost[ga->ipop]) {
450     if (trial_cost < ga->cost[ga->imin]) {
451       /* Was this a new minimum? */
452       /* if so, reset cmin to new low...*/
453       ga->imin = ga->ipop;
454       assignd(ga->D,ga->best,ga->tmp);
455       bImproved = TRUE;
456     }                           
457     /* improved objective function value ? */
458     ga->cost[ga->ipop]   = trial_cost;         
459     
460     ga->msf[ga->ipop]    = msf;
461     ga->energy[ga->ipop] = energy;         
462     copy_mat(pres,ga->pres[ga->ipop]);
463     copy_rvec(scale,ga->scale[ga->ipop]);
464     
465     assignd(ga->D,ga->pnew[ga->ipop],ga->tmp);
466     
467   }                            
468   else {
469     /* replace target with old value */
470     assignd(ga->D,ga->pnew[ga->ipop],ga->pold[ga->ipop]); 
471   }
472   /* #define SCALE_DEBUG*/
473 #ifdef SCALE_DEBUG
474   if (ga->D > 5) {
475     rvec dscale;
476     rvec_sub(ga->scale[ga->imin],&(ga->best[ga->D-3]),dscale);
477     if (norm(dscale) > 0) {
478       pr_rvec(fp,0,"scale",scale,DIM,TRUE);
479       pr_rvec(fp,0,"best ",&(ga->best[ga->D-3]),DIM,TRUE);
480       fprintf(fp,"imin = %d, ipop = %d, nfeval = %d\n",ga->imin,
481               ga->ipop,nfeval);
482       gmx_fatal(FARGS,"Scale inconsistency");
483     }
484   }
485 #endif  
486   
487   /* Increase population member count */
488   ga->ipop++;
489   
490   /* End mutation loop through population? */
491   if (ga->ipop == ga->NP) {
492     /* Save ga->best population member of current iteration */
493     assignd(ga->D,ga->bestit,ga->best);  
494     
495     /* swap population arrays. New generation becomes old one */
496     pswap     = ga->pold;
497     ga->pold  = ga->pnew;
498     ga->pnew  = pswap;
499     
500     /*----Compute the energy variance (just for monitoring purposes)-----------*/
501     /* compute the mean value first */
502     cmean = 0.0;          
503     for (j=0; (j<ga->NP); j++) 
504       cmean += ga->cost[j];
505     cmean = cmean/ga->NP;
506     
507     /* now the variance              */
508     cvar = 0.0;
509     for (j=0; (j<ga->NP); j++) 
510       cvar += sqr(ga->cost[j] - cmean);
511     cvar = cvar/(ga->NP-1);
512     
513     /*----Output part----------------------------------------------------------*/
514     if (1 || bImproved || (nfeval == ga->NP)) {
515       fprintf(fp,"\nGen: %5d\n  Cost: %12.3e  <Cost>: %12.3e\n"
516               "  Ener: %8.4f RMSF: %8.3f Pres: %8.1f %8.1f  %8.1f (%8.1f)\n"
517               "  Box-Scale: %15.10f  %15.10f  %15.10f\n",
518               ga->gen,ga->cost[ga->imin],cmean,ga->energy[ga->imin],
519               sqrt(ga->msf[ga->imin]),ga->pres[ga->imin][XX][XX],
520               ga->pres[ga->imin][YY][YY],ga->pres[ga->imin][ZZ][ZZ],
521               trace(ga->pres[ga->imin])/3.0,
522               ga->scale[ga->imin][XX],ga->scale[ga->imin][YY],
523               ga->scale[ga->imin][ZZ]);
524       
525       for (j=0; (j<ga->D); j++)
526         fprintf(fp,"\tbest[%d]=%-15.10f\n",j,ga->best[j]);
527       if (ga->cost[ga->imin] < tol) {
528         for (i=0; (i<ga->NP); i++) {
529           fprintf(fp,"Animal: %3d Cost:%8.3f  Ener: %8.3f RMSF: %8.3f%s\n",
530                   i,ga->cost[i],ga->energy[i],sqrt(ga->msf[i]),
531                   (i == ga->imin) ? " ***" : "");
532           for (j=0; (j<ga->D); j++)
533             fprintf(fp,"\tParam[%d][%d]=%15.10g\n",i,j,ga->pold[i][j]);
534         }
535         return TRUE;
536       }
537       fflush(fp);
538     }
539   }
540   nfeval++;
541   
542   return FALSE;
543 }
544