xxxxxxxxxx
141
const goal = "hello"
const popSize = 20;
let population = [];
const fitnesses = [];
let maxScore = 0;
let fittest = "";
function setup() {
createCanvas(400, 400);
// frameRate(1);
// noLoop();
for(let i = 0; i < popSize; i ++) {
population.push(new DNA(goal.length, 0.3, 0.2));
fitnesses.push(0);
}
print(fitness(goal, null))
}
function draw() {
background(220);
text(goal, width/4, height/4);
text(fittest, width/4, height/3);
text(maxScore, width/4, height/2);
for(let i = 0; i < popSize; i ++) {
text(pheno(population[i]), width/2, (height/popSize) * (i + 0.5));
}
nextGen();
}
function nextGen() {
let total = 0;
for(let i = 0; i < popSize; i ++) {
const f = fitness(goal, population[i]);
fitnesses[i] = f;
total += f;
if(f > maxScore) {
maxScore = f;
fittest = pheno(population[i]);
}
}
let nextGen = [];
for(let i = 0; i < popSize; i ++) {
let a = randomPop(population, fitnesses, total);
let b = randomPop(population, fitnesses, total);
nextGen.push(a.breed(b));
}
population = nextGen;
}
function randomPop(p, f, totalFitness) {
let s = random(totalFitness);
let t = 0;
for(let i = 0; i < f.length; i ++) {
t += f[i];
if(t > s) {
return p[i];
}
}
}
function pheno(dna) {
let s = "";
if(!dna) {
return "";
}
for(let i = 0; i < dna.length; i ++) {
const n = (dna.dna[i] * 26) | 0;
s += char(97 + n)
}
return s;
}
function fitness(goal, dna) {
let p = pheno(dna);
let score = 0;
for(let i = 0; i < p.length; i ++) {
let n1 = unchar(p[i]);
let n2 = unchar(goal[i]);
let s = abs(n1 - n2);
if(s === 0) {
score -= 10;
} else {
score += s;
}
}
return (goal.length * 26) - score;
}
class DNA {
constructor(length, mutationRate, mutationAmt) {
this.length = length;
this.mutationRate = mutationRate;
this.mutationAmt = mutationAmt;
this.dna = new Array(length);
this.randomise();
}
randomise() {
for(let i = 0; i < this.length; i ++) {
this.dna[i] = random();
}
}
setDNA(dna) {
for(let i = 0; i < this.length; i ++) {
const n = i >= dna.length ? 0 : dna[i];
this.dna[i] = n;
}
}
duplicate() {
const newDNA = new DNA(this.length, this.mutationRate, this.mutationAmt);
newDNA.setDNA(this.dna);
return newDNA
}
mutate() {
for(let i = 0; i < this.length; i ++) {
if(random() < this.mutationRate) {
const amt = random(-this.mutationAmt, this.mutationAmt);
const n = this.dna[i] + amt;
this.dna[i] = constrain(n, 0, 1);
}
}
}
breed(other) {
const offspring = this.duplicate();
for(let i = 0; i < this.length; i ++) {
const n1 = i >= other.dna.length ? 0 : other.dna[i];
const n2 = this.dna[i];
offspring.dna[i] = random() < 0.5 ? n1 : n2;
}
offspring.mutate();
return offspring;
}
}