-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
20 changed files
with
1,387 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
|
||
|
||
class Button { | ||
Rectangle r; // Button's rectangle | ||
String txt; // Button's text | ||
boolean clickedOn; // Did i click on it? | ||
boolean rolloverOn; // Did i rollover it? | ||
|
||
Button(int x, int y, int w, int h, String s) { | ||
r = new Rectangle(x,y,w,h); | ||
txt = s; | ||
} | ||
|
||
void display() { | ||
// Draw rectangle and text based on whether rollover or clicked | ||
rectMode(CORNER); | ||
stroke(0); noFill(); | ||
if (rolloverOn) fill(0.5); | ||
if (clickedOn) fill(0); | ||
rect(r.x,r.y,r.width,r.height); | ||
float b = 0.0; | ||
if (clickedOn) b = 1; | ||
else if (rolloverOn) b = 0.2; | ||
else b = 0; | ||
fill(b); | ||
textAlign(LEFT); | ||
text(txt,r.x+10,r.y+14); | ||
|
||
} | ||
|
||
|
||
// Methods to check rollover, clicked, or released (must be called from appropriate | ||
// Places in draw, mousePressed, mouseReleased | ||
boolean rollover(int mx, int my) { | ||
if (r.contains(mx,my)) rolloverOn = true; | ||
else rolloverOn = false; | ||
return rolloverOn; | ||
} | ||
|
||
boolean clicked(int mx, int my) { | ||
if (r.contains(mx,my)) clickedOn = true; | ||
return clickedOn; | ||
} | ||
|
||
void released() { | ||
clickedOn = false; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
|
||
class DNA { | ||
|
||
// The genetic sequence | ||
float[] genes; | ||
int len = 20; // 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); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
|
||
// The class for our "face", contains DNA sequence, fitness value, position on screen | ||
|
||
// Fitness Function f(t) = t (where t is "time" mouse rolls over face) | ||
|
||
class Face { | ||
|
||
DNA dna; // Face's DNA | ||
float fitness; // How good is this face? | ||
float x, y; // Position on screen | ||
int wh = 70; // Size of square enclosing face | ||
boolean rolloverOn; // Are we rolling over this face? | ||
|
||
Rectangle r; | ||
|
||
// Create a new face | ||
Face(DNA dna_, float x_, float y_) { | ||
dna = dna_; | ||
x = x_; | ||
y = y_; | ||
fitness = 1; | ||
// Using java.awt.Rectangle (see: http://java.sun.com/j2se/1.4.2/docs/api/java/awt/Rectangle.html) | ||
r = new Rectangle(int(x-wh/2), int(y-wh/2), int(wh), int(wh)); | ||
} | ||
|
||
// Display the face | ||
void display() { | ||
// We are using the face's DNA to pick properties for this face | ||
// such as: head size, color, eye position, etc. | ||
// Now, since every gene is a floating point between 0 and 1, we map the values | ||
float r = map(dna.genes[0],0,1,0,70); | ||
color c = color(dna.genes[1],dna.genes[2],dna.genes[3]); | ||
float eye_y = map(dna.genes[4],0,1,0,5); | ||
float eye_x = map(dna.genes[5],0,1,0,10); | ||
float eye_size = map(dna.genes[5],0,1,0,10); | ||
color eyecolor = color(dna.genes[4],dna.genes[5],dna.genes[6]); | ||
color mouthColor = color(dna.genes[7],dna.genes[8],dna.genes[9]); | ||
float mouth_y = map(dna.genes[5],0,1,0,25); | ||
float mouth_x = map(dna.genes[5],0,1,-25,25); | ||
float mouthw = map(dna.genes[5],0,1,0,50); | ||
float mouthh = map(dna.genes[5],0,1,0,10); | ||
|
||
// Once we calculate all the above properties, we use those variables to draw rects, ellipses, etc. | ||
pushMatrix(); | ||
translate(x, y); | ||
noStroke(); | ||
|
||
// Draw the head | ||
smooth(); | ||
fill(c); | ||
ellipseMode(CENTER); | ||
ellipse(0, 0, r, r); | ||
|
||
// Draw the eyes | ||
fill(eyecolor); | ||
rectMode(CENTER); | ||
rect(-eye_x, -eye_y, eye_size, eye_size); | ||
rect( eye_x, -eye_y, eye_size, eye_size); | ||
|
||
// Draw the mouth | ||
fill(mouthColor); | ||
rectMode(CENTER); | ||
rect(mouth_x, mouth_y, mouthw, mouthh); | ||
|
||
// Draw the bounding box | ||
stroke(0.25); | ||
if (rolloverOn) fill(0, 0.25); | ||
else noFill(); | ||
rectMode(CENTER); | ||
rect(0, 0, wh, wh); | ||
popMatrix(); | ||
|
||
// Display fitness value | ||
textAlign(CENTER); | ||
if (rolloverOn) fill(0); | ||
else fill(0.25); | ||
text(int(fitness), x, y+55); | ||
} | ||
|
||
float getFitness() { | ||
return fitness; | ||
} | ||
|
||
DNA getDNA() { | ||
return dna; | ||
} | ||
|
||
// Increment fitness if mouse is rolling over face | ||
void rollover(int mx, int my) { | ||
if (r.contains(mx, my)) { | ||
rolloverOn = true; | ||
fitness += 0.25; | ||
} else { | ||
rolloverOn = false; | ||
} | ||
} | ||
} |
44 changes: 44 additions & 0 deletions
44
Lectures/Lecture13/Faces_interactiveselection/Faces_interactiveselection.pde
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
|
||
|
||
Population population; | ||
Button button; | ||
|
||
void setup() { | ||
size(800,200); | ||
colorMode(RGB,1.0); | ||
smooth(); | ||
int popmax = 10; | ||
float mutationRate = 0.05; // 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); | ||
// A simple button class | ||
button = new Button(15,150,160,20, "evolve new generation"); | ||
} | ||
|
||
void draw() { | ||
background(1.0); | ||
// Display the faces | ||
population.display(); | ||
population.rollover(mouseX,mouseY); | ||
// Display some text | ||
textAlign(LEFT); | ||
fill(0); | ||
text("Generation #:" + population.getGenerations(),15,190); | ||
|
||
// Display the button | ||
button.display(); | ||
button.rollover(mouseX,mouseY); | ||
|
||
} | ||
|
||
// If the button is clicked, evolve next generation | ||
void mousePressed() { | ||
if (button.clicked(mouseX,mouseY)) { | ||
population.selection(); | ||
population.reproduction(); | ||
} | ||
} | ||
|
||
void mouseReleased() { | ||
button.released(); | ||
} |
95 changes: 95 additions & 0 deletions
95
Lectures/Lecture13/Faces_interactiveselection/Population.pde
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
|
||
// A class to describe a population of faces | ||
// this hasn't changed very much from example to example | ||
|
||
class Population { | ||
|
||
float mutationRate; // Mutation rate | ||
Face[] population; // array to hold the current population | ||
ArrayList<Face> 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 Face[num]; | ||
matingPool = new ArrayList<Face>(); | ||
generations = 0; | ||
for (int i = 0; i < population.length; i++) { | ||
population[i] = new Face(new DNA(), 50+i*75, 60); | ||
} | ||
} | ||
|
||
// 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].rollover(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 | ||
Face mom = matingPool.get(m); | ||
Face 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 Face(child, 50+i*75, 60); | ||
} | ||
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; | ||
} | ||
} |
21 changes: 21 additions & 0 deletions
21
Lectures/Lecture13/Faces_interactiveselection/Rectangle.pde
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
// Re-implementing java.awt.Rectangle | ||
// so JS mode works | ||
|
||
class Rectangle { | ||
int x; | ||
int y; | ||
int width; | ||
int height; | ||
|
||
Rectangle(int x_, int y_, int w, int h) { | ||
x = x_; | ||
y = y_; | ||
width = w; | ||
height = h; | ||
} | ||
|
||
boolean contains(int px, int py) { | ||
return (px > x && px < x + width && py > y && py < y + height); | ||
} | ||
|
||
} |
Oops, something went wrong.