Created
May 6, 2018 02:15
-
-
Save thesephist/02457f4399ae5c9a2c0817ddf7c2d0f3 to your computer and use it in GitHub Desktop.
Mutation rate vs. Population Simulation
This file contains hidden or 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
// Constants | |
const M_RATES = [ | |
0, | |
0.001, | |
0.01, | |
0.1, | |
]; | |
const POP_SIZE = 100; | |
const GENERATIONS = 50; | |
const GENOME_LENGTH = 20; | |
const FITNESS_FACTOR = 0.8; // on a scale of 0 to 1 higher = more difficult | |
const LIFETIME = 4; // generations | |
const FERTILITY = .3; | |
class Individual { | |
constructor(m_rate, genome) { | |
this.m_rate = m_rate; | |
this.age = 0; | |
if (genome) { | |
this.genome = genome; | |
} else { | |
this.genome = []; | |
for (let i = 0; i < GENOME_LENGTH; i ++) { | |
this.genome.push(Math.random()); | |
} | |
} | |
} | |
is_fit() { | |
// To be "fit", 90% of genes have to have value > FITNESS_FACTOR | |
let fit_genes_count = 0; | |
for (const gene of this.genome) { | |
if (gene > FITNESS_FACTOR) fit_genes_count ++; | |
} | |
return fit_genes_count > (0.2 * this.genome.length); | |
} | |
do_age() { | |
this.age ++; | |
} | |
clone() { | |
const n_ind = new Individual(this.m_rate, this.genome.slice()); | |
for (let i = 0; i < GENOME_LENGTH; i ++) { | |
if (Math.random() < this.m_rate) { | |
n_ind.genome[i] = Math.random(); | |
} | |
} | |
return n_ind; | |
} | |
} | |
class Population { | |
constructor(size, m_rate) { | |
this.size = size; | |
this.m_rate = m_rate; | |
this.population = []; | |
this.generation = 0; | |
for (let i = 0; i < size; i ++) { | |
this.population.push(new Individual(m_rate)); | |
} | |
} | |
get_avg_fitness() { | |
let sum = 0; | |
for (const individual of this.population) { | |
if (individual.is_fit()) sum ++; | |
} | |
return sum / this.population.length; | |
} | |
/** | |
* Pass one generation, killing off unfit organisms | |
*/ | |
age_generation() { | |
for (const individual of this.population) { | |
individual.do_age(); | |
if (Math.random() < FERTILITY) { | |
this.population.push(individual.clone()); | |
} | |
if (individual.age >= LIFETIME) { | |
this._remove_individual(individual); | |
} | |
} | |
this.generation ++; | |
} | |
_remove_individual(individual) { | |
this.population.splice(this.population.indexOf(individual), 1); | |
} | |
} | |
function main() { | |
// create populations | |
const populations = []; | |
for (const rate of M_RATES) { | |
populations.push(new Population(POP_SIZE, rate)); | |
} | |
for (let i = 0; i < GENERATIONS; i ++) { | |
// loops | |
for (const pop of populations) { | |
pop.age_generation(); | |
} | |
console.log( | |
populations.map(p => p.population.length).join('\t') | |
+ '\t' | |
+ populations.map(p => p.get_avg_fitness()).join('\t') | |
); | |
} | |
} | |
main(); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment