/* 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 /* 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; }