1 /**********************************************************************
2   test_de.c
3  **********************************************************************
4 
5   test_de - Test program for GAUL.
6   Copyright ©2002-2005, Stewart Adcock <stewart@linux-domain.com>
7   All rights reserved.
8 
9   The latest version of this program should be available at:
10   http://gaul.sourceforge.net/
11 
12   This program is free software; you can redistribute it and/or modify
13   it under the terms of the GNU General Public License as published by
14   the Free Software Foundation; either version 2 of the License, or
15   (at your option) any later version.  Alternatively, if your project
16   is incompatible with the GPL, I will probably agree to requests
17   for permission to use the terms of any other license.
18 
19   This program is distributed in the hope that it will be useful, but
20   WITHOUT ANY WARRANTY WHATSOEVER.
21 
22   A full copy of the GNU General Public License should be in the file
23   "COPYING" provided with this distribution; if not, see:
24   http://www.gnu.org/
25 
26  **********************************************************************
27 
28   Synopsis:	Test program for GAUL's differential evolution algorithm.
29 
30 		This program aims to solve a function of the form
31 		(0.75-A)+(0.95-B)^2+(0.23-C)^3+(0.71-D)^4 = 0
32 
33  **********************************************************************/
34 
35 #include "gaul.h"
36 
37 struct strategies_t
38   {
39   char			*label;
40   ga_de_strategy_type	strategy;
41   ga_de_crossover_type	crossover;
42   int			num_perturbed;
43   double		crossover_factor;
44   double		weighting_factor;
45   double		weighting_factor2;
46   };
47 
48 static struct strategies_t strategy[]={
49         { "DE/best/1/exp (DE0)",     GA_DE_STRATEGY_BEST,       GA_DE_CROSSOVER_EXPONENTIAL, 1, 0.8, 0.5, 0.5 },
50         { "DE/best/1/exp (DE0)",     GA_DE_STRATEGY_BEST,       GA_DE_CROSSOVER_EXPONENTIAL, 1, 0.8, 2.0, 0.0 },
51         { "DE/best/2/exp",           GA_DE_STRATEGY_BEST,       GA_DE_CROSSOVER_EXPONENTIAL, 2, 0.8, 0.5, 0.5 },
52         { "DE/best/2/exp",           GA_DE_STRATEGY_BEST,       GA_DE_CROSSOVER_EXPONENTIAL, 2, 0.8, 2.0, 0.0 },
53         { "'DE/best/3/exp'",         GA_DE_STRATEGY_BEST,       GA_DE_CROSSOVER_EXPONENTIAL, 3, 0.8, 0.5, 0.5 },
54         { "'DE/best/3/exp'",         GA_DE_STRATEGY_BEST,       GA_DE_CROSSOVER_EXPONENTIAL, 3, 0.8, 2.0, 0.0 },
55         { "DE/rand/1/exp (DE1)",     GA_DE_STRATEGY_RAND,       GA_DE_CROSSOVER_EXPONENTIAL, 1, 0.8, 0.5, 0.5 },
56         { "DE/rand/1/exp (DE1)",     GA_DE_STRATEGY_RAND,       GA_DE_CROSSOVER_EXPONENTIAL, 1, 0.8, 2.0, 0.0 },
57         { "DE/rand/2/exp",           GA_DE_STRATEGY_RAND,       GA_DE_CROSSOVER_EXPONENTIAL, 2, 0.8, 0.5, 0.5 },
58         { "DE/rand/2/exp",           GA_DE_STRATEGY_RAND,       GA_DE_CROSSOVER_EXPONENTIAL, 2, 0.8, 2.0, 0.0 },
59         { "'DE/rand/3/exp'",         GA_DE_STRATEGY_RAND,       GA_DE_CROSSOVER_EXPONENTIAL, 3, 0.8, 0.5, 0.5 },
60         { "'DE/rand/3/exp'",         GA_DE_STRATEGY_RAND,       GA_DE_CROSSOVER_EXPONENTIAL, 3, 0.8, 2.0, 0.0 },
61         { "DE/rand-to-best/1/exp",   GA_DE_STRATEGY_RANDTOBEST, GA_DE_CROSSOVER_EXPONENTIAL, 1, 0.8, 0.5, 0.5 },
62         { "DE/rand-to-best/1/exp",   GA_DE_STRATEGY_RANDTOBEST, GA_DE_CROSSOVER_EXPONENTIAL, 1, 0.8, 2.0, 0.0 },
63         { "'DE/rand-to-best/2/exp'", GA_DE_STRATEGY_RANDTOBEST, GA_DE_CROSSOVER_EXPONENTIAL, 2, 0.8, 0.5, 0.5 },
64         { "'DE/rand-to-best/2/exp'", GA_DE_STRATEGY_RANDTOBEST, GA_DE_CROSSOVER_EXPONENTIAL, 2, 0.8, 2.0, 0.0 },
65         { "DE/best/1/bin",           GA_DE_STRATEGY_BEST,       GA_DE_CROSSOVER_BINOMIAL,    1, 0.8, 0.5, 0.5 },
66         { "DE/best/1/bin",           GA_DE_STRATEGY_BEST,       GA_DE_CROSSOVER_BINOMIAL,    1, 0.8, 2.0, 0.0 },
67         { "DE/best/2/bin",           GA_DE_STRATEGY_BEST,       GA_DE_CROSSOVER_BINOMIAL,    2, 0.8, 0.5, 0.5 },
68         { "DE/best/2/bin",           GA_DE_STRATEGY_BEST,       GA_DE_CROSSOVER_BINOMIAL,    2, 0.8, 2.0, 0.0 },
69         { "'DE/best/3/bin'",         GA_DE_STRATEGY_BEST,       GA_DE_CROSSOVER_BINOMIAL,    3, 0.8, 0.5, 0.5 },
70         { "'DE/best/3/bin'",         GA_DE_STRATEGY_BEST,       GA_DE_CROSSOVER_BINOMIAL,    3, 0.8, 2.0, 0.0 },
71         { "DE/rand/1/bin",           GA_DE_STRATEGY_RAND,       GA_DE_CROSSOVER_BINOMIAL,    1, 0.8, 0.5, 0.5 },
72         { "DE/rand/1/bin",           GA_DE_STRATEGY_RAND,       GA_DE_CROSSOVER_BINOMIAL,    1, 0.8, 2.0, 0.0 },
73         { "DE/rand/2/bin",           GA_DE_STRATEGY_RAND,       GA_DE_CROSSOVER_BINOMIAL,    2, 0.8, 0.5, 0.5 },
74         { "DE/rand/2/bin",           GA_DE_STRATEGY_RAND,       GA_DE_CROSSOVER_BINOMIAL,    2, 0.8, 2.0, 0.0 },
75         { "'DE/rand/3/bin'",         GA_DE_STRATEGY_RAND,       GA_DE_CROSSOVER_BINOMIAL,    3, 0.8, 0.5, 0.5 },
76         { "'DE/rand/3/bin'",         GA_DE_STRATEGY_RAND,       GA_DE_CROSSOVER_BINOMIAL,    3, 0.8, 2.0, 0.0 },
77         { "DE/rand-to-best/1/bin",   GA_DE_STRATEGY_RANDTOBEST, GA_DE_CROSSOVER_BINOMIAL,    1, 0.8, 0.5, 0.5 },
78         { "DE/rand-to-best/1/bin",   GA_DE_STRATEGY_RANDTOBEST, GA_DE_CROSSOVER_BINOMIAL,    1, 0.8, 2.0, 0.0 },
79         { "'DE/rand-to-best/2/bin'", GA_DE_STRATEGY_RANDTOBEST, GA_DE_CROSSOVER_BINOMIAL,    2, 0.8, 0.5, 0.5 },
80         { "'DE/rand-to-best/2/bin'", GA_DE_STRATEGY_RANDTOBEST, GA_DE_CROSSOVER_BINOMIAL,    2, 0.8, 2.0, 0.0 },
81         { NULL, 0, 0, 0, 0.0, 0.0 } };
82 
83 
84 /**********************************************************************
85   test_score()
86   synopsis:	Fitness function.
87   parameters:
88   return:
89   updated:	25 Nov 2002
90  **********************************************************************/
91 
test_score(population * pop,entity * entity)92 boolean test_score(population *pop, entity *entity)
93   {
94   double		A, B, C, D;	/* Parameters. */
95 
96   A = ((double *)entity->chromosome[0])[0];
97   B = ((double *)entity->chromosome[0])[1];
98   C = ((double *)entity->chromosome[0])[2];
99   D = ((double *)entity->chromosome[0])[3];
100 
101   entity->fitness = -(fabs(0.75-A)+SQU(0.95-B)+fabs(CUBE(0.23-C))+FOURTH_POW(0.71-D));
102 
103   return TRUE;
104   }
105 
106 
107 /**********************************************************************
108   test_generation_callback()
109   synopsis:	Generation callback
110   parameters:
111   return:
112   updated:	21 Mar 2005
113  **********************************************************************/
114 
test_generation_callback(int generation,population * pop)115 boolean test_generation_callback(int generation, population *pop)
116   {
117 
118 /*
119  * This is a easy method for implementing randomly selected
120  * scaling factor (F in original paper) for each generation, as
121  * suggested in:
122  *
123  * Karaboga D., Okdem, S. "A simple and global optimization algorithm
124  * for engineering problems: differential evolution algorithm",
125  * Elec. Engin. 12:53-60 (2004).
126  *
127  * Uncomment, if desired.
128  */
129 /*
130   pop->de_params->weighting_factor = random_double_range(-2.0, 2.0);
131 */
132 
133 /*
134  * Write rank 1 solution every tenth generation.  Note, that this is
135  * not neccesarily the best solution because DE doesn't require the
136  * population to be sorted, as genetic algorithms usually do.
137  */
138   if ( generation%10 == 0)
139     printf( "%d: A = %f B = %f C = %f D = %f (fitness = %f)\n",
140             generation,
141             ((double *)pop->entity_iarray[0]->chromosome[0])[0],
142             ((double *)pop->entity_iarray[0]->chromosome[0])[1],
143             ((double *)pop->entity_iarray[0]->chromosome[0])[2],
144             ((double *)pop->entity_iarray[0]->chromosome[0])[3],
145             pop->entity_iarray[0]->fitness );
146 
147   return TRUE;
148   }
149 
150 
151 /**********************************************************************
152   test_seed()
153   synopsis:	Seed genetic data.
154   parameters:	population *pop
155 		entity *adam
156   return:	success
157   last updated: 25 Nov 2002
158  **********************************************************************/
159 
test_seed(population * pop,entity * adam)160 boolean test_seed(population *pop, entity *adam)
161   {
162 
163 /* Checks. */
164   if (!pop) die("Null pointer to population structure passed.");
165   if (!adam) die("Null pointer to entity structure passed.");
166 
167 /* Seeding. */
168   ((double *)adam->chromosome[0])[0] = random_double(2.0);
169   ((double *)adam->chromosome[0])[1] = random_double(2.0);
170   ((double *)adam->chromosome[0])[2] = random_double(2.0);
171   ((double *)adam->chromosome[0])[3] = random_double(2.0);
172 
173   return TRUE;
174   }
175 
176 
177 /**********************************************************************
178   main()
179   synopsis:	Main function.
180   parameters:
181   return:
182   updated:	21 Mar 2005
183  **********************************************************************/
184 
main(int argc,char ** argv)185 int main(int argc, char **argv)
186   {
187   population		*pop;		/* Population of solutions. */
188   int			i=0;		/* Loop variable over strategies. */
189 
190   random_seed(23091975);
191 
192   log_init(LOG_NORMAL, NULL, NULL, FALSE);
193 
194   while ( strategy[i].label != NULL )
195     {
196     if ( strategy[i].weighting_factor != strategy[i].weighting_factor2 )
197       {
198       printf( "Strategy %s ; C = %f ; F = rand( %f, %f )\n",
199             strategy[i].label,
200             strategy[i].crossover_factor,
201             strategy[i].weighting_factor, strategy[i].weighting_factor2 );
202       }
203     else
204       {
205       printf( "Strategy %s ; C = %f ; F = %f\n",
206               strategy[i].label,
207               strategy[i].crossover_factor,
208               strategy[i].weighting_factor );
209       }
210 
211     pop = ga_genesis_double(
212          40,			/* const int              population_size */
213          1,			/* const int              num_chromo */
214          4,			/* const int              len_chromo */
215          test_generation_callback,/* GAgeneration_hook      generation_hook */
216          NULL,			/* GAiteration_hook       iteration_hook */
217          NULL,			/* GAdata_destructor      data_destructor */
218          NULL,			/* GAdata_ref_incrementor data_ref_incrementor */
219          test_score,		/* GAevaluate             evaluate */
220          test_seed,		/* GAseed                 seed */
221          NULL,			/* GAadapt                adapt */
222          NULL,			/* GAselect_one           select_one */
223          NULL,			/* GAselect_two           select_two */
224          NULL,			/* GAmutate               mutate */
225          NULL,			/* GAcrossover            crossover */
226          NULL,			/* GAreplace              replace */
227          NULL			/* vpointer               User data */
228             );
229 
230     ga_population_set_differentialevolution_parameters(
231         pop, strategy[i].strategy, strategy[i].crossover,
232         strategy[i].num_perturbed, strategy[i].weighting_factor, strategy[i].weighting_factor2,
233         strategy[i].crossover_factor
234         );
235 
236     ga_differentialevolution(
237          pop,				/* population	*pop */
238          50				/* const int	max_generations */
239               );
240 
241     printf( "Final: A = %f B = %f C = %f D = %f (fitness = %f)\n",
242             ((double *)pop->entity_iarray[0]->chromosome[0])[0],
243             ((double *)pop->entity_iarray[0]->chromosome[0])[1],
244             ((double *)pop->entity_iarray[0]->chromosome[0])[2],
245             ((double *)pop->entity_iarray[0]->chromosome[0])[3],
246             pop->entity_iarray[0]->fitness );
247 
248     ga_extinction(pop);
249 
250     i++;
251     }
252 
253   exit(EXIT_SUCCESS);
254   }
255 
256 
257