population_set_replacement_method: New function.
[libpopulation.git] / src / libpopulation.c
index 26345f8..c27fd9b 100644 (file)
@@ -1,6 +1,6 @@
 /**
- * libevolve - src/evolve.c
- * Copyright (C) 2008 Florian octo Forster
+ * libpopulation - src/evolve.c
+ * 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
@@ -107,6 +107,7 @@ struct population_s
 
 #define POPULATION_FLAG_LISTEN   0x01
 #define POPULATION_FLAG_SHUTDOWN 0x02
+#define POPULATION_FLAG_EXPLORE  0x10
   int flags;
   pthread_t listen_thread_id;
 
@@ -489,6 +490,27 @@ int population_set_serialization (population_t *p, /* {{{ */
   return (0);
 } /* }}} int population_set_serialization */
 
+int population_set_replacement_method (population_t *p, int method) /* {{{ */
+{
+  int status = 0;
+
+  if (p == NULL)
+    return (EINVAL);
+
+  pthread_mutex_lock (&p->lock);
+
+  if (method == POPULATION_REPLACEMENT_EXPLOIT)
+    p->flags &= ~POPULATION_FLAG_EXPLORE;
+  else if (method == POPULATION_REPLACEMENT_EXPLORE)
+    p->flags |= POPULATION_FLAG_EXPLORE;
+  else
+    status = EINVAL;
+
+  pthread_mutex_unlock (&p->lock);
+
+  return (0);
+} /* }}} int population_set_replacement_method */
+
 int population_add_peer (population_t *p, const char *node, /* {{{ */
     const char *port)
 {
@@ -659,7 +681,7 @@ int population_insert (population_t *p, void *pi_orig) /* {{{ */
 {
   void *pi;
   int pi_rating;
-  int num_tries;
+  int sent_to_peer;
   int i;
 
   if (p == NULL)
@@ -675,6 +697,25 @@ int population_insert (population_t *p, void *pi_orig) /* {{{ */
     return (-1);
   }
 
+  /*
+   * With a small chance, send this individual to somewhere else.
+   * `sent_to_peer = -1' is used to signal the following code that this
+   * individual has been sent to somewhere else and doesn't go into the local
+   * population.
+   */
+  sent_to_peer = 0;
+  if (p->peers_num > 0)
+  {
+    double prob;
+
+    prob = ((double) rand ()) / (((double) RAND_MAX) + 1.0);
+    if (prob <= 0.001)
+    {
+      population_send_to_peer (p, pi);
+      sent_to_peer = 1;
+    }
+  }
+
   pi_rating = p->rate (pi);
 
   pthread_mutex_lock (&p->lock);
@@ -694,11 +735,11 @@ int population_insert (population_t *p, void *pi_orig) /* {{{ */
     }
   }
 
-  if (p->individuals_num <= 0)
+  if ((sent_to_peer != 0) || (p->individuals_num <= 0))
   {
     pthread_mutex_unlock (&p->lock);
     p->free (pi);
-    return (-1);
+    return (0);
   }
 
   do
@@ -728,6 +769,10 @@ int population_insert (population_t *p, void *pi_orig) /* {{{ */
 
     chance = (int) (((double) (chance_j + chance_pi))
         * (rand() / (RAND_MAX + 1.0)));
+
+    if (p->flags & POPULATION_FLAG_EXPLORE)
+      chance *= .5;
+
     if (chance < chance_j) /* j looses ;) */
     {
       void *temp0;
@@ -746,33 +791,7 @@ int population_insert (population_t *p, void *pi_orig) /* {{{ */
   pthread_mutex_unlock (&p->lock);
 
   if (pi != NULL)
-  {
     p->free (pi);
-    pi = NULL;
-  }
-
-  while (p->peers_num > 0)
-  {
-    double prob;
-    size_t j;
-    void *pi;
-
-    prob = ((double) rand ()) / (((double) RAND_MAX) + 1.0);
-    if (prob < 0.999)
-      break;
-
-    pi = population_get_random (p);
-    if (pi == NULL)
-    {
-      fprintf (stderr, "population_insert: population_get_random failed.\n");
-      break;
-    }
-
-    population_send_to_peer (p, pi);
-    p->free (pi);
-
-    break;
-  }
 
   return (0);
 } /* }}} int population_insert */