Merge branch 'ff/libpopulation'
authorFlorian Forster <octo@leeloo.home.verplant.org>
Sun, 13 Jul 2008 08:42:45 +0000 (10:42 +0200)
committerFlorian Forster <octo@leeloo.home.verplant.org>
Sun, 13 Jul 2008 08:42:45 +0000 (10:42 +0200)
src/Makefile
src/sn-evolution.c
src/sn_network.c
src/sn_network.h
src/sn_stage.c
src/sn_stage.h

index 4d351f7..516313f 100644 (file)
@@ -5,6 +5,10 @@ CFLAGS = -Wall -Werror -std=c99 -O3 -pthread
 APPLICATIONS = sn-apply sn-check-bf sn-cut sn-evolution sn-merge \
               sn-normalize sn-show sn-tex
 
+POPULATION_CFLAGS = -I/tmp/sifnfors/libpopulation/include
+
+POPULATION_LDFLAGS = -L/tmp/sifnfors/libpopulation/lib -Wl,--rpath -Wl,/tmp/sifnfors/libpopulation/lib -lpopulation
+
 all: $(APPLICATIONS)
 
 clean:
@@ -15,6 +19,7 @@ sn_comparator.o: sn_comparator.c sn_comparator.h
 
 sn_network.o: sn_network.c sn_network.h sn_stage.h sn_comparator.h sn_random.h
 
+sn_population.o: CFLAGS = $(POPULATION_CFLAGS)
 sn_population.o: sn_population.c sn_population.h sn_network.h sn_random.h
 
 sn_random.o: sn_random.c sn_random.h
@@ -28,6 +33,8 @@ sn-check-bf: sn-check-bf.c sn_network.o sn_stage.o sn_comparator.o sn_random.o
 
 sn-cut: sn-cut.c sn_network.o sn_stage.o sn_comparator.o sn_random.o
 
+sn-evolution: CFLAGS += $(POPULATION_CFLAGS)
+sn-evolution: LDFLAGS += $(POPULATION_LDFLAGS)
 sn-evolution: sn-evolution.c sn_network.o sn_stage.o sn_comparator.o sn_population.o sn_random.o
 
 sn-merge: sn-merge.c sn_network.o sn_stage.o sn_comparator.o sn_random.o
index d9190b6..3c11adb 100644 (file)
@@ -41,8 +41,9 @@
 
 #include <pthread.h>
 
+#include <population.h>
+
 #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.
@@ -58,7 +59,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 +78,8 @@ static void exit_usage (const char *name)
       "  -i <file>     Initial input file (REQUIRED)\n"
       "  -o <file>     Write the current best solution to <file>\n"
       "  -p <num>      Size of the population (default: 128)\n"
+      "  -P <peer>     Send individuals to <peer> (may be repeated)\n"
+      "  -t <num>      Number of threads (default: 4)\n"
       "\n",
       name);
   exit (1);
@@ -84,7 +89,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 +113,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 +141,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 +158,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,8 +217,8 @@ 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);
@@ -207,7 +251,7 @@ static int create_offspring (void)
   if (sn_bounded_random (0, 100) <= 1)
     mutate_network (n);
 
-  sn_population_push (population, n);
+  population_insert (population, n);
 
   sn_network_destroy (n);
 
@@ -253,11 +297,18 @@ static int evolution_start (int threads_num)
     status = sleep (1);
     if (status == 0)
     {
-      int best_rating;
+      sn_network_t *n;
+      int rating;
+
       i = iteration_counter;
 
-      best_rating = sn_population_best_rating (population);
-      printf ("After approximately %i iterations: Currently best rating: %i\n", i, best_rating);
+      n = population_get_fittest (population);
+      rating = rate_network (n);
+      sn_network_destroy (n);
+
+      printf ("After approximately %i iterations: "
+         "Currently best rating: %i\n",
+         i, rating);
     }
   }
 
@@ -276,6 +327,19 @@ 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)
     exit_usage (argv[0]);
@@ -288,12 +352,7 @@ int main (int argc, char **argv)
   sigterm_action.sa_handler = sigint_handler;
   sigaction (SIGTERM, &sigterm_action, NULL);
 
