COSC_4P82_Assignment_1/lib/lilgp/kernel_c/fitness.c

276 lines
7.9 KiB
C

/* lil-gp Genetic Programming System, version 1.0, 11 July 1995
* Copyright (C) 1995 Michigan State University
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Douglas Zongker (zongker@isl.cps.msu.edu)
* Dr. Bill Punch (punch@isl.cps.msu.edu)
*
* Computer Science Department
* A-714 Wells Hall
* Michigan State University
* East Lansing, Michigan 48824
* USA
*
*/
#include <lilgp.h>
/* select_afit_context()
*
* creates context for the fitness selection method.
*/
sel_context *select_afit_context ( int op, sel_context *sc, population *p,
char *string )
{
interval_data *id;
int i, j = 0;
switch ( op )
{
case SELECT_INIT:
sc = (sel_context *)MALLOC ( sizeof ( sel_context ) );
sc->p = p;
sc->select_method = select_interval;
sc->context_method = select_afit_context;
/* the interval_data structure (used with select_interval()) is
essentially a list of interval widths and indices for each
individual. */
id = (interval_data *)MALLOC ( sizeof ( interval_data ) );
id->ri = (reverse_index *)MALLOC ( (p->size+1) *
sizeof ( reverse_index ) );
id->total = 0.0;
id->count = p->size;
id->ri[j].fitness = 0.0;
id->ri[j].index = -1;
++j;
for ( i = 0; i < p->size; ++i )
{
/* interval width is the adjusted fitness. */
id->total += p->ind[i].a_fitness;
id->ri[j].fitness = id->total;
id->ri[j].index = i;
++j;
}
sc->data = (void *)id;
return sc;
break;
case SELECT_CLEAN:
id = (interval_data *)(sc->data);
FREE ( id->ri );
FREE ( sc->data );
FREE ( sc );
return NULL;
break;
}
return NULL;
}
/* select_inverse_afit_context()
*
* creates context for inverse_fitness selection method.
*/
sel_context *select_inverse_afit_context ( int op, sel_context *sc,
population *p, char *string )
{
interval_data *id;
int i, j = 0;
switch ( op )
{
case SELECT_INIT:
sc = (sel_context *)MALLOC ( sizeof ( sel_context ) );
sc->p = p;
sc->select_method = select_interval;
sc->context_method = select_inverse_afit_context;
/** use select_interval() to do the selection. **/
id = (interval_data *)MALLOC ( sizeof ( interval_data ) );
id->ri = (reverse_index *)MALLOC ( (p->size+1) *
sizeof ( reverse_index ) );
id->total = 0.0;
id->count = p->size;
id->ri[j].fitness = 0.0;
id->ri[j].index = -1;
++j;
for ( i = 0; i < p->size; ++i )
{
/* interval width is inverse of adjusted fitness. */
id->total += 1.0/p->ind[i].a_fitness;
id->ri[j].fitness = id->total;
id->ri[j].index = i;
++j;
}
sc->data = (void *)id;
return sc;
break;
case SELECT_CLEAN:
id = (interval_data *)(sc->data);
FREE ( id->ri );
FREE ( sc->data );
FREE ( sc );
return NULL;
break;
}
return NULL;
}
/* select_afit_overselect_context()
*
* creates context for fitness_overselect selection method.
*/
sel_context *select_afit_overselect_context ( int op, sel_context *sc,
population *p, char *string )
{
interval_data *id;
int i, j;
double total;
double group1_cutoff = 0.32;
int cutoffset;
double group1_selection = 0.8;
double cutoff;
double temp;
char **argv;
switch ( op )
{
case SELECT_INIT:
sc = (sel_context *)MALLOC ( sizeof ( sel_context ) );
sc->p = p;
sc->select_method = select_interval;
sc->context_method = select_afit_overselect_context;
/** parse the options string. **/
j = parse_o_rama ( string, &argv );
cutoffset = 0;
for ( i = 1; i < j; ++i )
{
if ( strcmp ( argv[i], "cutoff" ) == 0 )
{
group1_cutoff = strtod ( argv[++i], NULL );
cutoffset = 1;
}
else if ( strcmp ( argv[i], "proportion" ) == 0 )
group1_selection = strtod ( argv[++i], NULL );
else
error ( E_FATAL_ERROR, "unknown fitness_overselect option \"%s\".",
argv[i] );
}
/* if the cutoff was not set manually, then set it based on
the population size. */
if ( !cutoffset )
{
group1_cutoff = 320.0/p->size;
if ( group1_cutoff < 0.0 || group1_cutoff > 1.0 )
group1_cutoff = 0.32;
}
free_o_rama ( j, &argv );
if ( group1_cutoff < 0.0 || group1_cutoff > 1.0 )
error ( E_FATAL_ERROR, "Overselected fitness cutoff out of range. (%s)", string );
if ( group1_selection < 0.0 || group1_selection > 1.0 )
error ( E_FATAL_ERROR, "Overselected fitness proportion out of range. (%s)", string );
id = (interval_data *)MALLOC ( sizeof ( interval_data ) );
id->ri = (reverse_index *)MALLOC ( (p->size+1) *
sizeof ( reverse_index ) );
id->total = 0.0;
id->count = p->size;
id->ri[0].fitness = 0.0;
id->ri[0].index = -1;
j = 1;
/* store the fitness values in the reverse_index */
total = 0.0;
for ( i = 0; i < p->size; ++i )
{
total += p->ind[i].a_fitness;
id->ri[j].fitness = p->ind[i].a_fitness;
id->ri[j].index = i;
++j;
}
/* (sort lowest first) */
qsort ( (id->ri)+1, p->size, sizeof ( reverse_index ),
rev_ind_compare );
/* find the top individuals accounting for (cutoff) of the fitness,
and multiply their interval width by the selection. multiply
all the others by (1-selection). */
cutoff = total * (1.0-group1_cutoff);
total = 0.0;
for ( i = 1; i < p->size+1; ++i )
{
if ( total >= cutoff )
temp = id->ri[i].fitness * group1_selection;
else
temp = id->ri[i].fitness * (1.0-group1_selection);
total += id->ri[i].fitness;
id->ri[i].fitness = temp;
}
/* now convert to cumulative. */
total = 0.0;
for ( i = 1; i < p->size+1; ++i )
{
total += id->ri[i].fitness;
id->ri[i].fitness = total;
}
id->total = total;
sc->data = (void *)id;
return sc;
break;
case SELECT_CLEAN:
id = (interval_data *)(sc->data);
FREE ( id->ri );
FREE ( sc->data );
FREE ( sc );
return NULL;
break;
}
return NULL;
}