/* A class to control a group of Creatures. Handles fitness evaluation, simulation, and generational construction. */ public class Population { // maximum members of the population int maxPopulation; // genetic mutation rate float mutationRate; // our creatures Creature[] creatures; // gene pool for mating ArrayList genePool; // number of elapsed generations int generations; // keep track of how many creatures have finished int finishOrder; public Population(float mutationRate_, int maxPopulation_) { // store our parameters mutationRate = mutationRate_; maxPopulation = maxPopulation_; // create our control variables genePool = new ArrayList(); generations = 0; finishOrder = 1; // construct our creature list creatures = new Creature[maxPopulation]; for (int i = 0; i < creatures.length; i++) { creatures[i] = new Creature(start.copy(), new DNA(DNASIZE), creatures.length); } } /* Let every creature do their thing */ public void simulate(ArrayList obstacles) { for (int i = 0; i < creatures.length; i++) { // figure out if the creature reached it's target if ( (creatures[i].isFinished()) && (creatures[i].isActive()) ) { creatures[i].setFinishOrder(finishOrder); finishOrder++; } // let the creature run creatures[i].simulate(obstacles); } } /* figure out if anything reached the target */ public boolean targetReached() { for (int i = 0; i < creatures.length; i++) { if (creatures[i].isFinished()) { return true; } } return false; } /* Figure out the fitness for each creature */ void calcFitness() { for (int i = 0; i < creatures.length; i++) { creatures[i].calcFitness(); } // strange for this to be here, but it works finishOrder = 1; } /* Create our gene pool for the next generation */ public void naturalSelection() { // clear the genetic pool genePool.clear(); // get the total fitness of the creatures float totalFitness = getTotalFitness(); // figure out a noramlized fitness for each creature, the ratio of its fitness // to the fitness of the entire population. This is a fraction we use to determine // how many copies of the creature go into the genetic pool for (int i = 0; i < creatures.length; i++) { // get the fitness normal float fitNormal = creatures[i].getFitness() / totalFitness; // figure out how many copies to add int copies = (int) (fitNormal * 50000.0); // add the copies for (int j = 0; j < copies; j++) { genePool.add(creatures[i]); } } } public void generate() { // create a new generation, one by one walking through the creatures array // to fill it in by mating two random selections from the gene pool for (int i = 0; i < creatures.length; i++) { // figure out the "mom" and "dad" int m = (int)random(genePool.size()); int d = (int)random(genePool.size()); Creature mom = (Creature)genePool.get(m); Creature dad = (Creature)genePool.get(d); // get the genes for each creatures DNA mDNA = mom.getGenes(); DNA dDNA = dad.getGenes(); // mate DNA cDNA = mDNA.mate(dDNA); // mutate cDNA.mutate(mutationRate); // fill the creatures spot creatures[i] = new Creature(start.copy(), cDNA, creatures.length); } generations++; } int getGenerations() { return generations; } float getTotalFitness() { float total = 0.0; for (int i = 0; i < creatures.length; i++) { total += creatures[i].getFitness(); } return total; } }