/// todo: create a function that return the pop/chromosome size for brievty void Popu::mutate(int pos){ /// given an offspring we mutate it at a certain rate and create the new population int pos1=0,pos2=3;//size=offspring.elements.size(); QTime t;int rd=3; Chromosome mutant; ///NOTE: As we kept the 2 best parents as are (ellitisme) we start from 2 for (int i=0;i<2;i++){ if (i==0) mutant=parentOne; else mutant=parentTwo; for (int j=0;j<chromoSize;j++){ rd=qrand()%chromoSize; //qDebug()<<rd; ///DFFIXME : make it dependant on a variable value Mut_prob the probability should be small if (rd >chromoSize-(chromoSize/5)) { //qDebug()<<"creating a mutant"; pos1=qrand()%chromoSize; //qsrand(QTime::msec ()); pos2=qrand()%chromoSize; //qDebug()<<pos2<<pos1; //mutant.elements.swap(pos1,pos2); swapVals(mutant.elements,pos1,pos2); } ///qDebug()<<mutant.elements<<"route"<< mutant.routeLength; } mutant.setRoutelength(); ///qDebug()<<"creating a mutant at "<<pos+i<<"routes"<< mutant.routeLength; newGen.replace(pos+i,mutant); //qDebug()<<newGen.size(); } }
void Popu::mutateImprove(int pos){ //qDebug()<<"not mutant"; Chromosome toImprove; /// Time to improve the route (randomly for now) even the elite are concerned for (int i=0;i<2;i++){ if (i==0) toImprove=parentOne; else toImprove=parentTwo; ///qDebug()<<"Trying to improve parent n°"<<pos+i; ///FOR debug remove me! int orignalRouteLength=toImprove.routeLength; for (int j=0;j<chromoSize*2;j++){ int pos1=qrand()%chromoSize; int pos2=qrand()%chromoSize; int oldRouteLength=toImprove.routeLength; //toImprove.elements.swap(pos1,pos2); swapVals(toImprove.elements,pos1,pos2); toImprove.setRoutelength(); // qDebug()<<toImprove.routeLength<<oldRouteLength; ///undo changes as this become worse than before if ( toImprove.routeLength>oldRouteLength){ //toImprove.elements.swap(pos1,pos2); swapVals(toImprove.elements,pos1,pos2); toImprove.setRoutelength();/// could be simplier =oldRouteLength ? //qDebug()<<"no changes"; } else{ ///Improving (keeping changes) } } newGen.replace(i+pos,toImprove); ///qDebug()<<"Improved*********"<<toImprove.routeLength<<orignalRouteLength; //qDebug()<<toImprove.elements; //qDebug()<<"improved mutant routes"<< toImprove.routeLength; } }
/// returns an offspring from 2 parents Chromosome Popu::cross(Chromosome parent1, Chromosome parent2){ int i=0,pos=0,posOther=0,sizeFixe=parent2.elements.size()-1,size=parent2.elements.size()-1; double dist1=0,dist2=0; QPointFWithParent currentVal=parent1.elements.at(0); QPointFWithParent otherVal=parent2.elements.at(1),nextVal=parent1.elements.at(1); /// the other chromosome when working with p1 it's p2 and vice versa Chromosome activeParent=parent1; Chromosome otherParent=parent2; int activeParentRef=1; /// this reference chromosem is used when need to insert a random elment, as we delete from it every /// elmenet we append to the offsprings, we're sure we don't append duplicate points Chromosome referenceParent; referenceParent.elements=parent2.elements;/// could be parent1 also Chromosome offspring; //qDebug()<<"creating an offspring of "<<size+1<<"elements"; for (int i=0;i< sizeFixe-2;i++){ posOther=otherParent.elements.indexOf(currentVal); pos=activeParent.elements.indexOf(currentVal); ///check for case at list end => start at a random pos if so /// if (posOther==size ){ ///TODO:try with the other point before giving up ///if (referenceParent.elements.size()!=0){ /// int j=0; /// while (offspring.elements.contains(referenceParent.elements.at(j))){ /// posOther=otherParent.elements.indexOf(referenceParent.elements.at(j)); /// qDebug()<<"looping back randomly";j++; /// } /// qDebug()<<"stopped at" <<j; ///} ///} /// if (pos==size) { /// if (referenceParent.elements.size()!=0){ /// int k=0; /// while (offspring.elements.contains(referenceParent.elements.at(k))){ /// posOther=otherParent.elements.indexOf(referenceParent.elements.at(k)); /// qDebug()<<"looping back randomly";k++;///i++; /// } /// qDebug()<<"stopped at" <<k; //currentVal=referenceParent->elements.takeAt(0); /// } ///} /// qDebug()<<"We're in pos="<<pos<<" Other parent contains"<<currentVal<<" at pos"<<posOther<<"size="<<size; /// recheck if the random city is at list end : this tile we have to go to list begin if (posOther==size || posOther>size) { ///TODO:try with the other point before giving up posOther=0;///qDebug()<<"have to loop back"; } if (pos==size || pos>size){ pos=0;///qDebug()<<"have to loop back"; } /// get the next 'city' coordinates to compute how far is it otherVal=otherParent.elements.at(posOther+1); //qDebug()<<"deciding wich paretn to keep with"; //qDebug()<<activeParent->elements; nextVal=activeParent.elements.at(pos+1); /// the distance from the other parent cuurent point to next point in it dist2=dist(otherVal,currentVal); /// the distance from curretn parent to next point in active parent dist1=dist(nextVal,currentVal); /// if dist1<dist2 have to copy the path from the other parent and make it the active one; /// UNLES it's already prensent in the offspring offspring.elements.append(currentVal); referenceParent.elements.remove(referenceParent.elements.indexOf(currentVal)); parent1.elements.remove(parent1.elements.indexOf(currentVal)); parent2.elements.remove(parent2.elements.indexOf(currentVal)); size=parent2.elements.size()-1; ///qDebug()<<parent2.elements<<parent1.elements; if (dist2 < dist1) { ///qDebug()<<"switching to other parent"; if (offspring.elements.contains(otherVal)){ qDebug()<<"Point already presnet: forcing the other"; if (!offspring.elements.contains(nextVal)){ activeParent=parent2;otherParent=parent1;activeParentRef=2; currentVal=nextVal; continue; } /// use a random take if (referenceParent.elements.size()!=0){ qDebug()<<"Everything failed :setting a random point"; currentVal=referenceParent.elements.at(0); referenceParent.elements.remove(0); } else{ ///fixme qDebug()<<"Nothing to take from reference!!??"; break; } ///i++;///time to continue; } /// change the active parent if (activeParentRef==2){ activeParent=parent2;otherParent=parent1;activeParentRef=2; } else{ activeParent=parent1;otherParent=parent2;activeParentRef=1; } /// update current val currentVal=otherVal; } /// continue with the current parent else{ ///qDebug()<<"Continuing with this parent"; //offspring->elements.append(currentVal); ///offspring->elements.append(nextVal); ///keeping the parent //activeParent=parent1;otherParent=parent2; /// update current val currentVal=nextVal; } //qDebug()<<offspring.elements; } ///offspring->elements.append(currentVal); /// finally add the only point that remain in the ref chromosome //if (referenceParent.elements.size()!=0){ offspring.elements.append(referenceParent.elements.at(0)); referenceParent.elements.remove(0); offspring.elements.append(referenceParent.elements.at(0)); referenceParent.elements.remove(0); //} offspring.setRoutelength(); return offspring; }