Request X/Open 7 rather than declaring strdup ourselves.
[sort-networks.git] / src / sn-evolution2.c
index b5beca4..2f894ec 100644 (file)
@@ -1,6 +1,6 @@
 /**
- * collectd - src/sn-evolution.c
- * Copyright (C) 2008,2009  Florian octo Forster
+ * libsortnetwork - src/sn-evolution.c
+ * Copyright (C) 2008-2010  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
  * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
  *
  * Authors:
- *   Florian octo Forster <octo at verplant.org>
+ *   Florian octo Forster <ff at octo.it>
  **/
 
 #ifndef _ISOC99_SOURCE
 # define _ISOC99_SOURCE
 #endif
 #ifndef _POSIX_C_SOURCE
-# define _POSIX_C_SOURCE 200112L
+# define _POSIX_C_SOURCE 200809L
+#endif
+#ifndef _XOPEN_SOURCE
+# define _XOPEN_SOURCE 700
 #endif
 
 #include <stdlib.h>
@@ -39,6 +42,8 @@
 #include <assert.h>
 #include <limits.h>
 
+#include <math.h>
+
 #include <pthread.h>
 
 #include <population.h>
 #include "sn_network.h"
 #include "sn_random.h"
 
+#if !defined(__GNUC__) || !__GNUC__
+# define __attribute__(x) /**/
+#endif
+
 #define SNE_MIN(a,b) ((a) < (b) ? (a) : (b))
 #define SNE_MAX(a,b) ((a) > (b) ? (a) : (b))
 
-/* Yes, this is ugly, but the GNU libc doesn't export it with the above flags.
- * */
-char *strdup (const char *s);
-
 static uint64_t iteration_counter = 0;
 static int inputs_num = -1;
 
 static int comparators_num = -1;
 
+static char *initial_input_file = NULL;
 static char *best_output_file = NULL;
 
 static int stats_interval = 0;
@@ -69,7 +75,11 @@ static int evolution_threads_num = 4;
 
 static int do_loop = 0;
 
-static void sigint_handler (int signal)
+static int weight_overall = 50;
+static int weight_fails = 2;
+static int weight_stages = 1;
+
+static void sigint_handler (__attribute__((unused)) int signal)
 {
   do_loop++;
 } /* void sigint_handler */
@@ -81,6 +91,7 @@ static void exit_usage (const char *name)
       "Valid options are:\n"
       "  -i <inputs>       Number of inputs\n"
       "  -c <comparators>  Number of comparators\n"
+      "  -I <file>         Initial input file\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"
@@ -94,7 +105,7 @@ int read_options (int argc, char **argv)
 {
   int option;
 
-  while ((option = getopt (argc, argv, "i:c:o:p:P:s:t:h")) != -1)
+  while ((option = getopt (argc, argv, "i:c:I:o:p:P:s:t:h")) != -1)
   {
     switch (option)
     {
@@ -116,6 +127,14 @@ int read_options (int argc, char **argv)
        break;
       }
 
+      case 'I':
+      {
+       if (initial_input_file != NULL)
+         free (initial_input_file);
+       initial_input_file = strdup (optarg);
+       break;
+      }
+
       case 'o':
       {
        if (best_output_file != NULL)
@@ -235,7 +254,7 @@ static int rate_network (sn_network_t *n) /* {{{ */
   } /* while (42) */
 
   /* All tests successfull */
-  return (SN_NETWORK_STAGE_NUM (n) + patterns_failed);
+  return (weight_overall + (weight_stages * SN_NETWORK_STAGE_NUM (n)) + (weight_fails * patterns_failed));
 } /* }}} int rate_network */
 
 static sn_comparator_t get_random_comparator (void) /* {{{ */
@@ -252,10 +271,21 @@ static sn_comparator_t get_random_comparator (void) /* {{{ */
 
 static int mutate_network (sn_comparator_t *comparators, int comparators_num)
 {
+  static int old_comparators_num = -1;
+  static double mutate_probability = 0.0;
+
   int i;
 
+  if (old_comparators_num != comparators_num)
+  {
+    /* Probability that NO mutation takes place: 1/3 */
+    mutate_probability = powl (1.0 / 3.0, (1.0 / ((double) comparators_num)));
+    old_comparators_num = comparators_num;
+  }
+
+  /* `mutate_probability' actually holds 1-p, i. e. it is close to one */
   for (i = 0; i < comparators_num; i++)
-    if (sn_bounded_random (0, 1000) == 0)
+    if (sn_double_random () >= mutate_probability)
       comparators[i] = get_random_comparator ();
 
   return (0);
@@ -349,8 +379,7 @@ static int create_offspring (void)
 
   }
 
-  if (sn_bounded_random (0, 1000) == 0)
-    mutate_network (n_comparators, n_comparators_num);
+  mutate_network (n_comparators, n_comparators_num);
 
   n = sn_network_create (inputs_num);
   for (i = 0; i < n_comparators_num; i++)
@@ -368,7 +397,7 @@ static int create_offspring (void)
   return (0);
 } /* int create_offspring */
 
-static void *evolution_thread (void *arg)
+static void *evolution_thread (__attribute__((unused)) void *arg)
 {
   while (do_loop == 0)
   {
@@ -434,7 +463,7 @@ static int evolution_start (int threads_num)
       printf ("Best after approximately %i iterations: "
          "%i comparators in %i stages. Rating: %i (%i not sorted).\n",
          iter, comparators_num, stages_num, rating,
-         rating - stages_num);
+         (rating - (weight_overall + (weight_stages * stages_num))) / weight_fails);
     }
   }
 
@@ -481,6 +510,30 @@ int main (int argc, char **argv)
 
   population_start_listen_thread (population, NULL, NULL);
 
+  if (initial_input_file != NULL)
+  {
+    sn_network_t *n;
+
+    n = sn_network_read_file (initial_input_file);
+    if (n == NULL)
+    {
+      fprintf (stderr, "Cannot read network from `%s'.\n",
+         initial_input_file);
+      exit (EXIT_FAILURE);
+    }
+
+    if (n->inputs_num != inputs_num)
+    {
+      fprintf (stderr, "Network `%s' has %i inputs, but %i were configured "
+         "on the command line.\n",
+         initial_input_file, n->inputs_num, inputs_num);
+      exit (EXIT_FAILURE);
+    }
+
+    population_insert (population, n);
+    sn_network_destroy (n);
+  }
+  else /* if (initial_input_file == NULL) */
   {
     sn_network_t *n;
     int i;