Files
sunny9898/task8/_ref/noc-examples-processing-master/chp09_ga/EvolveFlowField/Population.pde
louiscklaw 5637fbf94f update,
2025-02-01 02:07:58 +08:00

143 lines
4.2 KiB
Plaintext

// The Nature of Code
// Daniel Shiffman
// http://natureofcode.com
// A class to describe a population of "creatures"
class Population {
float mutationRate; // Mutation rate
Rocket[] population; // Array to hold the current population
ArrayList<Rocket> darwin; // ArrayList which we will use for our "mating pool"
int generations; // Number of generations
int order; // Keep track of the order of creature's finishing the maze
// Initialize the population
Population(float m, int num) {
mutationRate = m;
population = new Rocket[num];
darwin = new ArrayList<Rocket>();
generations = 0;
//make a new set of creatures
for (int i = 0; i < population.length; i++) {
PVector position = new PVector(start.r.x+start.r.width/2, start.r.y+start.r.height/2);
population[i] = new Rocket(position, new DNA(dnasize));
}
order = 1; // The first one to finish will be #1
}
void live (ArrayList<Obstacle> o) {
// For every creature
float record = 100000;
int closest = 0;
for (int i = 0; i < population.length; i++) {
// If it finishes, mark it down as done!
if ((population[i].finished())) {
population[i].setFinish(order);
order++;
}
// Run it
population[i].run(o);
if (population[i].recordDist < record) {// && !population[i].dead) {
record = population[i].recordDist;
closest = i;
}
}
population[closest].highlight();
// Drawing one example of the DNA
if (debug) {
population[closest].dna.debugDraw();
}
}
// Did anything finish?
boolean targetReached() {
for (int i = 0; i < population.length; i++) {
if (population[i].finished()) return true;
}
return false;
}
// Calculate fitness for each creature
void calcFitness() {
for (int i = 0; i < population.length; i++) {
population[i].calcFitness();
}
order = 1; // Hmmm, awkward place for this, we have to reset this for the next generation
}
// Generate a mating pool
void naturalSelection() {
// Clear the ArrayList
darwin.clear();
// Calculate total fitness of whole population
float totalFitness = getTotalFitness();
float avgFitness = totalFitness/population.length;
// Calculate normalized fitness for each member of the population
// Based on normalized fitness, each member will get added to the mating pool a certain number of times a la roulette wheel
// A higher fitness = more entries to mating pool = more likely to be picked as a parent
// A lower fitness = fewer entries to mating pool = less likely to be picked as a parent
int count = 0;
for (int i = 0; i < population.length; i++) {
float fitness = population[i].getFitness();
//if (fitness > avgFitness) {
count++;
float fitnessNormal = fitness / totalFitness;
int n = (int) (fitnessNormal * 50000); // Arbitrary multiplier, consider mapping fix
for (int j = 0; j < n; j++) {
darwin.add(population[i]);
}
//}
}
//println("Total: " + count + " " + population.length);
}
// Making the next generation
void generate() {
// Refill the population with children from the mating pool
for (int i = 0; i < population.length; i++) {
int m = int(random(darwin.size()));
int d = int(random(darwin.size()));
// Pick two parents
Rocket mom = darwin.get(m);
Rocket dad = darwin.get(d);
// Get their genes
DNA momgenes = mom.getDNA();
DNA dadgenes = dad.getDNA();
// Mate their genes
DNA child = momgenes.crossover(dadgenes);
// Mutate their genes
child.mutate(mutationRate);
// Fill the new population with the new child
PVector position = new PVector(start.r.x+start.r.width/2, start.r.y+start.r.height/2);
population[i] = new Rocket(position, child);
}
generations++;
}
int getGenerations() {
return generations;
}
//compute total fitness for the population
float getTotalFitness() {
float total = 0;
for (int i = 0; i < population.length; i++) {
total += population[i].getFitness();
}
return total;
}
}