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
|
// 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
|
// Based on GA from The Nature of Code by Daniel Shiffman http://natureofcode.com
|
||||||
|
|
||||||
Population population;
|
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