-  population = sn_population_create (max_population_size);
-  if (population == NULL)
-  {
-    fprintf (stderr, "sn_population_create failed.\n");
-    return (1);
-  }
+  population_start_listen_thread (population, NULL, NULL);
 
   {
     sn_network_t *n;
@@ -307,7 +366,7 @@ int main (int argc, char **argv)
 
     inputs_num = SN_NETWORK_INPUT_NUM(n);
 
-    sn_population_push (population, n);
+    population_insert (population, n);
     sn_network_destroy (n);
   }
 
@@ -318,7 +377,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);
@@ -326,18 +385,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 */
index 1cc2d06..bda2e81 100644 (file)
@@ -691,4 +691,115 @@ int sn_network_write_file (sn_network_t *n, const char *file)
   return (status);
 } /* int sn_network_write_file */
 
+int sn_network_serialize (sn_network_t *n, char **ret_buffer,
+    size_t *ret_buffer_size)
+{
+  char *buffer;
+  size_t buffer_size;
+  int status;
+  int i;
+
+  buffer = *ret_buffer;
+  buffer_size = *ret_buffer_size;
+
+#define SNPRINTF_OR_FAIL(...) \
+  status = snprintf (buffer, buffer_size, __VA_ARGS__); \
+  if ((status < 1) || (status >= buffer_size)) \
+    return (-1); \
+  buffer += status; \
+  buffer_size -= status;
+
+  SNPRINTF_OR_FAIL ("Inputs: %i\r\n\r\n", n->inputs_num);
+
+  for (i = 0; i < n->stages_num; i++)
+  {
+    status = sn_stage_serialize (n->stages[i], &buffer, &buffer_size);
+    if (status != 0)
+      return (status);
+  }
+
+  *ret_buffer = buffer;
+  *ret_buffer_size = buffer_size;
+  return (0);
+} /* int sn_network_serialize */
+
+sn_network_t *sn_network_unserialize (char *buffer, size_t buffer_size)
+{
+  sn_network_t *n;
+  int opt_inputs = 0;
+
+  if (buffer_size == 0)
+    return (NULL);
+
+  /* Read options first */
+  while (buffer_size > 0)
+  {
+    char *endptr;
+    char *str_key;
+    char *str_value;
+    char *line;
+    int   line_len;
+
+    line = buffer;
+    endptr = strchr (buffer, '\n');
+    if (endptr == NULL)
+      return (NULL);
+
+    *endptr = 0;
+    endptr++;
+    buffer = endptr;
+    line_len = strlen (line);
+
+    if ((line_len > 0) && (line[line_len - 1] == '\r'))
+    {
+      line[line_len - 1] = 0;
+      line_len--;
+    }
+
+    if (line_len == 0)
+      break;
+
+    str_key = line;
+    str_value = strchr (line, ':');
+    if (str_value == NULL)
+    {
+      printf ("Cannot parse line: %s\n", line);
+      continue;
+    }
+
+    *str_value = '\0'; str_value++;
+    while ((*str_value != '\0') && (isspace (*str_value) != 0))
+      str_value++;
+
+    if (strcasecmp ("Inputs", str_key) == 0)
+      opt_inputs = atoi (str_value);
+    else
+      printf ("Unknown key: %s\n", str_key);
+  } /* while (fgets) */
+
+  if (opt_inputs < 2)
+    return (NULL);
+
+  n = sn_network_create (opt_inputs);
+
+  while (42)
+  {
+    sn_stage_t *s;
+
+    s = sn_stage_unserialize (&buffer, &buffer_size);
+    if (s == NULL)
+      break;
+
+    sn_network_stage_add (n, s);
+  }
+
+  if (SN_NETWORK_STAGE_NUM (n) < 1)
+  {
+    sn_network_destroy (n);
+    return (NULL);
+  }
+
+  return (n);
+} /* sn_network_t *sn_network_unserialize */
+
 /* vim: set shiftwidth=2 softtabstop=2 : */
index 4bcd586..905097d 100644 (file)
@@ -62,6 +62,9 @@ sn_network_t *sn_network_read_file (const char *file);
 int sn_network_write (sn_network_t *n, FILE *fh);
 int sn_network_write_file (sn_network_t *n, const char *file);
 
+int sn_network_serialize (sn_network_t *n, char **ret_buffer,
+    size_t *ret_buffer_size);
+sn_network_t *sn_network_unserialize (char *buffer, size_t buffer_size);
 #endif /* SN_NETWORK_H */
 
 /* vim: set shiftwidth=2 softtabstop=2 : */
