/* 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 /* initialize_topology() * * reads the parameter database and builds the exchange table. */ void initialize_topology ( multipop *mpop ) { char pnamebuf[100], pnamebuf2[100]; char *param, *param2, *param3; int i, j, k; int errors = 0; if ( mpop->size == 1 ) { /* singlepop problem -- no topology needed. */ mpop->exch = NULL; mpop->exchanges = -1; return; } oprintf ( OUT_SYS, 30, "building subpopulation exchange topology:\n" ); param = get_parameter ( "multiple.exchanges" ); if ( param == NULL ) { /* multipop problem, but no exchanges specified. */ mpop->exch = NULL; mpop->exchanges = 0; return; } else { mpop->exchanges = atoi ( param ); if ( mpop->exchanges < 0 ) error ( E_FATAL_ERROR, "\"exchanges\" must be nonnegative." ); } mpop->exch = (exchange *)MALLOC ( mpop->exchanges * sizeof ( exchange ) ); for ( i = 0; i < mpop->exchanges; ++i ) { /** read the destination subpop. **/ sprintf ( pnamebuf, "exch[%d].to", i+1 ); param = get_parameter ( pnamebuf ); if ( param == NULL ) { ++errors; error ( E_ERROR, "\"%s\" must be set.", pnamebuf ); } else { mpop->exch[i].to = atoi ( param ) - 1; if ( mpop->exch[i].to < 0 || mpop->exch[i].to >= mpop->size ) { ++errors; error ( E_ERROR, "\"%s\" is out of range.\n", pnamebuf ); } } /** read how the individuals to be replaced in the destination subpop are selected. **/ sprintf ( pnamebuf, "exch[%d].toselect", i+1 ); mpop->exch[i].tosc = get_parameter ( pnamebuf ); if ( mpop->exch[i].tosc == NULL ) { ++errors; error ( E_ERROR, "\"%s\" must be set.", pnamebuf ); } else { if ( ! exists_select_method ( mpop->exch[i].tosc ) ) { ++errors; error ( E_ERROR, "\"%s\": \"%s\" is not a selection method.", pnamebuf, mpop->exch[i].tosc ); } } /** read how many individuals are to be exchanged in this manner. **/ sprintf ( pnamebuf, "exch[%d].count", i+1 ); param = get_parameter ( pnamebuf ); if ( param == NULL ) { ++errors; error ( E_ERROR, "\"%s\" must be set.", pnamebuf ); } else { mpop->exch[i].count = atoi ( param ); if ( mpop->exch[i].count < 0 ) { ++errors; error ( E_ERROR, "\"%s\" must be nonnegative.", pnamebuf ); } } /** check to see if "from" is specified without a "tree[#]". **/ sprintf ( pnamebuf, "exch[%d].from", i+1 ); param = get_parameter ( pnamebuf ); if ( param ) { /** if "from" is specified, then we're copying whole individuals from one subpop to another. **/ /* these arrays are not needed. */ mpop->exch[i].from = NULL; mpop->exch[i].as = NULL; /* allocate an array of one string (to hold the selection method). */ mpop->exch[i].fromsc = (char **)MALLOC ( sizeof ( char * ) ); /* the subpop that individuals are taken from. */ mpop->exch[i].copywhole = atoi ( param ) - 1; if ( mpop->exch[i].copywhole < 0 || mpop->exch[i].copywhole >= mpop->size ) { ++errors; error ( E_ERROR, "\"%s\" is out of range.", pnamebuf ); } /* the selection method used to pick the individuals from the source subpop. */ sprintf ( pnamebuf, "exch[%d].fromselect", i+1 ); mpop->exch[i].fromsc[0] = get_parameter ( pnamebuf ); if ( mpop->exch[i].fromsc[0] == NULL ) { ++errors; error ( E_ERROR, "\"%s\" must be set.", pnamebuf ); } else { if ( ! exists_select_method ( mpop->exch[i].fromsc[0] ) ) { ++errors; error ( E_ERROR, "\"%s\": \"%s\" is not a selection method.", pnamebuf, mpop->exch[i].fromsc[0] ); } } } else { /** since "from" is not defined, we're taking trees from different subpops and merging them to create a composite individual to place in the destination subpop. **/ mpop->exch[i].copywhole = -1; /* this array lists, for each tree, which subpop it comes from. */ mpop->exch[i].from = (int *)MALLOC ( tree_count * sizeof ( int ) ); /* this array keeps track of when two trees are supposed to always come from the same individual (not just the same subpop). */ mpop->exch[i].as = (int *)MALLOC ( tree_count * sizeof ( int ) ); /* this array holds the selection method strings used for each tree. */ mpop->exch[i].fromsc = (char **)MALLOC ( tree_count * sizeof ( char * ) ); /* get the default selection method, if one is specified. */ sprintf ( pnamebuf, "exch[%d].fromselect", i+1 ); param3 = get_parameter ( pnamebuf ); for ( j = 0; j < tree_count; ++j ) { /** for each tree, attempt to read the "from" and "fromselect" parameters. **/ sprintf ( pnamebuf, "exch[%d].from.tree[%d]", i+1, j ); param = get_parameter ( pnamebuf ); sprintf ( pnamebuf2, "exch[%d].fromselect.tree[%d]", i+1, j ); param2 = get_parameter ( pnamebuf2 ); if ( param == NULL && param2 == NULL ) { /* neither is set, we're supposed to leave this tree untouched in the destination individual. */ mpop->exch[i].from[j] = -1; mpop->exch[i].as[j] = -1; mpop->exch[i].fromsc[j] = NULL; } else if ( param2 == NULL ) { /* only "from" is set, examine param3 for default selection method. */ /* source subpop. */ mpop->exch[i].from[j] = atoi ( param ) - 1; if ( mpop->exch[i].from[j] < 0 || mpop->exch[i].from[j] >= mpop->size ) { ++errors; error ( E_ERROR, "\"%s\" is out of range.", pnamebuf ); } /* no default set, error. */ if ( param3 == NULL ) { ++errors; error ( E_ERROR, "\"%s\" must be set.", pnamebuf2 ); } else { mpop->exch[i].as[j] = -1; if ( ! exists_select_method ( param3 ) ) { ++errors; error ( E_ERROR, "\"%s\": \"%s\" is not a selection method.", pnamebuf, param3 ); } } mpop->exch[i].fromsc[j] = param3; } else if ( param == NULL ) { /* only "fromselect" is set; it better be of the form "as_#". */ if ( strncmp ( param2, "as_", 3 ) == 0 ) { mpop->exch[i].from[j] = -1; mpop->exch[i].fromsc[j] = NULL; /* "as" stores which tree this one comes from the same subpop as. */ mpop->exch[i].as[j] = atoi ( param2 + 3 ); if ( mpop->exch[i].as[j] < 0 || mpop->exch[i].as[j] >= tree_count ) { ++errors; error ( E_ERROR, "\"%s\" is out of range.", pnamebuf2 ); } } else { ++errors; error ( E_ERROR, "\"%s\" must be \"as_#\".", pnamebuf2 ); } } else { /* they're both set. */ mpop->exch[i].as[j] = -1; mpop->exch[i].from[j] = atoi ( param ) - 1; if ( mpop->exch[i].from[j] < 0 || mpop->exch[i].from[j] >= mpop->size ) { ++errors; error ( E_ERROR, "\"%s\" is out of range.", pnamebuf ); } mpop->exch[i].fromsc[j] = param2; if ( ! exists_select_method ( param2 ) ) { ++errors; error ( E_ERROR, "\"%s\": \"%s\" is not a selection method.", pnamebuf2, param2 ); } } } /* now we need to resolve any chains of "as_" references: if tree 2 comes from the same individual as tree 1, and tree 1 comes from the same individual as tree 0, we need to change that to say that both 2 and 1 come from tree 0. also detect circular references. */ for ( j = 0; j < tree_count; ++j ) { if ( mpop->exch[i].as[j] == -1 ) continue; k = mpop->exch[i].as[j]; while ( k != -1 ) { if ( k == j ) { ++errors; error ( E_ERROR, "Circular reference resolving \"exch[%d].fromselect.tree[%d]\".", i+1, j ); j = tree_count; break; } mpop->exch[i].as[j] = k; k = mpop->exch[i].as[k]; } k = mpop->exch[i].as[j]; if ( mpop->exch[i].from[k] == -1 && mpop->exch[i].as[k] == -1 ) mpop->exch[i].as[j] = -1; } } #ifdef DEBUG /* print out information on this exchange. */ printf ( "exchange %d:\n", i+1 ); printf ( "to: %d; count: %d; select: %s\n", mpop->exch[i].to, mpop->exch[i].count, mpop->exch[i].tosc ); if ( mpop->exch[i].copywhole == -1 ) { for ( j = 0; j < tree_count; ++j ) { param = mpop->exch[i].fromsc[j]; printf ( " %3d: from: %3d as: %3d select: %s\n", j, mpop->exch[i].from[j], mpop->exch[i].as[j], param==NULL?"NULL":param ); } } else { param = mpop->exch[i].fromsc[0]; printf ( "copywhole: %d select: %s\n", mpop->exch[i].copywhole, param==NULL?"NULL":param ); } #endif } /* if any errors occurred then stop now. */ if ( errors ) error ( E_FATAL_ERROR, "Errors occurred while building topology. Aborting." ); /* print out the summary of exchanges. */ oprintf ( OUT_SYS, 30, " %d exchange(s) total.\n", mpop->exchanges ); for ( i = 0; i < mpop->exchanges; ++i ) { oprintf ( OUT_SYS, 30, " exchange %d:\n", i+1 ); oprintf ( OUT_SYS, 30, " replace %d individual(s) in subpop %d (selected by %s)\n", mpop->exch[i].count, mpop->exch[i].to+1, mpop->exch[i].tosc ); if ( mpop->exch[i].copywhole != -1 ) oprintf ( OUT_SYS, 30, " with individual(s) from subpop %d (selected by %s)\n", mpop->exch[i].copywhole+1, mpop->exch[i].fromsc[0] ); else for ( j = 0; j < tree_count; ++j ) { if ( mpop->exch[i].from[j] == -1 ) { if ( mpop->exch[i].as[j] == -1 ) oprintf ( OUT_SYS, 30, " tree %d: leaving original tree\n", j ); else oprintf ( OUT_SYS, 30, " tree %d: from same individual as tree %d\n", j, mpop->exch[i].as[j] ); } else oprintf ( OUT_SYS, 30, " tree %d: from subpop %d (selected by %s)\n", j, mpop->exch[i].from[j]+1, mpop->exch[i].fromsc[j] ); } } } /* free_topology() * * this frees the topology table. */ void free_topology ( multipop *mpop ) { int i; for ( i = 0; i < mpop->exchanges; ++i ) { if ( mpop->exch[i].from ) FREE ( mpop->exch[i].from ); if ( mpop->exch[i].as ) FREE ( mpop->exch[i].as ); FREE ( mpop->exch[i].fromsc ); } if ( mpop->exch ) FREE ( mpop->exch ); } /* exchange_subpopulations() * * this performs the actual exchanges, using the information stored * in the exchange table. */ void exchange_subpopulations ( multipop *mpop ) { int i, j, k; sel_context *tocon; sel_context **fromcon; select_context_func_ptr select_con; int tp, *fp; int ti, *fi; #ifdef _PARALLEL_H /* Are we working in parallel */ if (get_operation_mode() == SLAVE) { exchange_filter(mpop); return; } #endif /** arrays used for composite individuals. **/ /* fromcon[j] holds the selection context used to pick individual to take tree j from. */ fromcon = (sel_context **)MALLOC ( tree_count * sizeof ( sel_context * ) ); /* fp[j] holds the population from which to take tree j from. */ fp = (int *)MALLOC ( tree_count * sizeof ( int ) ); /* fi[j] holds the individual from which to take tree j from. */ fi = (int *)MALLOC ( tree_count * sizeof ( int ) ); for ( i = 0; i < mpop->exchanges; ++i ) { /* where individuals are going. */ tp = mpop->exch[i].to; /* set up selection method to pick individuals to be replaced. */ select_con = get_select_context ( mpop->exch[i].tosc ); tocon = select_con ( SELECT_INIT, NULL, mpop->pop[tp], mpop->exch[i].tosc ); /* are we copying whole individuals or creating composites? */ if ( mpop->exch[i].copywhole > -1 ) { /*** copying whole individuals. ***/ /* the source subpop. */ fp[0] = mpop->exch[i].copywhole; /* selection method for choosing individuals from source subpop. */ select_con = get_select_context ( mpop->exch[i].fromsc[0] ); fromcon[0] = select_con ( SELECT_INIT, NULL, mpop->pop[fp[0]], mpop->exch[i].fromsc[0] ); for ( k = 0; k < mpop->exch[i].count; ++k ) { /** pick an individual to be replaced that has not already been replaced during this exchange cycle. **/ do { ti = tocon->select_method ( tocon ); } while ( mpop->pop[tp]->ind[ti].flags & FLAG_NEWEXCH ); /* pick an individual from the source subpop. */ fi[0] = fromcon[0]->select_method ( fromcon[0] ); /** remove the old iondividual from the population. **/ for ( j = 0; j < tree_count; ++j ) { /* always dereference ERCs when removing trees from the population. */ reference_ephem_constants ( mpop->pop[tp]->ind[ti].tr[j].data, -1 ); free_tree ( mpop->pop[tp]->ind[ti].tr+j ); } /* copy the individual. */ duplicate_individual ( mpop->pop[tp]->ind+ti, mpop->pop[fp[0]]->ind+fi[0] ); /* reference the ERCs in the new individual. */ for ( j = 0; j < tree_count; ++j ) reference_ephem_constants ( mpop->pop[tp]->ind[ti].tr[j].data, 1 ); /* mark the individual as just coming from an exchange. */ mpop->pop[tp]->ind[ti].flags = FLAG_NEWEXCH; } /* all done with this exchange, delete the selection context. */ fromcon[0]->context_method ( SELECT_CLEAN, fromcon[0], NULL, NULL ); } else { /*** creating composite individuals. ***/ /** create selection contexts for each tree. **/ for ( j = 0; j < tree_count; ++j ) { /* does this tree need a context? */ if ( mpop->exch[i].fromsc[j] ) { /* create it. */ select_con = get_select_context ( mpop->exch[i].fromsc[j] ); fromcon[j] = select_con ( SELECT_INIT, NULL, mpop->pop[mpop->exch[i].from[j]], mpop->exch[i].fromsc[j] ); } else /* don't need one. */ fromcon[j] = NULL; } for ( k = 0; k < mpop->exch[i].count; ++k ) { /** select an individual to be replaced that hasn't already been during this exchange cycle. **/ do { ti = tocon->select_method ( tocon ); } while ( mpop->pop[tp]->ind[ti].flags & FLAG_NEWEXCH ); /** now select the individuals that we will merge to replace trees of the destination individual. **/ for ( j = 0; j < tree_count; ++j ) { /* we don't need to do a selection for a particular tree if (1) it uses the same individual as another tree or (2) it doesn't get replaced in the destination individual. */ fp[j] = mpop->exch[i].from[j]; if ( fp[j] != -1 ) { fi[j] = fromcon[fp[j]]->select_method ( fromcon[fp[j]] ); } } /** now resolve "as_" references in the fp and fi arrays. */ for ( j = 0; j < tree_count; ++j ) if ( fp[j] == -1 ) { if ( mpop->exch[i].as[j] == -1 ) /* tree j doesn't get replaced, so set both values to -1. */ fp[j] = fi[j] = -1; else { /* tree j comes from the same individual as some other tree. */ fp[j] = fp[mpop->exch[i].as[j]]; fi[j] = fi[mpop->exch[i].as[j]]; } } /** replace the appropriate parts of the old tree. **/ for ( j = 0; j < tree_count; ++j ) { /* skip trees that don't get replaced. */ if ( fp[j] == -1 ) continue; /* dereference ERCs in old tree. */ reference_ephem_constants ( mpop->pop[tp]->ind[ti].tr[j].data, -1 ); /* delete old tree. */ free_tree ( mpop->pop[tp]->ind[ti].tr+j ); /* copy new tree. */ copy_tree ( mpop->pop[tp]->ind[ti].tr+j, mpop->pop[fp[j]]->ind[fi[j]].tr+j ); /* reference ERCs in new tree. */ reference_ephem_constants ( mpop->pop[tp]->ind[ti].tr[j].data, 1 ); } /* evaluate the fitness of the new composite individual. */ app_eval_fitness ( mpop->pop[tp]->ind+ti ); mpop->pop[tp]->ind[ti].flags = FLAG_NEWEXCH; } /* destroy source selection contexts. */ for ( j = 0; j < tree_count; ++j ) if ( fromcon[j] ) fromcon[j]->context_method ( SELECT_CLEAN, fromcon[j], NULL, NULL ); } /* destroy destination selection context. */ tocon->context_method ( SELECT_CLEAN, tocon, NULL, NULL ); } FREE ( fromcon ); FREE ( fp ); FREE ( fi ); /* erase all the NEWEXCH flags. */ for ( i = 0; i < mpop->size; ++i ) for ( j = 0; j < mpop->pop[i]->size; ++j ) mpop->pop[i]->ind[j].flags &= ~FLAG_NEWEXCH; } /* rebuild_exchange_topology() * * rebuilds the exchange table. called from user code after making changes * to the parameters governing exchanges. */ void rebuild_exchange_topology ( multipop *mpop ) { free_topology ( mpop ); initialize_topology ( mpop ); } #ifdef _PARALLEL_H /* exchange_test() * * returns the exchange type: NO, SEND, RECEIVE, NORMAL */ int exchange_test( int tp, int fp ) { const int exch_matrix[2][2] = { { NOP, SEND }, { RECEIVE, NORMAL } }; int from; int to; int low; int high; low = get_low(); high = get_high(); to = OTHER; if ( (low <= tp) && (tp < high) ) { /* The destination population resides on this node */ to = MYSELF; } from = OTHER; if ( (low <= fp) && (fp < high) ) { /* The source population resides on this node */ from = MYSELF; } return exch_matrix[to][from]; } /* exchange_filter() * * does a traversal of all the exchanges and invoke the appropriate functions */ void exchange_filter ( multipop *mpop ) { int i, j, k; sel_context **fromcon; select_context_func_ptr select_con; int tp, *fp; int *fi; int exch_type; int low; int high; low = get_low(); high = get_high(); /** arrays used for composite individuals. **/ /* fromcon[j] holds the selection context used to pick individual to take tree j from. */ fromcon = (sel_context **)MALLOC ( tree_count * sizeof ( sel_context * ) ); /* fp[j] holds the population from which to take tree j from. */ fp = (int *)MALLOC ( tree_count * sizeof ( int ) ); /* fi[j] holds the individual from which to take tree j from. */ fi = (int *)MALLOC ( tree_count * sizeof ( int ) ); for ( i = 0; i < mpop->exchanges; ++i ) { /* where individuals are going. */ tp = mpop->exch[i].to; /* are we copying whole individuals or creating composites? */ if ( mpop->exch[i].copywhole > -1 ) { /*** copying whole individuals. ***/ /* the source subpop. */ fp[0] = mpop->exch[i].copywhole; exch_type = exchange_test(tp, fp[0]); if ( (exch_type == NOP) || (exch_type == RECEIVE)) continue; /* selection method for choosing individuals from source subpop. */ select_con = get_select_context ( mpop->exch[i].fromsc[0] ); fromcon[0] = select_con ( SELECT_INIT, NULL, mpop->pop[fp[0]], mpop->exch[i].fromsc[0] ); for ( k = 0; k < mpop->exch[i].count; ++k ) { /* pick an individual from the source subpop. */ fi[0] = fromcon[0]->select_method ( fromcon[0] ); /* We know the: populations,, ind */ exchange_dispatch(mpop, exch_type, i, tp, fp[0], fi[0], -1); } /* all done with this exchange, delete the selection context. */ fromcon[0]->context_method ( SELECT_CLEAN, fromcon[0], NULL, NULL ); } else { /*** creating composite individuals. ***/ /** create selection contexts for each tree. **/ for ( j = 0; j < tree_count; ++j ) { exch_type = exchange_test(tp, mpop->exch[i].from[j]); if ( (exch_type == NOP) || (exch_type == RECEIVE)) continue; /* does this tree need a context? */ if ( mpop->exch[i].fromsc[j] ) { /* create it. */ select_con = get_select_context ( mpop->exch[i].fromsc[j] ); fromcon[j] = select_con ( SELECT_INIT, NULL, mpop->pop[mpop->exch[i].from[j]], mpop->exch[i].fromsc[j] ); } else /* don't need one. */ fromcon[j] = NULL; } for ( k = 0; k < mpop->exch[i].count; ++k ) { /** now select the individuals that we will merge to replace trees of the destination individual. **/ for ( j = 0; j < tree_count; ++j ) { /* we don't need to do a selection for a particular tree if (1) it uses the same individual as another tree or (2) it doesn't get replaced in the destination individual. */ fp[j] = mpop->exch[i].from[j]; exch_type = exchange_test(tp, fp[j]); if ( (exch_type == NOP) || (exch_type == RECEIVE)) continue; if ( fp[j] != -1 ) { fi[j] = fromcon[fp[j]]->select_method ( fromcon[fp[j]] ); } } /** now resolve "as_" references in the fp and fi arrays. */ for ( j = 0; j < tree_count; ++j ) if ( fp[j] == -1 ) { if ( mpop->exch[i].as[j] == -1 ) /* tree j doesn't get replaced, so set both values to -1. */ fp[j] = fi[j] = -1; else { /* tree j comes from the same individual as some other tree. */ fp[j] = fp[mpop->exch[i].as[j]]; fi[j] = fi[mpop->exch[i].as[j]]; } } /** replace the appropriate parts of the old tree. **/ for ( j = 0; j < tree_count; ++j ) { /* skip trees that don't get replaced. */ if ( fp[j] == -1 ) continue; exch_type = exchange_test(tp, fp[0]); if ( (exch_type == NOP) || (exch_type == RECEIVE)) continue; exchange_dispatch(mpop, exch_type, i, tp, fp[j], fi[j], j); } /* Is hier OK voor lokale uitwisselingen maar niet voor export toestanden evaluate the fitness of the new composite individual. app_eval_fitness ( mpop->pop[tp]->ind+ti ); mpop->pop[tp]->ind[ti].flags = FLAG_NEWEXCH; */ } /* destroy source selection contexts. */ for ( j = 0; j < tree_count; ++j ) if ( fromcon[j] ) fromcon[j]->context_method ( SELECT_CLEAN, fromcon[j], NULL, NULL ); } } /* erase all the NEWEXCH flags. */ for ( i = low; i < high; ++i ) for ( j = 0; j < mpop->pop[i]->size; ++j ) mpop->pop[i]->ind[j].flags &= ~FLAG_NEWEXCH; FREE ( fromcon ); FREE ( fp ); FREE ( fi ); /* Are there any tree or individuals send from other populations? */ exchange_import( mpop ); } /* exchange_dispatch() * * invokes the appropriate functions based on source and destination */ void exchange_dispatch(multipop *mpop, int exch_type, int exch, int tp, int fp, int fi, int ft) { switch(exch_type) { case NOP: { #ifdef PDEBUG printf ("\t NOP \n"); #endif /* Nothing to do this happens on another node */ break; } case SEND: { #ifdef PDEBUG printf ("\tEXPORTING TO %d\n", tp); #endif /* Export a tree or and individual */ exchange_export ( mpop, exch, tp, fp, fi, ft); break; } case RECEIVE: { #ifdef PDEBUG printf ("\t RECEIVE \n"); #endif /* Do nothing yet */ break; } case NORMAL: { #ifdef PDEBUG printf ("\tNORMAL from %d to %d\n", fp, tp); #endif /* Both and destination are on this node */ exchange_normal( mpop, exch, tp, fp, fi, ft); break; } default: { error ( E_FATAL_ERROR, "Exchange number %d is not valid", exch); break; } } return; } /* exchange_normal * * should do the same as the initial exchange function */ void exchange_normal ( multipop *mpop, int exch, int tp, int fp, int fi, int ft ) { const int i = exch; int j; sel_context *tocon; select_context_func_ptr select_con; int ti; { /* set up selection method to pick individuals to be replaced. */ select_con = get_select_context ( mpop->exch[i].tosc ); tocon = select_con ( SELECT_INIT, NULL, mpop->pop[tp], mpop->exch[i].tosc ); /* are we copying whole individuals or creating composites? */ if ( mpop->exch[i].copywhole > -1 ) { /*** copying whole individuals. ***/ /** pick an individual to be replaced that has not already been replaced during this exchange cycle. **/ do { ti = tocon->select_method ( tocon ); } while ( mpop->pop[tp]->ind[ti].flags & FLAG_NEWEXCH ); /** remove the old iondividual from the population. **/ for ( j = 0; j < tree_count; ++j ) { /* always dereference ERCs when removing trees from the population. */ reference_ephem_constants ( mpop->pop[tp]->ind[ti].tr[j].data, -1 ); free_tree ( mpop->pop[tp]->ind[ti].tr+j ); } /* copy the individual. */ duplicate_individual ( mpop->pop[tp]->ind+ti, mpop->pop[fp]->ind+fi ); /* reference the ERCs in the new individual. */ for ( j = 0; j < tree_count; ++j ) reference_ephem_constants ( mpop->pop[tp]->ind[ti].tr[j].data, 1 ); /* mark the individual as just coming from an exchange. */ mpop->pop[tp]->ind[ti].flags = FLAG_NEWEXCH; } else { /*** creating composite individuals. ***/ { /** select an individual to be replaced that hasn't already been during this exchange cycle. **/ do { ti = tocon->select_method ( tocon ); } while ( mpop->pop[tp]->ind[ti].flags & FLAG_NEWEXCH ); /* dereference ERCs in old tree. */ reference_ephem_constants ( mpop->pop[tp]->ind[ti].tr[ft].data, -1 ); /* delete old tree. */ free_tree ( mpop->pop[tp]->ind[ti].tr+ft ); /* copy new tree. */ copy_tree ( mpop->pop[tp]->ind[ti].tr+ft, mpop->pop[fp]->ind[fi].tr+ft ); /* reference ERCs in new tree. */ reference_ephem_constants ( mpop->pop[tp]->ind[ti].tr[ft].data, 1 ); } } /* destroy destination selection context. */ tocon->context_method ( SELECT_CLEAN, tocon, NULL, NULL ); } } /* exchange_export() * * exports individuals to population not present on this node */ void exchange_export ( multipop *mpop, int exch, int tp, int fp, int fi, int ft ) { int destination_node; /* Determine the node on which the population resides */ destination_node = population_mapping (tp); if (destination_node < 0) error (E_FATAL_ERROR, "In exchange_export() no node for population number %d", tp); /* are we copying whole individuals or creating composites? */ if ( mpop->exch[exch].copywhole > -1 ) { /*** copying whole individuals. ***/ /* send the individual: exchange nr, pop, ind, ind ptr */ send_individual ( destination_node, exch, mpop->pop[fp]->ind+fi ); } else { /* send the tree: exchange nr, pop, ind, tree, tree ptr */ send_tree ( destination_node, exch, ft, mpop->pop[fp]->ind[fi].tr+ft ); } return; } /* exchange_import() * * checks whether there are trees/individuals can be imported and merged/copied * this function has a event driven character since its processing is based on the * received messages. */ void exchange_import ( multipop *mpop ) { int i, j, k; int count; int tmp; sel_context *tocon; select_context_func_ptr select_con; int ti; int ft; int bufid; int exch; int tp; int bytes; int msgtg; int tid; individual *ind_ptr; tree tmp_tree; #ifdef PDEBUG printf ("Receiving\n"); #endif while ( (bufid = pvm_nrecv(-1, -1)) ) { pvm_bufinfo ( bufid, &bytes, &msgtg, &tid ); /* Intermediate reset */ ft = -1; #ifdef PDEBUG_IMPORT printf ("GOT FROM tid[%x]\n", tid); #endif switch (msgtg) { case TERM_REQUEST_TAG: { /* Force the user termination criterium */ set_term(1); return; break; /* Useless, yes I know. */ } case IND_TAG: { /* Extract exchange_number and all the trees */ receive_individual ( &exch, &ind_ptr ); break; } case TREE_TAG: { /* Extract exchange_number, destination pop. the tree and the tree number */ receive_tree ( &exch, &ft, &tmp_tree ); break; } default: { error (E_FATAL_ERROR, "Unkown tag in exchange_import() value = %d", msgtg); } } /* Reuse the variable "i" from the original code :-) */ i = exch; #ifdef PDEBUG_IMPORT printf ("Exchange nr. %d dest. pop %d from tree %d \n", i, mpop->exch[i].to, ft); #endif { /* where individuals are going. */ tp = mpop->exch[i].to; /* Check if the population to node mapping was correct */ tid = population_mapping (tp); if (tid != pvm_mytid()) error (E_FATAL_ERROR, "Incorrect mapping! Received msg meant for population number %d\n", tp); /* set up selection method to pick individuals to be replaced. */ select_con = get_select_context ( mpop->exch[i].tosc ); tocon = select_con ( SELECT_INIT, NULL, mpop->pop[tp], mpop->exch[i].tosc ); /* are we copying whole individuals or creating composites? */ if ( mpop->exch[i].copywhole > -1 ) { /*** copying whole individuals. ***/ /** pick an individual to be replaced that has not already been replaced during this exchange cycle. **/ count = 0; tmp = mpop->pop[tp]->size; do { ti = tocon->select_method ( tocon ); count++; if (count > tmp) { /* No individual left to be selected! */ printf("exchange_import: no ind. left for replacement 1\n"); return; } #ifdef PDEBUG_IMPORT_XXXX printf ("exch: search ind ti %d \n", ti); printf ("pop size is %d\n", mpop->pop[tp]->size); #endif } while ( mpop->pop[tp]->ind[ti].flags & FLAG_NEWEXCH ); /** remove the old iondividual from the population. **/ for ( j = 0; j < tree_count; ++j ) { /* always dereference ERCs when removing trees from the population. */ reference_ephem_constants ( mpop->pop[tp]->ind[ti].tr[j].data, -1 ); free_tree ( mpop->pop[tp]->ind[ti].tr+j ); } /* copy the individual. */ #ifdef PDEBUG printf("dup ind ..."); fflush(stdout); #endif duplicate_individual ( mpop->pop[tp]->ind+ti, ind_ptr ); #ifdef PDEBUG printf("dup ind ended\n"); #endif /* Freeing the individual */ /* Starting with all the trees themselves */ for (k=0; ktr+k); /* Free the array */ FREE(ind_ptr->tr); /* Free the individual structure */ FREE(ind_ptr); /* reference the ERCs in the new individual. */ for ( j = 0; j < tree_count; ++j ) reference_ephem_constants ( mpop->pop[tp]->ind[ti].tr[j].data, 1 ); /* mark the individual as just coming from an exchange. */ mpop->pop[tp]->ind[ti].flags = FLAG_NEWEXCH; } else { /*** creating composite individuals. ***/ { /** select an individual to be replaced that hasn't already been during this exchange cycle. **/ count = 0; tmp = mpop->pop[tp]->size; do { ti = tocon->select_method ( tocon ); if (count > tmp) { /* No individual left to be selected! */ printf("exchange_import: no ind. left for replacement 2\n"); return; } } while ( mpop->pop[tp]->ind[ti].flags & FLAG_NEWEXCH ); /* dereference ERCs in old tree. */ reference_ephem_constants ( mpop->pop[tp]->ind[ti].tr[ft].data, -1 ); /* delete old tree. */ free_tree ( mpop->pop[tp]->ind[ti].tr+ft ); /* copy new tree. */ copy_tree ( mpop->pop[tp]->ind[ti].tr+ft, &tmp_tree); /* Free the tree */ free_tree (&tmp_tree); /* reference ERCs in new tree. */ reference_ephem_constants ( mpop->pop[tp]->ind[ti].tr[ft].data, 1 ); } } /* destroy destination selection context. */ tocon->context_method ( SELECT_CLEAN, tocon, NULL, NULL ); } } return; } /* signal_master() * * send termination signal to the master */ void signal_master(int signal) { int ptid; ptid = pvm_parent(); pvm_initsend(ENCODING); pvm_send (ptid, signal); } /* pack_individual() * * pack an individual in order to send it */ void pack_individual( individual *ind_ptr) { int i; /* First pack the individual's information */ if (pvm_pkdouble(&(ind_ptr->r_fitness), 1, 1)) pvm_perror ("send_individual() error packing \"r_fitness\""); if (pvm_pkdouble(&(ind_ptr->s_fitness), 1, 1)) pvm_perror ("send_individual() error packing \"s_fitness\""); if (pvm_pkdouble(&(ind_ptr->a_fitness), 1, 1)) pvm_perror ("send_individual() error packing \"a_fitness\""); if (pvm_pkint(&(ind_ptr->hits), 1, 1)) pvm_perror ("send_individual() error packing \"hits\""); if (pvm_pkint(&(ind_ptr->evald), 1, 1)) pvm_perror ("send_individual() error packing \"evald\""); if (pvm_pkint(&(ind_ptr->flags), 1, 1)) pvm_perror ("send_individual() error packing \"flags\""); /* 2nd pack its trees */ for (i=0; itr[i])); return; } /* unpack_individual() * * unpack an individual and allocates the memory for it ... */ void unpack_individual ( individual **ind_ptr ) { int i; individual *tmp_ind; tmp_ind = (individual *) MALLOC (sizeof(individual)); tmp_ind->tr = (tree *) MALLOC (sizeof(tree)*tree_count); /* First unpack the individual's information */ if (pvm_upkdouble(&(tmp_ind->r_fitness), 1, 1)) pvm_perror ("receive_individual() error unpacking \"r_fitness\"") ; if (pvm_upkdouble(&(tmp_ind->s_fitness), 1, 1)) pvm_perror ("receive_individual() error unpacking \"s_fitness\""); if (pvm_upkdouble(&(tmp_ind->a_fitness), 1, 1)) pvm_perror ("receive_individual() error unpacking \"a_fitness\""); if (pvm_upkint(&(tmp_ind->hits), 1, 1)) pvm_perror ("receive_individual() error unpacking \"hits\""); if (pvm_upkint(&(tmp_ind->evald), 1, 1)) pvm_perror ("receive_individual() error unpacking \"evald\""); if (pvm_upkint(&(tmp_ind->flags), 1, 1)) pvm_perror ("receive_individual() error unpacking \"flags\""); /* 2nd unpack it trees */ for (i=0; itr[i]); /* 3d put into the pointer */ *ind_ptr = tmp_ind; return; } /* send_individual() * * send an entire individual */ void send_individual ( int destination_node, int exch, individual *ind_ptr ) { #ifdef PDEBUG printf("send_individiual() to %x\n", destination_node); #endif pvm_initsend(ENCODING); /* Zero pack the exchange number */ if (pvm_pkint(&exch, 1, 1)) pvm_perror ("send_individual() error packing \"exch\""); pack_individual(ind_ptr); /* Send */ if (pvm_send (destination_node, IND_TAG)) pvm_perror ("send_individual() error sending"); #ifdef PDEBUG printf("finished send_individual()\n"); #endif } /* receive_individual() * * receives an individual. */ void receive_individual ( int *exch, individual **ind_ptr ) { #ifdef PDEBUG printf("receive_individiual()\n"); #endif /* Zero pack the exchange number */ if (pvm_upkint(exch, 1, 1)) pvm_perror ("send_individual() error unpacking \"exch\""); /* First unpack the individual's information */ unpack_individual(ind_ptr); #ifdef PDEBUG printf("finished receive_individual()\n"); #endif } #endif