X-Git-Url: https://git.verplant.org/?a=blobdiff_plain;f=src%2Fsn-evolution.c;h=86bdfba7cd292d0a394a143da939ebb834237d70;hb=79789cfc25a65312d8b91000abc7eb9209322555;hp=946c6fb95ffe81c2bc48905ad926cee1c6c15fc1;hpb=3d20efb01212f0a989d4162ba4a8fce897cca979;p=sort-networks.git diff --git a/src/sn-evolution.c b/src/sn-evolution.c index 946c6fb..86bdfba 100644 --- a/src/sn-evolution.c +++ b/src/sn-evolution.c @@ -1,6 +1,6 @@ /** * collectd - src/sn-evolution.c - * Copyright (C) 2008 Florian octo Forster + * Copyright (C) 2008,2009 Florian octo Forster * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -41,8 +41,9 @@ #include +#include + #include "sn_network.h" -#include "sn_population.h" #include "sn_random.h" /* Yes, this is ugly, but the GNU libc doesn't export it with the above flags. @@ -51,6 +52,7 @@ char *strdup (const char *s); static uint64_t iteration_counter = 0; static int inputs_num = 16; +static int inputs_num_is_power_of_two = 1; static char *initial_input_file = NULL; static char *best_output_file = NULL; @@ -58,7 +60,9 @@ static char *best_output_file = NULL; static int stats_interval = 0; static int max_population_size = 128; -static sn_population_t *population; +static population_t *population; + +static int evolution_threads_num = 4; static int do_loop = 0; @@ -75,6 +79,8 @@ static void exit_usage (const char *name) " -i Initial input file (REQUIRED)\n" " -o Write the current best solution to \n" " -p Size of the population (default: 128)\n" + " -P Send individuals to (may be repeated)\n" + " -t Number of threads (default: 4)\n" "\n", name); exit (1); @@ -84,7 +90,7 @@ int read_options (int argc, char **argv) { int option; - while ((option = getopt (argc, argv, "i:o:p:P:s:h")) != -1) + while ((option = getopt (argc, argv, "i:o:p:P:s:t:h")) != -1) { switch (option) { @@ -108,7 +114,23 @@ int read_options (int argc, char **argv) { int tmp = atoi (optarg); if (tmp > 0) + { max_population_size = tmp; + population_set_size (population, (size_t) max_population_size); + } + break; + } + + case 'P': + { + int status; + + status = population_add_peer (population, optarg, /* port = */ NULL); + if (status != 0) + { + fprintf (stderr, "population_add_peer failed with status %i.\n", + status); + } break; } @@ -120,6 +142,14 @@ int read_options (int argc, char **argv) break; } + case 't': + { + int tmp = atoi (optarg); + if (tmp >= 1) + evolution_threads_num = tmp; + break; + } + case 'h': default: exit_usage (argv[0]); @@ -129,6 +159,21 @@ int read_options (int argc, char **argv) return (0); } /* int read_options */ +static int rate_network (const sn_network_t *n) +{ + int rate; + int i; + + rate = SN_NETWORK_STAGE_NUM (n) * SN_NETWORK_INPUT_NUM (n); + for (i = 0; i < SN_NETWORK_STAGE_NUM (n); i++) + { + sn_stage_t *s = SN_NETWORK_STAGE_GET (n, i); + rate += SN_STAGE_COMP_NUM (s); + } + + return (rate); +} /* int rate_network */ + static int mutate_network (sn_network_t *n) { sn_network_t *n_copy; @@ -173,14 +218,14 @@ static int create_offspring (void) sn_network_t *p1; sn_network_t *n; - p0 = sn_population_pop (population); - p1 = sn_population_pop (population); + p0 = population_get_random (population); + p1 = population_get_random (population); assert (p0 != NULL); assert (p1 != NULL); /* combine the two parents */ - n = sn_network_combine (p0, p1); + n = sn_network_combine (p0, p1, inputs_num_is_power_of_two); sn_network_destroy (p0); sn_network_destroy (p1); @@ -204,10 +249,10 @@ static int create_offspring (void) assert (SN_NETWORK_INPUT_NUM (n) == inputs_num); - if (sn_bounded_random (0, 100) <= 1) + if ((SN_NETWORK_INPUT_NUM (n) <= 16) && (sn_bounded_random (0, 100) <= 1)) mutate_network (n); - sn_population_push (population, n); + population_insert (population, n); sn_network_destroy (n); @@ -253,11 +298,33 @@ static int evolution_start (int threads_num) status = sleep (1); if (status == 0) { - int best_rating; - i = iteration_counter; + sn_network_t *n; + int stages_num; + int comparators_num; + int rating; + int iter; + + iter = iteration_counter; + + n = population_get_fittest (population); + + rating = rate_network (n); + + stages_num = SN_NETWORK_STAGE_NUM (n); + comparators_num = 0; + for (i = 0; i < stages_num; i++) + { + sn_stage_t *s; + + s = SN_NETWORK_STAGE_GET (n, i); + comparators_num += SN_STAGE_COMP_NUM (s); + } - best_rating = sn_population_best_rating (population); - printf ("After approximately %i iterations: Currently best rating: %i\n", i, best_rating); + sn_network_destroy (n); + + printf ("Best after approximately %i iterations: " + "%i comparators in %i stages. Rating: %i.\n", + iter, comparators_num, stages_num, rating); } } @@ -274,6 +341,20 @@ static int evolution_start (int threads_num) int main (int argc, char **argv) { struct sigaction sigint_action; + struct sigaction sigterm_action; + + population = population_create ((pi_rate_f) rate_network, + (pi_copy_f) sn_network_clone, + (pi_free_f) sn_network_destroy); + if (population == NULL) + { + fprintf (stderr, "population_create failed.\n"); + return (1); + } + + population_set_serialization (population, + (pi_serialize_f) sn_network_serialize, + (pi_unserialize_f) sn_network_unserialize); read_options (argc, argv); if (initial_input_file == NULL) @@ -283,15 +364,15 @@ int main (int argc, char **argv) sigint_action.sa_handler = sigint_handler; sigaction (SIGINT, &sigint_action, NULL); - population = sn_population_create (max_population_size); - if (population == NULL) - { - fprintf (stderr, "sn_population_create failed.\n"); - return (1); - } + memset (&sigterm_action, '\0', sizeof (sigterm_action)); + sigterm_action.sa_handler = sigint_handler; + sigaction (SIGTERM, &sigterm_action, NULL); + + population_start_listen_thread (population, NULL, NULL); { sn_network_t *n; + int tmp; n = sn_network_read_file (initial_input_file); if (n == NULL) @@ -302,7 +383,24 @@ int main (int argc, char **argv) inputs_num = SN_NETWORK_INPUT_NUM(n); - sn_population_push (population, n); + /* Determine if `inputs_num' is a power of two. If so, more merge + * algorithms can be used. */ + tmp = inputs_num; + inputs_num_is_power_of_two = 1; + while (tmp > 0) + { + if ((tmp % 2) != 0) + { + if (tmp == 1) + inputs_num_is_power_of_two = 1; + else + inputs_num_is_power_of_two = 0; + break; + } + tmp = tmp >> 1; + } + + population_insert (population, n); sn_network_destroy (n); } @@ -313,7 +411,7 @@ int main (int argc, char **argv) "=======================\n", initial_input_file, inputs_num, max_population_size); - evolution_start (3); + evolution_start (evolution_threads_num); printf ("Exiting after %llu iterations.\n", (unsigned long long) iteration_counter); @@ -321,18 +419,17 @@ int main (int argc, char **argv) { sn_network_t *n; - n = sn_population_best (population); + n = population_get_fittest (population); if (n != NULL) { if (best_output_file != NULL) sn_network_write_file (n, best_output_file); - else - sn_network_show (n); + sn_network_show (n); sn_network_destroy (n); } } - sn_population_destroy (population); + population_destroy (population); return (0); } /* int main */