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