<HTML>
<HEAD>
<TITLE>
lil-gp Bug Patches
</TITLE>
</HEAD>
<BODY bgcolor=white>
<H1> lil-gp Bug Patches</h1>
<p> I have identified two chief bugs in lil-gpl 1.1 beta while working in multi-threaded mode.  Until they are resolved, here are (ugly) patches to the code which should work nicely.

<a href="http://www.daimi.aau.dk/~ptr/">Peter Anderson</a> has also identified a bug in lilgp's ERC facility; I've not verified this bug, but his patch is located <a href="peters-patch.html">here</a>.

<h2>The Tree Evaluation Facility</h2>
<p> This appears to be a <b>very</b> serious bug; all the function <tt>set_current_individual()</tt> does is modify a global static pointer.  This creates a very dangerous race condition when individuals are being evaluated simultaneously.  The patch is to move this global variable into the thread-safe globaldata structure.  This means you will have to first add to your <b>globaldata</b> structure the line...

<p><tt>individual* current_individual;</tt>

<p>You should not access this line in your evaluation code, even though it's in the globaldata structure.  Once this line has been added, follow the following patch instructions.

<p><b>Open the file <tt>eval.c</tt>.  Change the passage...</b>

<P><pre><tt>
static individual * current_individual;

void set_current_individual ( individual *ind )
{
  current_individual = ind;
}
</tt></pre>

<p><b>...to...</b>

<p><pre><tt>
#if !defined(POSIX_MT) && !defined(SOLARIS_MT)
static individual * current_individual;
#define CURRENT_INDIVIDUAL current_individual
#else
#define CURRENT_INDIVIDUAL ((get_globaldata())->current_individual)
#endif

void set_current_individual ( individual *ind )
{
  CURRENT_INDIVIDUAL = ind;
}
</tt></pre>

<p><b>...next, there are THREE passages you'll need to change.  They're all identical.  All three times it occurs, change...</b>

<p><pre><tt>
arg->d = evaluate_tree ( current_individual->tr[f->evaltree].data,
                        f->evaltree );
</tt></pre>

<p><b>...to...</b>

<p><pre><tt>
arg->d = evaluate_tree ( CURRENT_INDIVIDUAL->tr[f->evaltree].data,
                        f->evaltree );
</tt></pre>


<h2>The Random Facility</h2>
<p> lil-gp's random facility is not threadsafe and cannot be called from your evaluation code in multi-threaded mode without some patching.   The patch for this wraps the random facility in a mutex so only one thread can call the random function at a time. Assuming threads aren't re-seeing the generator, the only function that needs to be wrapped is <tt>random_double()</tt> because the other random functions operate on it.    <b>Note that this patch only works for POSIX Threads</b>.  You'll have to code your own Solaris Threads patch, sorry.  Here are the patch instructions.

<p><b>First open <tt>main.c</tt>, and change the passage</b>

<P><pre><tt>
/* maximum number of nodes per individual.  -1 if no limit is
   enforced. */
int ind_nodelimit;

int main ( int argc, char **argv )
{

     multipop *mpop;
     int startgen;
     char *param;
     event start, end, diff;
     event eval, breed;
     int startfromcheckpoint;

#ifdef MEMORY_LOG
     /* dump all memory allocations to a file. */
     mlog = fopen ( "memory.log", "w" );
#endif
</tt></pre>

<p> <b>...to...</b>

<p><pre><tt>
/* maximum number of nodes per individual.  -1 if no limit is
   enforced. */
int ind_nodelimit;

extern pthread_mutex_t random_mutex;  /* Mutexes the random code */

int main ( int argc, char **argv )
{

     multipop *mpop;
     int startgen;
     char *param;
     event start, end, diff;
     event eval, breed;
     int startfromcheckpoint;

     pthread_mutex_init(&random_mutex,NULL); /* Initialize the random mutex */

#ifdef MEMORY_LOG
     /* dump all memory allocations to a file. */
     mlog = fopen ( "memory.log", "w" );
#endif
</tt></pre>

<p><b> Then modify the passage (at the end of <tt>main()</tt>)...</b>

<p><pre><tt>
     /* print memory/time statistics and close output files. */
     output_system_stats ( &diff, &eval, &breed );
     close_output_streams();

#ifdef MEMORY_LOG
     fclose ( mlog );
#endif

     /* all done. */
     return 0;
}
</tt></pre>

<p><b>...to...</b>

<p><pre><tt>
     /* print memory/time statistics and close output files. */
     output_system_stats ( &diff, &eval, &breed );
     close_output_streams();

#ifdef MEMORY_LOG
     fclose ( mlog );
#endif

     pthread_mutex_destroy(&random_mutex);  /* Destroy random mutex */

     /* all done. */
     return 0;
}
</tt></pre>


<p><b> Next, open the file <tt>random.c</tt> Change the passage </b>


<p><pre><tt>
static double mz = 0.0;
static double ma[55];       /* the number 55 is special -- see Knuth. */
static int inext, inextp;
</tt></pre>

<p><b> ...to...</b>

<p><pre><tt>
static double mz = 0.0;
static double ma[55];       /* the number 55 is special -- see Knuth. */
static int inext, inextp;

pthread_mutex_t random_mutex;
</tt></pre>

<p><b> and change the function...</b>

<p><pre><tt>
double random_double ( void )
{

     double mj;
     double res;

     inext = (inext+1)%55;
     inextp = (inextp+1)%55;
     
     mj = ma[inext] - ma[inextp];
     if ( mj < mz )
          mj = mj + mbig;
     ma[inext] = mj;

     res=mbig;

     return mj/res;
}
</tt></pre>

<p><b> ...to...</b>

<p><pre><tt>
double random_double ( void )
{
  /* There's a race condition on this, so we need to mutex it! */

     double mj;
     double res;

     pthread_mutex_lock(&random_mutex);

     inext = (inext+1)%55;
     inextp = (inextp+1)%55;
     
     mj = ma[inext] - ma[inextp];
     if ( mj < mz )
          mj = mj + mbig;
     ma[inext] = mj;

     res=mbig;

     pthread_mutex_unlock(&random_mutex);
     return mj/res;
}
</tt></pre>


</BODY>
</HTML>