/// Do the scaling on the population. Like the statistics and diversity, this /// method does not change the contents of the population, but it does change /// the values of the status members of the object. So we allow it to work on /// a const population. void GAPopulation::scale(GABoolean flag) const { if(scaled == gaTrue && flag != gaTrue) { return; } GAPopulation* This = (GAPopulation*)this; if(n > 0) { sclscm->evaluate(*This); float tmpsum; This->fitMin = This->fitMax = tmpsum = sind[0]->fitness(); unsigned int i; for(i = 1; i < n; i++) { tmpsum += sind[i]->fitness(); This->fitMax = GAMax(fitMax, sind[i]->fitness()); This->fitMin = GAMin(fitMin, sind[i]->fitness()); } float tmpave = tmpsum / n; This->fitAve = tmpave; This->fitSum = tmpsum; /// if scores are huge we'll lose data here float tmpvar = 0.0; if(n > 1) { for(i = 0; i < n; i++) { float s = sind[i]->fitness() - This->fitAve; s *= s; tmpvar += s; } tmpvar /= (n - 1); } This->fitDev = (float)sqrt(tmpvar); This->fitVar = tmpvar; /// could lose data if huge variance } else { This->fitMin = This->fitMax = This->fitSum = 0.0; This->fitVar = This->fitDev = 0.0; } This->scaled = gaTrue; This->ssorted = gaFalse; }
/// Evaluate each member of the population and store basic population statistics /// in the member variables. It is OK to run this on a const object - it /// changes to physical state of the population, but not the logical state. /// The partial sums are normalized to the range [0,1] so that they can be /// used whether the population is sorted as low-is-best or high-is-best. /// Individual 0 is always the best individual, and the partial sums are /// calculated so that the worst individual has the smallest partial sum. All /// of the partial sums add to 1.0. void GAPopulation::statistics(GABoolean flag) const { if(statted == gaTrue && flag != gaTrue) { return; } GAPopulation * This = (GAPopulation *)this; if(n > 0) { float tmpsum; This->rawMin = This->rawMax = tmpsum = rind[0]->score(); unsigned int i; for(i = 1; i < n; i++) { float scr = rind[i]->score(); tmpsum += scr; This->rawMax = GAMax(rawMax, scr); This->rawMin = GAMin(rawMin, scr); } float tmpave = tmpsum / n; This->rawAve = tmpave; This->rawSum = tmpsum; /// if scores are huge we'll lose data here float tmpvar = 0.0; if(n > 1) { for(i = 0; i < n; i++) { float s = rind[i]->score() - This->rawAve; s *= s; tmpvar += s; } tmpvar /= (n - 1); } This->rawDev = (float)sqrt(tmpvar); This->rawVar = tmpvar; /// could lose data if huge variance } else { This->rawMin = This->rawMax = This->rawSum = 0.0; This->rawDev = This->rawVar = 0.0; } This->statted = gaTrue; }
// Make sure our bitmask is big enough, generate a mask, then use it to // extract the information from each parent to stuff the two children. // We don't deallocate any space for the masks under the assumption that we'll // have to use them again in the future. // For now we'll implement this only for fixed length genomes. If you use // this crossover method on genomes of different sizes it might break! int GA3DBinaryStringGenome:: UniformCrossover(const GAGenome& p1, const GAGenome& p2, GAGenome* c1, GAGenome* c2){ GA3DBinaryStringGenome &mom=(GA3DBinaryStringGenome &)p1; GA3DBinaryStringGenome &dad=(GA3DBinaryStringGenome &)p2; int i,j,k, nc=0;; if(c1 && c2){ GA3DBinaryStringGenome &sis=(GA3DBinaryStringGenome &)*c1; GA3DBinaryStringGenome &bro=(GA3DBinaryStringGenome &)*c2; if(sis.width() == bro.width() && sis.height() == bro.height() && sis.depth() == bro.depth() && mom.width() == dad.width() && mom.height() == dad.height() && mom.depth() == dad.depth() && sis.width() == mom.width() && sis.height() == mom.height() && sis.depth() == mom.depth()){ for(i=sis.width()-1; i>=0; i--){ for(j=sis.height()-1; j>=0; j--){ for(k=sis.depth()-1; k>=0; k--){ if(GARandomBit()){ sis.gene(i,j,k, mom.gene(i,j,k)); bro.gene(i,j,k, dad.gene(i,j,k)); } else{ sis.gene(i,j,k, dad.gene(i,j,k)); bro.gene(i,j,k, mom.gene(i,j,k)); } } } } } else{ GAMask mask; int maxx = GAMax(sis.width(), bro.width()); int minx = GAMin(mom.width(), dad.width()); int maxy = GAMax(sis.height(), bro.height()); int miny = GAMin(mom.height(), dad.height()); int maxz = GAMax(sis.depth(), bro.depth()); int minz = GAMin(mom.depth(), dad.depth()); mask.size(maxx*maxy*maxz); for(i=0; i<maxx; i++) for(j=0; j<maxy; j++) for(k=0; k<maxz; k++) mask[i*maxy*maxz+j*maxz+k] = GARandomBit(); minx = GAMin(sis.width(), minx); miny = GAMin(sis.height(), miny); minz = GAMin(sis.depth(), minz); for(i=minx-1; i>=0; i--) for(j=miny-1; j>=0; j--) for(k=minz-1; k>=0; k--) sis.gene(i,j,k, (mask[i*miny*minz+j*minz+k] ? mom.gene(i,j,k) : dad.gene(i,j,k))); minx = GAMin(bro.width(), minx); miny = GAMin(bro.height(), miny); minz = GAMin(bro.depth(), minz); for(i=minx-1; i>=0; i--) for(j=miny-1; j>=0; j--) for(k=minz-1; k>=0; k--) bro.gene(i,j,k, (mask[i*miny*minz+j*minz+k] ? dad.gene(i,j,k) : mom.gene(i,j,k))); } nc = 2; } else if(c1 || c2){ GA3DBinaryStringGenome &sis = (c1 ? (GA3DBinaryStringGenome&)*c1 : (GA3DBinaryStringGenome&)*c2); if(mom.width() == dad.width() && mom.height() == dad.height() && mom.depth() == dad.depth() && sis.width() == mom.width() && sis.height() == mom.height() && sis.depth() == mom.depth()){ for(i=sis.width()-1; i>=0; i--) for(j=sis.height()-1; j>=0; j--) for(k=sis.depth()-1; k>=0; k--) sis.gene(i,j,k, (GARandomBit() ? mom.gene(i,j,k):dad.gene(i,j,k))); } else{ int minx = GAMin(mom.width(), dad.width()); int miny = GAMin(mom.height(), dad.height()); int minz = GAMin(mom.depth(), dad.depth()); minx = GAMin(sis.width(), minx); miny = GAMin(sis.height(), miny); minz = GAMin(sis.depth(), minz); for(i=minx-1; i>=0; i--) for(j=miny-1; j>=0; j--) for(k=minz-1; k>=0; k--) sis.gene(i,j,k, (GARandomBit() ? mom.gene(i,j,k):dad.gene(i,j,k))); } nc = 1; } return nc; }