kopia lustrzana https://github.com/villares/sketch-a-day
main
rodzic
c41dfab9f8
commit
50821b3924
|
@ -1,5 +1,5 @@
|
|||
// Alexandre B A Villares - https://abav.lugaralgum.com/sketch-a-day
|
||||
// s182 20180629
|
||||
// s183 20180701
|
||||
// Based on GA from The Nature of Code by Daniel Shiffman http://natureofcode.com
|
||||
|
||||
Population population;
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
// The Nature of Code
|
||||
// Daniel Shiffman
|
||||
// http://natureofcode.com
|
||||
|
||||
// Interactive Selection
|
||||
// http://www.genarts.com/karl/papers/siggraph91.html
|
||||
|
||||
class DNA {
|
||||
|
||||
// The genetic sequence
|
||||
float[] genes;
|
||||
int len = 40; // Arbitrary length
|
||||
|
||||
//Constructor (makes a random DNA)
|
||||
DNA() {
|
||||
// DNA is random floating point values between 0 and 1 (!!)
|
||||
genes = new float[len];
|
||||
for (int i = 0; i < genes.length; i++) {
|
||||
genes[i] = random(0,1);
|
||||
}
|
||||
}
|
||||
|
||||
DNA(float[] newgenes) {
|
||||
genes = newgenes;
|
||||
}
|
||||
|
||||
|
||||
// Crossover
|
||||
// Creates new DNA sequence from two (this &
|
||||
DNA crossover(DNA partner) {
|
||||
float[] child = new float[genes.length];
|
||||
int crossover = int(random(genes.length));
|
||||
for (int i = 0; i < genes.length; i++) {
|
||||
if (i > crossover) child[i] = genes[i];
|
||||
else child[i] = partner.genes[i];
|
||||
}
|
||||
DNA newgenes = new DNA(child);
|
||||
return newgenes;
|
||||
}
|
||||
|
||||
// Based on a mutation probability, picks a new random character in array spots
|
||||
void mutate(float m) {
|
||||
for (int i = 0; i < genes.length; i++) {
|
||||
if (random(1) < m) {
|
||||
genes[i] = random(0,1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
// The Nature of Code
|
||||
// Daniel Shiffman
|
||||
// http://natureofcode.com
|
||||
// Interactive Selection
|
||||
// http://www.genarts.com/karl/papers/siggraph91.html
|
||||
|
||||
// The class for our "organism", contains DNA sequence, fitness value, position on screen
|
||||
// Fitness Function f(t) = t (where t is "time" mouse rolls over organism)
|
||||
|
||||
class Organism {
|
||||
|
||||
DNA dna; // organism's DNA
|
||||
float fitness; // How good is this organism?
|
||||
float x, y; // Position on screen
|
||||
int wh = 110; // Size of square enclosing organism
|
||||
boolean mouseIsOver; // Are we rolling over this organism?
|
||||
|
||||
// Create a new organism
|
||||
Organism(DNA dna_, float x_, float y_) {
|
||||
dna = dna_;
|
||||
x = x_;
|
||||
y = y_;
|
||||
fitness = 1;
|
||||
}
|
||||
|
||||
// Display the organism
|
||||
void display() {
|
||||
// We are using the organism's DNA to pick properties for this organism
|
||||
// Now, since every gene is a floating point between 0 and 1, we map the values
|
||||
int n = int(map(dna.genes[0]+dna.genes[39], 0, 2, 3, 19));
|
||||
pushMatrix();
|
||||
pushStyle();
|
||||
translate(x, y);
|
||||
for (int i = 2; i < n; i = i + 2) {
|
||||
stroke(1);
|
||||
stroke(dna.genes[i-1], 1, 1);
|
||||
noFill();
|
||||
float x1 = map(dna.genes[i], 0, 1, -wh/4, wh/4);
|
||||
float y1 = map(dna.genes[i+1], 0, 1, -wh/4, wh/4);
|
||||
float x2 = map(dna.genes[i*2], 0, 1, -wh/4, wh/4);
|
||||
float y2 = map(dna.genes[i*2+1], 0, 1, -wh/4, wh/4);
|
||||
float x3 = map(dna.genes[i-1], 0, 1, wh/10, wh/4);
|
||||
float y3 = map(dna.genes[i*2-1], 0, 1, wh/10, wh/4);
|
||||
triangle(x1, y1, x2, y2, x3, y3);
|
||||
}
|
||||
// Draw the bounding box
|
||||
popStyle();
|
||||
|
||||
rectMode(CENTER);
|
||||
|
||||
if (mouseIsOver) fill(0.5, 0.5);
|
||||
else noFill();
|
||||
|
||||
stroke(1);
|
||||
rect(0, 0, wh, wh);
|
||||
stroke(0.5);
|
||||
line(-wh/2, 0, wh/2, 0);
|
||||
line(0, -wh/2, 0, wh/2);
|
||||
popMatrix();
|
||||
|
||||
// Display fitness value
|
||||
textAlign(CENTER);
|
||||
fill(1);
|
||||
text(fitness, x, y+70);
|
||||
}
|
||||
|
||||
float getFitness() {
|
||||
return fitness;
|
||||
}
|
||||
|
||||
DNA getDNA() {
|
||||
return dna;
|
||||
}
|
||||
|
||||
// Increment fitness if mouse is rolling over organism
|
||||
void checkMouseOver(int mx, int my) {
|
||||
int cx = int(x-wh/2);
|
||||
int cy = int(y-wh/2);
|
||||
if (mx > cx && mx < cx + wh && my > cy && my < cy + wh) {
|
||||
mouseIsOver = true;
|
||||
if (mousePressed) fitness += 0.25;
|
||||
} else {
|
||||
mouseIsOver = false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
// The Nature of Code
|
||||
// Daniel Shiffman
|
||||
// http://natureofcode.com
|
||||
|
||||
// Interactive Selection
|
||||
// http://www.genarts.com/karl/papers/siggraph91.html
|
||||
|
||||
// A class to describe a population of faces
|
||||
// this hasn't changed very much from example to example
|
||||
|
||||
class Population {
|
||||
|
||||
float mutationRate; // Mutation rate
|
||||
Organism[] population; // array to hold the current population
|
||||
ArrayList<Organism> matingPool; // ArrayList which we will use for our "mating pool"
|
||||
int generations; // Number of generations
|
||||
|
||||
// Create the population
|
||||
Population(float m, int num) {
|
||||
mutationRate = m;
|
||||
population = new Organism[num];
|
||||
matingPool = new ArrayList<Organism>();
|
||||
generations = 0;
|
||||
//for (int i = 0; i < population.length; i++) {
|
||||
// population[i] = new Organism(new DNA(), 50+i*88.5, 60);
|
||||
//}
|
||||
float s = width/5.2;
|
||||
int i = 0;
|
||||
for (int x = 0; x < 5; x++) {
|
||||
for (int y = 0; y < 5; y++) {
|
||||
population[i] = new Organism(new DNA(), s/1.75+x*s, s/1.75+y*s);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Display all faces
|
||||
void display() {
|
||||
for (int i = 0; i < population.length; i++) {
|
||||
population[i].display();
|
||||
}
|
||||
}
|
||||
|
||||
// Are we rolling over any of the faces?
|
||||
void rollover(int mx, int my) {
|
||||
for (int i = 0; i < population.length; i++) {
|
||||
population[i].checkMouseOver(mx, my);
|
||||
}
|
||||
}
|
||||
|
||||
// Generate a mating pool
|
||||
void selection() {
|
||||
// Clear the ArrayList
|
||||
matingPool.clear();
|
||||
|
||||
// Calculate total fitness of whole population
|
||||
float maxFitness = getMaxFitness();
|
||||
|
||||
// Calculate fitness for each member of the population (scaled to value between 0 and 1)
|
||||
// Based on fitness, each member will get added to the mating pool a certain number of times
|
||||
// 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
|
||||
for (int i = 0; i < population.length; i++) {
|
||||
float fitnessNormal = map(population[i].getFitness(), 0, maxFitness, 0, 1);
|
||||
int n = (int) (fitnessNormal * 100); // Arbitrary multiplier
|
||||
for (int j = 0; j < n; j++) {
|
||||
matingPool.add(population[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Making the next generation
|
||||
void reproduction() {
|
||||
// Refill the population with children from the mating pool
|
||||
for (int i = 0; i < population.length; i++) {
|
||||
// Sping the wheel of fortune to pick two parents
|
||||
int m = int(random(matingPool.size()));
|
||||
int d = int(random(matingPool.size()));
|
||||
// Pick two parents
|
||||
Organism mom = matingPool.get(m);
|
||||
Organism dad = matingPool.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
|
||||
population[i] = new Organism(child, population[i].x, population[i].y);
|
||||
}
|
||||
generations++;
|
||||
}
|
||||
|
||||
int getGenerations() {
|
||||
return generations;
|
||||
}
|
||||
|
||||
// Find highest fintess for the population
|
||||
float getMaxFitness() {
|
||||
float record = 0;
|
||||
for (int i = 0; i < population.length; i++) {
|
||||
if (population[i].getFitness() > record) {
|
||||
record = population[i].getFitness();
|
||||
}
|
||||
}
|
||||
return record;
|
||||
}
|
||||
}
|
Plik binarny nie jest wyświetlany.
Po Szerokość: | Wysokość: | Rozmiar: 91 KiB |
|
@ -0,0 +1,35 @@
|
|||
// Alexandre B A Villares - https://abav.lugaralgum.com/sketch-a-day
|
||||
// s182 20180629
|
||||
// Based on GA from The Nature of Code by Daniel Shiffman http://natureofcode.com
|
||||
|
||||
Population population;
|
||||
|
||||
void setup() {
|
||||
size(750, 750);
|
||||
colorMode(HSB, 1.0);
|
||||
int popmax = 25;
|
||||
float mutationRate = 0.03; // A pretty high mutation rate here, our population is rather small we need to enforce variety
|
||||
// Create a population with a target phrase, mutation rate, and population max
|
||||
population = new Population(mutationRate, popmax);
|
||||
}
|
||||
|
||||
void draw() {
|
||||
background(0);
|
||||
// Display the faces
|
||||
population.display();
|
||||
population.rollover(mouseX, mouseY);
|
||||
// Display some text
|
||||
textAlign(LEFT);
|
||||
fill(1);
|
||||
text("[pressione 'e' para a calcular a próxima geração] Geração #:" + population.getGenerations(), 25, 20);
|
||||
}
|
||||
|
||||
// If 'e' is presses, evolve next generation
|
||||
void keyPressed() {
|
||||
if (key == 'e') {
|
||||
randomSeed(frameCount);
|
||||
population.selection();
|
||||
population.reproduction();
|
||||
//saveFrame(population.getGenerations()+"GA.png");
|
||||
}
|
||||
}
|
Ładowanie…
Reference in New Issue