2 #define _POSIX_C_SOURCE 200112L
17 #include "sn_network.h"
19 /* Yes, this is ugly, but the GNU libc doesn't export it with the above flags.
21 char *strdup (const char *s);
23 struct population_entry_s
25 sn_network_t *network;
28 typedef struct population_entry_s population_entry_t;
30 static uint64_t iteration_counter = 0;
31 static int max_population_size = 128;
32 static int olymp_size = 96;
33 static int inputs_num = 16;
35 static char *initial_input_file = NULL;
36 static char *best_output_file = NULL;
38 static int stats_interval = 0;
40 static population_entry_t *population = NULL;
41 static int population_size = 0;
43 static int do_loop = 0;
45 static void sigint_handler (int signal)
48 } /* void sigint_handler */
50 static int init_random (void)
55 fd = open ("/dev/random", O_RDONLY);
62 read (fd, (void *) &r, sizeof (r));
68 } /* int init_random */
70 static int bounded_random (int upper_bound)
72 double r = ((double) rand ()) / ((double) RAND_MAX);
73 return ((int) (r * upper_bound));
76 static void exit_usage (const char *name)
78 printf ("Usage: %s [options]\n"
80 "Valid options are:\n"
81 " -i <file> Initial input file (REQUIRED)\n"
82 " -o <file> Write the current best solution to <file>\n"
83 " -p <num> Size of the population (default: 128)\n"
84 " -P <num> Size of the \"olymp\" (default: 96)\n"
88 } /* void exit_usage */
90 int read_options (int argc, char **argv)
94 while ((option = getopt (argc, argv, "i:o:p:P:s:h")) != -1)
100 if (initial_input_file != NULL)
101 free (initial_input_file);
102 initial_input_file = strdup (optarg);
108 if (best_output_file != NULL)
109 free (best_output_file);
110 best_output_file = strdup (optarg);
116 int tmp = atoi (optarg);
118 max_population_size = tmp;
124 int tmp = atoi (optarg);
132 int tmp = atoi (optarg);
134 stats_interval = tmp;
140 exit_usage (argv[0]);
145 } /* int read_options */
147 static int rate_network (const sn_network_t *n)
152 rate = SN_NETWORK_STAGE_NUM (n) * SN_NETWORK_INPUT_NUM (n);
153 for (i = 0; i < SN_NETWORK_STAGE_NUM (n); i++)
155 sn_stage_t *s = SN_NETWORK_STAGE_GET (n, i);
156 rate += SN_STAGE_COMP_NUM (s);
160 } /* int rate_network */
162 static int population_print_stats (int iterations)
168 for (i = 0; i < population_size; i++)
170 if ((best == -1) || (best > population[i].rating))
171 best = population[i].rating;
172 total += population[i].rating;
175 printf ("Iterations: %6i; Best: %i; Average: %.2f;\n",
176 iterations, best, ((double) total) / ((double) population_size));
179 } /* int population_print_stats */
181 static int insert_into_population (sn_network_t *n)
190 rating = rate_network (n);
192 if (population_size < max_population_size)
194 population[population_size].network = n;
195 population[population_size].rating = rating;
203 for (i = 0; i < olymp_size; i++)
205 if (population[i].rating > worst_rating)
207 worst_rating = population[i].rating;
210 if ((population[i].rating < best_rating)
211 || (best_rating == -1))
212 best_rating = population[i].rating;
215 if (rating < best_rating)
217 if (best_output_file != NULL)
219 printf ("Writing network with rating %i to %s\n",
220 rating, best_output_file);
221 sn_network_write_file (n, best_output_file);
225 printf ("New best solution has rating %i\n",
230 nmemb = max_population_size - (worst_index + 1);
232 sn_network_destroy (population[worst_index].network);
233 population[worst_index].network = NULL;
235 memmove (population + worst_index,
236 population + (worst_index + 1),
237 nmemb * sizeof (population_entry_t));
239 population[max_population_size - 1].network = n;
240 population[max_population_size - 1].rating = rating;
243 } /* int insert_into_population */
245 static int create_offspring (void)
251 p0 = bounded_random (population_size);
252 p1 = bounded_random (population_size);
254 n = sn_network_combine (population[p0].network, population[p1].network);
256 while (SN_NETWORK_INPUT_NUM (n) > inputs_num)
259 enum sn_network_cut_dir_e dir;
261 pos = bounded_random (SN_NETWORK_INPUT_NUM (n));
262 dir = (bounded_random (2) == 0) ? DIR_MIN : DIR_MAX;
264 assert ((pos >= 0) && (pos < SN_NETWORK_INPUT_NUM (n)));
266 sn_network_cut_at (n, pos, dir);
269 sn_network_compress (n);
271 assert (SN_NETWORK_INPUT_NUM (n) == inputs_num);
273 insert_into_population (n);
276 } /* int create_offspring */
278 static int start_evolution (void)
287 i = iteration_counter;
289 if ((stats_interval > 0) && ((i % stats_interval) == 0))
290 population_print_stats (i);
294 } /* int start_evolution */
296 int main (int argc, char **argv)
298 struct sigaction sigint_action;
300 read_options (argc, argv);
301 if (initial_input_file == NULL)
302 exit_usage (argv[0]);
306 memset (&sigint_action, '\0', sizeof (sigint_action));
307 sigint_action.sa_handler = sigint_handler;
308 sigaction (SIGINT, &sigint_action, NULL);
310 population = (population_entry_t *) malloc (max_population_size
311 * sizeof (population_entry_t));
312 if (population == NULL)
314 printf ("Malloc failed.\n");
317 memset (population, '\0', max_population_size
318 * sizeof (population_entry_t));
321 sn_network_t *n = sn_network_read_file (initial_input_file);
324 printf ("n == NULL\n");
327 population[0].network = n;
328 population[0].rating = rate_network (n);
331 inputs_num = SN_NETWORK_INPUT_NUM(n);
334 printf ("Current configuration:\n"
335 " Initial network: %s\n"
336 " Number of inputs: %3i\n"
337 " Population size: %3i\n"
339 "=======================\n",
340 initial_input_file, inputs_num, max_population_size, olymp_size);
344 printf ("Exiting after %llu iterations.\n", iteration_counter);
346 if (best_output_file == NULL)
352 for (i = 0; i < population_size; i++)
354 if ((best_rate == -1) || (best_rate > population[i].rating))
356 best_rate = population[i].rating;
361 sn_network_show (population[best_index].network);
367 for (i = 0; i < population_size; i++)
369 sn_network_destroy (population[i].network);
370 population[i].network = NULL;
380 /* vim: set shiftwidth=2 softtabstop=2 : */