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**************************************************************
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 **
59 ***H*O*C*E***********************************************************/
61 /* Adopted for use in GROMACS by David van der Spoel, Oct 2001 */
76 #include "gmx_fatal.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
[])
96 for (i
= 0; (i
< D
); i
++)
102 static real
**make2d(int n
, int m
)
108 for (i
= 0; (i
< n
); i
++)
115 static void copy2range(int D
, real c
[], t_range r
[])
119 for (i
= 0; (i
< D
); i
++)
122 while (c
[i
] < r
[i
].rmin
)
126 while (c
[i
] > r
[i
].rmax
)
130 /* if (c[i] < r[i].rmin)
132 if (c[i] > r[i].rmax)
139 t_genalg
*init_ga(FILE *fplog
, const char *infile
, int D
, t_range range
[])
143 double ff
= 0, cr
= 0;
146 /*------Initializations----------------------------*/
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
);
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
);
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");
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 */
223 /* Copy data for first force evaluation to range array */
224 copy2range(ga
->D
, ga
->pold
[i_init
], range
);
231 /* Now starts real genetic stuff, a new trial set is made */
232 if (ga
->ipop
== ga
->NP
)
242 do /* Pick a random population member */
243 { /* Endless loop for ga->NP < 2 !!! */
244 r1
= (int)(rando(&ga
->seed
)*ga
->NP
);
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
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
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
);
304 switch (ga
->strategy
)
307 /* strategy DE0 (not in our paper) */
310 ga
->tmp
[n
] = ga
->bestit
[n
] + ga
->FF
*(ga
->pold
[r2
][n
]-ga
->pold
[r3
][n
]);
314 while ((rando(&ga
->seed
) < ga
->CR
) && (L
< ga
->D
));
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.
323 /* strategy DE1 in the techreport */
326 ga
->tmp
[n
] = ga
->pold
[r1
][n
] + ga
->FF
*(ga
->pold
[r2
][n
]-ga
->pold
[r3
][n
]);
330 while ((rando(&ga
->seed
) < ga
->CR
) && (L
< ga
->D
));
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
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
]);
349 while ((rando(&ga
->seed
) < ga
->CR
) && (L
< ga
->D
));
352 /* DE/ga->best/2/exp is another powerful strategy worth trying */
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
;
361 while ((rando(&ga
->seed
) < ga
->CR
) && (L
< ga
->D
));
364 /*----DE/rand/2/exp seems to be a robust optimizer for many functions-----*/
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
;
373 while ((rando(&ga
->seed
) < ga
->CR
) && (L
< ga
->D
));
376 /*===Essentially same strategies but BINOMIAL ga->CROSSOVER===*/
378 /*-------DE/ga->best/1/bin------*/
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
]);
392 /*-------DE/rand/1/bin------*/
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
]);
406 /*-------DE/rand-to-ga->best/1/bin------*/
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
]);
421 /*-------DE/ga->best/2/bin------*/
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
;
436 /*-------DE/rand/2/bin-------*/
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
;
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
;
463 real cvar
; /* computes the cost variance */
464 real cmean
; /* mean cost */
468 trial_cost
= cost(pres
, msf
, energy
);
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
]);
478 pr_rvec(debug
, 0, "scale", scale
, DIM
, TRUE
);
479 pr_rvec(debug
, 0, "pold ", ga
->pold
[nfeval
]+4, DIM
, TRUE
);
484 /* When we get here we have done an initial evaluation for all
485 * animals in the population
492 /* First iteration after first round of trials */
493 if (nfeval
== ga
->NP
)
495 /* Evaluate who is ga->best */
497 for (j
= 1; (j
< ga
->NP
); j
++)
499 if (ga
->cost
[j
] < ga
->cost
[ga
->imin
])
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...*/
517 assignd(ga
->D
, ga
->best
, ga
->tmp
);
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
);
533 /* replace target with old value */
534 assignd(ga
->D
, ga
->pnew
[ga
->ipop
], ga
->pold
[ga
->ipop
]);
536 /* #define SCALE_DEBUG*/
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
,
548 gmx_fatal(FARGS
, "Scale inconsistency");
553 /* Increase population member count */
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 */
567 /*----Compute the energy variance (just for monitoring purposes)-----------*/
568 /* compute the mean value first */
570 for (j
= 0; (j
< ga
->NP
); j
++)
572 cmean
+= ga
->cost
[j
];
574 cmean
= cmean
/ga
->NP
;
576 /* now the variance */
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
]);