//HJJA population *change_population ( population *oldpop, breedphase *bp ) { population *newpop; int i, j; int numphases; double totalrate = 0.0; double r, r2; int prob_oper = atoi ( get_parameter ( "probabilistic_operators" ) ); /* allocate the new population. */ newpop = allocate_population ( oldpop->size ); globaldata* g = get_globaldata();//get the lists if(g->bUseHFC){ if( IsHighestActiveLevel(g->current_population)){ /*reproduce best guys into the new population. */ for(i=0;i<run_stats[0].bestn;i++){ //printf("best %d ind\n", i); duplicate_individual ( (newpop->ind)+newpop->next, run_stats[0].best[i]->ind); newpop->ind[newpop->next].flags = FLAG_NONE; ++(newpop->next); //HJJS structure niching: mutation //Assumption: we think any structure mutation will create a new structure //for numeric mutation, we won't change the structure CStruct* pSt; int structID = newpop->ind[newpop->next].structID; pSt = g->pStructHash->find(structID); if(pSt==NULL){ //make sure,though redudency code pSt = new CStruct(); pSt->structID = ++(g->currMaxStructID); pSt->age=1; pSt->lastGen=g->current_generation+1; pSt->nIndividuals=0; pSt->nIndNextGen=1; newpop->ind[newpop->next].structID=pSt->structID; g->pStructHash->insert(pSt); } else{ if(pSt->lastGen != g->current_generation+1){//the first individual in this generation pSt->age++; pSt->lastGen = g->current_generation+1; } pSt->nIndNextGen++;//increase the ind no of this population } //HJJS end } } //End HJJ_ELITISM }//End useHFC /* the first element of the breedphase table is a dummy -- its operator field stores the number of phases. */ numphases = bp[0].operatorID; /* call the start method for each phase. */ for ( i = 1; i <= numphases; ++i ) { totalrate += bp[i].rate; if ( bp[i].operator_start ) bp[i].operator_start ( oldpop, bp[i].data ); } /* now fill the new population. */ while ( newpop->next < newpop->size ) { /** select an operator, either stochastically or not depending on the probabilistic_operators parameter. **/ if ( prob_oper ) r = totalrate * random_double(); else r = totalrate * ((double)newpop->next/(double)newpop->size); r2 = bp[1].rate; for ( i = 1; r2 < r; ) r2 += bp[++i].rate; #ifdef DEBUG fprintf ( stderr, "picked %10.3lf; operator %d\n", r, i ); #endif /* call the phase's method to do the operation. */ if ( bp[i].operator_operate ){ bp[i].operator_operate ( oldpop, newpop, bp[i].data ); } } /* call each phase's method to do cleanup. */ for ( i = 1; i <= numphases; ++i ) { if ( bp[i].operator_end ) bp[i].operator_end ( bp[i].data ); } /* mark all the ERCs referenced in the new population. */ for ( i = 0; i < newpop->size; ++i ) for ( j = 0; j < tree_count; ++j ) reference_ephem_constants ( newpop->ind[i].tr[j].data, 1 ); /* free the old population. */ free_population ( oldpop ); //Bug when do reproduction ? return ( newpop ); }
/* operator_mutate_erc() * * do the mutation. */ void operator_mutate_erc ( population *oldpop, population *newpop, void *data ) { int i; int ps; mutate_erc_data * md; int t; double r; int p; int count=0; md = (mutate_erc_data *)data; /* choose a tree to mutate. */ //t: the tTH tree of the individual r = random_double() * md->treetotal; for ( t = 0; r >= md->tree[t]; ++t ); /* select an individual to mutate. */ //p: parent invidualIP //ps: parent tree size p = md->sc->select_method ( md->sc ); ps = tree_nodes ( oldpop->ind[p].tr[t].data ); vector<lnode*> ParamNodeList; //the root nodes of all numeric subtree vector<lnode*> MutatedParamNodelist;////the root nodes of all numeric subtree to be mutated vector<lnode*> ERCNodelist; //ERC nodelist for a subtree get_subtree_parameter_list(oldpop->ind[p].tr[t].data, &ParamNodeList); //decide which parameters needs to be mutated int nParam = ParamNodeList.size(); if (nParam >= 1){ int nParamMutated = nParam * md->var_percent; //at least we mutate one parameter! if (nParamMutated<1) nParamMutated = 1; //we randomly select nParamMutated parameters to be mutated. //we allow duplicate selection of parameters. for(i=0;i<nParamMutated;i++){ int vi = random_int (nParam); MutatedParamNodelist.push_back(ParamNodeList[vi]); } //for each parameter subtree, we randomly selection a portion of //its ERCs and mutate them. for(i=0;i<nParamMutated;i++){ ERCNodelist.clear(); lnode* pNode = MutatedParamNodelist[i]; /* there are too possiblility 1: the root node of numeric subtree is a ERC itself. 2: it is a internal node*/ if( pNode->f->type == TERM_ERC){ //we mutate a ERC by ERC+ 5%ERC* N(0,1) ++pNode; //HJJ!!!!!! The next node of pNode->f is the ERC node! double value = pNode->d->d; pNode->d->d = value * (0.05* gauss_dist()+1); #ifdef DEBUG_ERC_MUTATE printf("ERC init_value = %f new value = %f\n", value, pNode->d->d); #endif } else{ int tSize = tree_nodes(pNode); get_tree_nodes_ERC(pNode,tSize-1, &ERCNodelist); //decide how many ERCs of this subtree is to be mutated. int nERC = ERCNodelist.size(); if (nERC<1) continue; //no ERC in this subtree. Is this possible? int nERCmut= nERC * md->erc_percent; if (nERCmut <1) nERCmut=1; //at least mutate one ERC for(int j=0;j<nERCmut;j++){ lnode* pNode = ERCNodelist[ random_int(nERC)]; //we mutate a ERC by ERC+ 5%ERC* N(0,1) ++pNode; double value = pNode->d->d; pNode->d->d = value * (0.05* gauss_dist()+1); #ifdef DEBUG_ERC_MUTATE printf("ERC init_value = %f new value = %f\n", value, pNode->d->d); #endif } }//end else } }//end parameter mutation //Now copy the mutated individual to the new population /* ...and reproduce it into the new population. */ duplicate_individual ( (newpop->ind)+newpop->next, (oldpop->ind)+p ); newpop->ind[newpop->next].flags = FLAG_NONE; //HJJS structure niching: mutation //Assumption: we think any structure mutation will create a new structure //for numeric mutation, we won't change the structure globaldata* g = get_globaldata(); CStruct* pSt; int structID = newpop->ind[newpop->next].structID; pSt = g->pStructHash->find(structID); if(pSt==NULL){ //make sure,though redudency code pSt = new CStruct(); pSt->structID = ++(g->currMaxStructID); pSt->age=1; pSt->lastGen=g->current_generation+1; pSt->nIndividuals=0; pSt->nIndNextGen=1; newpop->ind[newpop->next].structID=pSt->structID; g->pStructHash->insert(pSt); } else{ if(pSt->lastGen != g->current_generation+1){//the first individual in this generation pSt->age++; pSt->lastGen = g->current_generation+1; } pSt->nIndNextGen++;//increase the ind no of this population } //HJJS end ++newpop->next; #ifdef DEBUG_ERC_MUTATE printf ( "ERC MUTATION COMPLETE.\n\n\n" ); #endif }
void calculate_pop_stats(popstats *s, population *pop, int gen, int subpop) { int i, j, k, l; int b; saved_ind *shp; individual **temp; /* allocate a list of the top N individuals. */ s->best = (saved_ind **) MALLOC(s->bestn * sizeof(saved_ind *)); temp = (individual **) MALLOC((s->bestn + 1) * sizeof(individual *)); s->size = pop->size; /** this is all pretty obvious -- set all the max and min values to the first individual's values, then go through the population looking for things that are bigger/smaller/better/worse/etc. **/ s->maxnodes = s->minnodes = s->totalnodes = s->bestnodes = s->worstnodes = individual_size(pop->ind + 0); s->maxdepth = s->mindepth = s->totaldepth = s->bestdepth = s->worstdepth = individual_depth(pop->ind + 0); s->maxhits = s->minhits = s->totalhits = s->besthits = s->worsthits = pop->ind[0].hits; s->bestfit = s->worstfit = s->totalfit = pop->ind[0].a_fitness; temp[0] = pop->ind; b = 1; s->bestgen = s->worstgen = gen; s->bestpop = s->worstpop = subpop; for (i = 1; i < s->size; ++i) { j = individual_size(pop->ind + i); s->totalnodes += j; if (j < s->minnodes) s->minnodes = j; if (j > s->maxnodes) s->maxnodes = j; k = individual_depth(pop->ind + i); s->totaldepth += k; if (k < s->mindepth) s->mindepth = k; if (k > s->maxdepth) s->maxdepth = k; l = pop->ind[i].hits; s->totalhits += l; if (l < s->minhits) s->minhits = l; if (l > s->maxhits) s->maxhits = l; s->totalfit += pop->ind[i].a_fitness; if (pop->ind[i].a_fitness > s->bestfit) { s->bestfit = pop->ind[i].a_fitness; s->bestnodes = j; s->bestdepth = k; s->besthits = l; } else if (pop->ind[i].a_fitness < s->worstfit) { s->worstfit = pop->ind[i].a_fitness; s->worstnodes = j; s->worstdepth = k; s->worsthits = l; } /** insert the current individual into the top N list (if it belongs there). **/ for (j = b; j > 0; --j) { if (pop->ind[i].a_fitness < temp[j - 1]->a_fitness) break; temp[j] = temp[j - 1]; } if (j < s->bestn) temp[j] = pop->ind + i; if (b < s->bestn) ++b; } /** now save copies of the individuals in the "temp" list **/ for (i = 0; i < b; ++i) { shp = (saved_ind *) MALLOC(sizeof(saved_ind)); shp->ind = (individual *) MALLOC(sizeof(individual)); shp->ind->tr = (tree *) MALLOC(tree_count * sizeof(tree)); duplicate_individual(shp->ind, temp[i]); for (j = 0; j < tree_count; ++j) reference_ephem_constants(shp->ind->tr[j].data, 1); shp->refcount = 1; shp->next = NULL; saved_tail->next = shp; saved_tail = shp; ++saved_head->refcount; s->best[i] = shp; } #ifdef DEBUG printf ( "the best list is:\n" ); for ( j = 0; j < s->bestn; ++j ) printf ( " %08x %lf\n", s->best[j], s->best[j]->ind->a_fitness ); #endif FREE(temp); }
void operator_crossover ( population *oldpop, population *newpop, void *data ) { crossover_data * cd; int p1, p2; int ps1, ps2; int l1, l2; lnode *st[3]; int sts1, sts2; int ns1, ns2; int badtree1, badtree2; double total; int forceany1, forceany2; int repcount; int f, t1, t2, j; double r, r2; int totalnodes1, totalnodes2; int i; /* get the crossover-specific data structure. */ cd = (crossover_data *)data; total = cd->internal + cd->external; /* choose a function set. */ r = random_double() * cd->treetotal; for ( f = 0; r >= cd->func[f]; ++f ); /* fill in the "treecumul" array, zeroing all trees which don't use the selected function set. */ r = 0.0; t1 = 0; for ( j = 0; j < tree_count; ++j ) { if ( tree_map[j].fset == f ) r = (cd->treecumul[j] = r + cd->tree[j]); else cd->treecumul[j] = r; } /* select the first and second trees. */ r2 = random_double() * r; for ( t1 = 0; r2 >= cd->treecumul[t1]; ++t1 ); r2 = random_double() * r; for ( t2 = 0; r2 >= cd->treecumul[t2]; ++t2 ); #ifdef DEBUG_CROSSOVER printf ( "selected function set %d --> t1: %d; t2: %d\n", f, t1, t2 ); #endif /* choose two parents */ p1 = cd->sc->select_method ( cd->sc ); ps1 = oldpop->ind[p1].tr[t1].nodes; /* if the tree only has one node, we obviously can't do fucntionpoint crossover. use anypoint instead. */ forceany1 = (ps1==1||total==0.0); p2 = cd->sc2->select_method ( cd->sc2 ); ps2 = oldpop->ind[p2].tr[t2].nodes; forceany2 = (ps2==1||total==0.0); #ifdef DEBUG_CROSSOVER fprintf ( stderr, "parent 1 is:\n" ); print_individual ( oldpop->ind+p1, stderr ); fprintf ( stderr, "parent 2 is:\n" ); print_individual ( oldpop->ind+p2, stderr ); #endif while(1) { /* choose two crossover points */ if ( forceany1 ) { /* choose any point. */ l1 = random_int ( ps1 ); st[1] = get_subtree ( oldpop->ind[p1].tr[t1].data, l1 ); } else if ( total*random_double() < cd->internal ) { /* choose an internal point. */ l1 = random_int ( tree_nodes_internal (oldpop->ind[p1].tr[t1].data) ); st[1] = get_subtree_internal ( oldpop->ind[p1].tr[t1].data, l1 ); } else { /* choose an external point. */ l1 = random_int ( tree_nodes_external (oldpop->ind[p1].tr[t1].data) ); st[1] = get_subtree_external ( oldpop->ind[p1].tr[t1].data, l1 ); } if ( forceany2 ) { /* choose any point on second parent. */ l2 = random_int ( ps2 ); st[2] = get_subtree ( oldpop->ind[p2].tr[t2].data, l2 ); } else if ( total*random_double() < cd->internal ) { /* choose internal point. */ l2 = random_int ( tree_nodes_internal (oldpop->ind[p2].tr[t2].data) ); st[2] = get_subtree_internal ( oldpop->ind[p2].tr[t2].data, l2 ); } else { /* choose external point. */ l2 = random_int ( tree_nodes_external (oldpop->ind[p2].tr[t2].data) ); st[2] = get_subtree_external ( oldpop->ind[p2].tr[t2].data, l2 ); } #ifdef DEBUG_CROSSOVER printf ( "subtree 1 is: " ); print_tree ( st[1], stdout ); printf ( "subtree 2 is: " ); print_tree ( st[2], stdout ); #endif /* count the nodes in the selected subtrees. */ sts1 = tree_nodes ( st[1] ); sts2 = tree_nodes ( st[2] ); /* calculate the sizes of the offspring. */ ns1 = ps1 - sts1 + sts2; ns2 = ps2 - sts2 + sts1; totalnodes1 = ns1; totalnodes2 = ns2; #ifdef DEBUG_CROSSOVER printf ( "newtree 1 has size %d; limit is %d\n", ns1, tree_map[t1].nodelimit ); #endif /** validate the first offspring against the tree node and depth limits; set "badtree1" if any are violated. **/ badtree1 = 0; if ( tree_map[t1].nodelimit > -1 && ns1 > tree_map[t1].nodelimit ) badtree1 = 1; else if ( tree_map[t1].depthlimit > -1 ) { ns1 = tree_depth_to_subtree ( oldpop->ind[p1].tr[t1].data, st[1] ) + tree_depth ( st[2] ); #ifdef DEBUG_CROSSOVER printf ( "newtree 1 has depth %d; limit is %d\n", ns1, tree_map[t1].depthlimit ); #endif if ( ns1 > tree_map[t1].depthlimit ) badtree1 = 1; } /* if we're supposed to keep trying, skip up and choose new crossover points. */ if ( cd->keep_trying && badtree1 ) continue; /** validate the second offspring against the tree node and depth limits; set "badtree2" if any are violated. **/ badtree2 = 0; if ( tree_map[t2].nodelimit > -1 && ns2 > tree_map[t2].nodelimit ) badtree2 = 1; else if ( tree_map[t2].depthlimit > -1 ) { ns2 = tree_depth_to_subtree ( oldpop->ind[p2].tr[t2].data, st[2] ) + tree_depth ( st[1] ); if ( ns2 > tree_map[t2].depthlimit ) badtree2 = 1; } /* if we're supposed to keep trying, skip up and choose new crossover points. */ if ( cd->keep_trying && badtree2 ) continue; /* check both offspring against the individual node limits, set badtree1 and/or badtree2 if either is too big. */ if ( ind_nodelimit > -1 ) { for ( i = 0; i < tree_count; ++i ) { if ( i != t1 ) totalnodes1 += oldpop->ind[p1].tr[i].nodes; if ( i != t2 ) totalnodes2 += oldpop->ind[p2].tr[i].nodes; } badtree1 |= (totalnodes1 > ind_nodelimit); badtree2 |= (totalnodes2 > ind_nodelimit); #ifdef DEBUG_CROSSOVER printf ( "newind 1 has %d nodes; limit is %d\n", totalnodes1, ind_nodelimit ); #endif } /* choose new crossover points if either tree is too big. */ if ( cd->keep_trying && (badtree1 || badtree2) ) continue; /* copy the first parent to the first offspring position */ duplicate_individual ( newpop->ind+newpop->next, oldpop->ind+p1 ); if ( !badtree1 ) { /* if the first offspring is allowable... */ #ifdef DEBUG_CROSSOVER fprintf ( stderr, "offspring 1 is allowable.\n" ); #endif /* make a copy of the crossover tree, replacing the selected subtree with the crossed-over subtree. */ copy_tree_replace_many ( 0, oldpop->ind[p1].tr[t1].data, st+1, st+2, 1, &repcount ); if ( repcount != 1 ) { /* this can't happen, but check anyway. */ error ( E_FATAL_ERROR, "botched crossover: this can't happen" ); } /* free the appropriate tree of the new individual */ free_tree ( newpop->ind[newpop->next].tr+t1 ); /* copy the crossovered tree to the freed space */ gensp_dup_tree ( 0, newpop->ind[newpop->next].tr+t1 ); /* the new individual's fitness fields are of course invalid. */ newpop->ind[newpop->next].evald = EVAL_CACHE_INVALID; newpop->ind[newpop->next].flags = FLAG_NONE; } else { /* offspring too big but keep_trying not set, just leave the copied parent 1 in the offspring position. */ #ifdef DEBUG_CROSSOVER fprintf ( stderr, "offspring 1 is too big; copying parent 1.\n" ); #endif } /* we've just filled in one member of the new population. */ ++newpop->next; #ifdef DEBUG_CROSSOVER fprintf ( stderr, "offspring 1:" ); if ( newpop->ind[newpop->next-1].evald == EVAL_CACHE_VALID ) fprintf ( stderr, " (valid)\n" ); else fprintf ( stderr, " (invalid)\n" ); print_individual ( newpop->ind+(newpop->next-1), stderr ); #endif /* if the new population needs another member (it's not full) */ if ( newpop->next < newpop->size ) { /* copy the second parent to the second offspring position. */ duplicate_individual ( newpop->ind+newpop->next, oldpop->ind+p2 ); if ( !badtree2 ) { /* if the second offspring is allowable... */ #ifdef DEBUG_CROSSOVER fprintf ( stderr, "offspring 2 is allowable.\n" ); #endif /* then make a copy of the tree, replacing the crossover subtree. */ copy_tree_replace_many ( 0, oldpop->ind[p2].tr[t2].data, st+2, st+1, 1, &repcount ); if ( repcount != 1 ) { error ( E_FATAL_ERROR, "bad crossover: this can't happen" ); } /* free the old tree in the new individual, and replace it with the crossover tree. */ free_tree ( newpop->ind[newpop->next].tr+t2 ); gensp_dup_tree ( 0, newpop->ind[newpop->next].tr+t2 ); newpop->ind[newpop->next].evald = EVAL_CACHE_INVALID; newpop->ind[newpop->next].flags = FLAG_NONE; } else { /* offspring too big but keep_trying not set; just leave the copy of parent 2 where it is. */ #ifdef DEBUG_CROSSOVER fprintf ( stderr, "offspring 2 is big; copying parent 2.\n" ); #endif } ++newpop->next; #ifdef DEBUG_CROSSOVER fprintf ( stderr, "offspring 2:" ); if ( newpop->ind[newpop->next-1].evald == EVAL_CACHE_VALID ) fprintf ( stderr, " (valid)\n" ); else fprintf ( stderr, " (invalid)\n" ); print_individual ( newpop->ind+(newpop->next-1), stderr ); #endif } #ifdef DEBUG_CROSSOVER else { /* the first offspring filled the population, discard the second. */ fprintf ( stderr, "offspring 2 not needed.\n\n" ); } #endif break; } #ifdef DEBUG_CROSSOVER printf ( "CROSSOVER COMPLETE.\n\n\n" ); #endif }