index bade6c4..3999851 100644 (file)
@@ -405,4 +405,122 @@ int sn_stage_write (sn_stage_t *s, FILE *fh)
   return (0);
 } /* int sn_stage_write */
 
-/* vim: set shiftwidth=2 softtabstop=2 : */
+int sn_stage_serialize (sn_stage_t *s,
+    char **ret_buffer, size_t *ret_buffer_size)
+{
+  char *buffer;
+  size_t buffer_size;
+  int status;
+  int i;
+
+  if (s->comparators_num <= 0)
+    return (0);
+
+  buffer = *ret_buffer;
+  buffer_size = *ret_buffer_size;
+
+#define SNPRINTF_OR_FAIL(...) \
+  status = snprintf (buffer, buffer_size, __VA_ARGS__); \
+  if ((status < 1) || (status >= buffer_size)) \
+    return (-1); \
+  buffer += status; \
+  buffer_size -= status;
+
+  for (i = 0; i < s->comparators_num; i++)
+  {
+    SNPRINTF_OR_FAIL ("%i %i\r\n",
+       SN_COMP_MIN (s->comparators + i),
+       SN_COMP_MAX (s->comparators + i));
+  }
+
+  SNPRINTF_OR_FAIL ("\r\n");
+
+  *ret_buffer = buffer;
+  *ret_buffer_size = buffer_size;
+  return (0);
+} /* int sn_stage_serialize */
+
+sn_stage_t *sn_stage_unserialize (char **ret_buffer, size_t *ret_buffer_size)
+{
+  sn_stage_t *s;
+  char *buffer;
+  size_t buffer_size;
+  int status;
+
+  buffer = *ret_buffer;
+  buffer_size = *ret_buffer_size;
+
+  if (buffer_size == 0)
+    return (NULL);
+
+  s = sn_stage_create (0);
+  if (s == NULL)
+    return (NULL);
+
+  status = 0;
+  while (buffer_size > 0)
+  {
+    sn_comparator_t c;
+    char *endptr;
+    char *substr;
+    size_t substr_length;
+
+    endptr = strchr (buffer, '\n');
+    if (endptr == NULL)
+    {
+      status = -1;
+      break;
+    }
+
+    *endptr = 0;
+    endptr++;
+
+    substr = buffer;
+    substr_length = strlen (buffer);
+    buffer = endptr;
+    buffer_size -= (substr_length + 1);
+
+    if ((substr_length > 0) && (substr[substr_length - 1] == '\r'))
+    {
+      substr[substr_length - 1] = 0;
+      substr_length--;
+    }
+
+    if (substr_length == 0)
+    {
+      status = 0;
+      break;
+    }
+
+    endptr = NULL;
+    c.min = (int) strtol (substr, &endptr, 0);
+    if (substr == endptr)
+    {
+      status = -1;
+      break;
+    }
+
+    substr = endptr;
+    endptr = NULL;
+    c.max = (int) strtol (substr, &endptr, 0);
+    if (substr == endptr)
+    {
+      status = -1;
+      break;
+    }
+
+    sn_stage_comparator_add (s, &c);
+  } /* while (buffer_size > 0) */
+
+  if ((status != 0) || (s->comparators_num == 0))
+  {
+    sn_stage_destroy (s);
+    return (NULL);
+  }
+
+  *ret_buffer = buffer;
+  *ret_buffer_size = buffer_size;
+  return (s);
+} /* sn_stage_t *sn_stage_unserialize */
+
+/* vim: set shiftwidth=2 softtabstop=2 expandtab : */
index e1cb898..e625de6 100644 (file)
@@ -63,6 +63,10 @@ int sn_stage_remove_input (sn_stage_t *s, int input);
 sn_stage_t *sn_stage_read (FILE *fh);
 int sn_stage_write (sn_stage_t *s, FILE *fh);
 
+int sn_stage_serialize (sn_stage_t *s,
+    char **ret_buffer, size_t *ret_buffer_size);
+sn_stage_t *sn_stage_unserialize (char **buffer, size_t *buffer_size);
+
 #endif /* SN_STAGE_H */
 
 /* vim: set shiftwidth=2 softtabstop=2 : */