From: Florian Forster Date: Fri, 1 Feb 2008 18:30:56 +0000 (+0100) Subject: src/sn-evolution.c: Added a first version of evolutionary optimization. X-Git-Tag: v1.0.0~124 X-Git-Url: https://git.verplant.org/?a=commitdiff_plain;h=a09322850b6ef3ca305bb7b43bd52416375ae9c1;p=sort-networks.git src/sn-evolution.c: Added a first version of evolutionary optimization. --- diff --git a/src/Makefile b/src/Makefile index bff684f..4cf6a22 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,7 +1,8 @@ CC = gcc -CFLAGS = -Wall -Werror -std=c99 -O3 +#CFLAGS = -Wall -Werror -std=c99 -O3 +CFLAGS = -Wall -Werror -std=c99 -O0 -g -all: sn-cut sn-merge sn-show +all: sn-cut sn-evolution sn-merge sn-show sn_comparator.o: sn_comparator.c sn_comparator.h @@ -11,6 +12,8 @@ sn_network.o: sn_network.c sn_network.h sn_stage.h sn_comparator.h sn-cut: sn-cut.c sn_network.o sn_stage.o sn_comparator.o +sn-evolution: sn-evolution.c sn_network.o sn_stage.o sn_comparator.o + sn-merge: sn-merge.c sn_network.o sn_stage.o sn_comparator.o sn-show: sn-show.c sn_network.o sn_stage.o sn_comparator.o diff --git a/src/sn-evolution.c b/src/sn-evolution.c new file mode 100644 index 0000000..4638b37 --- /dev/null +++ b/src/sn-evolution.c @@ -0,0 +1,213 @@ +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "sn_network.h" + +struct population_entry_s +{ + sn_network_t *network; + int rating; +}; +typedef struct population_entry_s population_entry_t; + +static int iterations_num = 10000; +static int max_population_size = 64; +static int inputs_num = 16; + +static population_entry_t *population = NULL; +int population_size = 0; + +static int init_random (void) +{ + int fd; + unsigned int r; + + fd = open ("/dev/random", O_RDONLY); + if (fd < 0) + { + perror ("open"); + return (-1); + } + + read (fd, (void *) &r, sizeof (r)); + close (fd); + + srand (r); + + return (0); +} /* int init_random */ + +static int bounded_random (int upper_bound) +{ + double r = ((double) rand ()) / ((double) RAND_MAX); + return ((int) (r * upper_bound)); +} + +static void exit_usage (const char *name) +{ + printf ("%s \n", name); + exit (1); +} /* void exit_usage */ + +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 population_print_stats (int iterations) +{ + int best = -1; + int total = 0; + int i; + + for (i = 0; i < population_size; i++) + { + if ((best == -1) || (best > population[i].rating)) + best = population[i].rating; + total += population[i].rating; + } + + printf ("Iterations: %6i; Best: %i; Average: %.2f;\n", + iterations, best, ((double) total) / ((double) population_size)); + + return (0); +} /* int population_print_stats */ + +static int insert_into_population (sn_network_t *n) +{ + int rating; + int i; + + rating = rate_network (n); + + if (population_size < max_population_size) + { + population[population_size].network = n; + population[population_size].rating = rating; + population_size++; + return (0); + } + + for (i = 0; i < population_size; i++) + if (population[i].rating > rating) + break; + + if (i < population_size) + { + sn_network_destroy (population[i].network); + population[i].network = n; + population[i].rating = rating; + } + else + { + sn_network_destroy (n); + } + + return (0); +} /* int insert_into_population */ + +static int create_offspring (void) +{ + int p0; + int p1; + sn_network_t *n; + + p0 = bounded_random (population_size); + p1 = bounded_random (population_size); + + n = sn_network_combine (population[p0].network, population[p1].network); + + while (SN_NETWORK_INPUT_NUM (n) > inputs_num) + { + int pos; + enum sn_network_cut_dir_e dir; + + pos = bounded_random (SN_NETWORK_INPUT_NUM (n)); + dir = (bounded_random (2) == 0) ? DIR_MIN : DIR_MAX; + + assert ((pos >= 0) && (pos < SN_NETWORK_INPUT_NUM (n))); + + sn_network_cut_at (n, pos, dir); + } + + insert_into_population (n); + + return (0); +} /* int create_offspring */ + +static int start_evolution (void) +{ + int i; + + for (i = 0; i < iterations_num; i++) + { + if ((i % 100) == 0) + population_print_stats (i); + + create_offspring (); + } + + return (0); +} /* int start_evolution */ + +int main (int argc, char **argv) +{ + if (argc != 2) + exit_usage (argv[0]); + + init_random (); + + population = (population_entry_t *) malloc (max_population_size + * sizeof (population_entry_t)); + if (population == NULL) + { + printf ("Malloc failed.\n"); + return (-1); + } + memset (population, '\0', max_population_size + * sizeof (population_entry_t)); + + { + sn_network_t *n = sn_network_read_file (argv[1]); + if (n == NULL) + { + printf ("n == NULL\n"); + return (1); + } + population[0].network = n; + population[0].rating = rate_network (n); + population_size++; + } + + start_evolution (); + + if (0) { + int i; + for (i = 0; i < population_size; i++) + { + sn_network_show (population[i].network); + printf ("=============\n"); + } + } + + return (0); +} /* int main */ + +/* vim: set shiftwidth=2 softtabstop=2 : */ diff --git a/src/sn_network.c b/src/sn_network.c index 07d811d..3934e91 100644 --- a/src/sn_network.c +++ b/src/sn_network.c @@ -73,11 +73,19 @@ int sn_network_stage_remove (sn_network_t *n, int s_num) n->stages_num--; /* Free the unused memory */ - temp = (sn_stage_t **) realloc (n->stages, - n->stages_num * sizeof (sn_stage_t *)); - if (temp == NULL) - return (-1); - n->stages = temp; + if (n->stages_num == 0) + { + free (n->stages); + n->stages = NULL; + } + else + { + temp = (sn_stage_t **) realloc (n->stages, + n->stages_num * sizeof (sn_stage_t *)); + if (temp == NULL) + return (-1); + n->stages = temp; + } return (0); } /* int sn_network_stage_remove */ @@ -145,6 +153,10 @@ int sn_network_compress (sn_network_t *n) } } + while ((n->stages_num > 0) + && (SN_STAGE_COMP_NUM (n->stages[n->stages_num - 1]) == 0)) + sn_network_stage_remove (n, n->stages_num - 1); + return (0); } /* int sn_network_compress */ @@ -175,7 +187,6 @@ int sn_network_cut_at (sn_network_t *n, int input, enum sn_network_cut_dir_e dir assert (((dir == DIR_MIN) && (position == 0)) || ((dir == DIR_MAX) && (position == (n->inputs_num - 1)))); - for (i = 0; i < n->stages_num; i++) sn_stage_remove_input (n->stages[i], position); diff --git a/src/sn_network.h b/src/sn_network.h index 7e13973..b960dc0 100644 --- a/src/sn_network.h +++ b/src/sn_network.h @@ -16,6 +16,7 @@ typedef struct sn_network_s sn_network_t; #define SN_NETWORK_STAGE_NUM(n) (n)->stages_num #define SN_NETWORK_STAGE_GET(n,i) ((n)->stages[i]) +#define SN_NETWORK_INPUT_NUM(n) (n)->inputs_num sn_network_t *sn_network_create (int inputs_num); void sn_network_destroy (sn_network_t *n); diff --git a/src/sn_stage.c b/src/sn_stage.c index 0cfabe9..f0d169d 100644 --- a/src/sn_stage.c +++ b/src/sn_stage.c @@ -64,6 +64,7 @@ int sn_stage_comparator_remove (sn_stage_t *s, int c_num) sn_comparator_t *temp; assert (c_num < s->comparators_num); + assert (c_num >= 0); if (nmemb > 0) memmove (s->comparators + c_num, s->comparators + (c_num + 1), @@ -71,11 +72,19 @@ int sn_stage_comparator_remove (sn_stage_t *s, int c_num) s->comparators_num--; /* Free the unused memory */ - temp = (sn_comparator_t *) realloc (s->comparators, - s->comparators_num * sizeof (sn_comparator_t)); - if (temp == NULL) - return (-1); - s->comparators = temp; + if (s->comparators_num == 0) + { + free (s->comparators); + s->comparators = NULL; + } + else + { + temp = (sn_comparator_t *) realloc (s->comparators, + s->comparators_num * sizeof (sn_comparator_t)); + if (temp == NULL) + return (-1); + s->comparators = temp; + } return (0); } /* int sn_stage_comparator_remove */