Last active
January 22, 2020 11:06
-
-
Save borgeslt/7350901f9139f83c44a709918e923084 to your computer and use it in GitHub Desktop.
A Simple Genetic Algorithms in Javascript
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
/* | |
Based on the Vijini Mallawaarachchi's article in Towards Data Science | |
https://towardsdatascience.com/introduction-to-genetic-algorithms-including-example-code-e396e98d8bf3 | |
*/ | |
"strict mode" | |
function Individual(numOfGenes) { | |
const _genes = Array(numOfGenes).fill(0).map(i => Math.floor(Math.random() * 1000 % 2)); | |
let _fitness = 0; | |
return { | |
fitness: () => _fitness, | |
genes: (index, value) => { | |
if(!index) { | |
return _genes; | |
} | |
if (!value) { | |
return _genes[index]; | |
} | |
return (_genes[index] = value); | |
}, | |
computeFitness: () => { | |
_fitness = _genes.reduce((a, c) => a += c); | |
}, | |
mutate: () => { | |
let mutationPoint = Math.floor(Math.random() * 1000 % numOfGenes); | |
_genes[mutationPoint] = _genes[mutationPoint] ^ 1; | |
} | |
} | |
} | |
function Population(numOfIndividuals, numOfGenes) { | |
const _individuals = Array(numOfIndividuals).fill(0).map(() => new Individual(numOfGenes)); | |
let _fittest; | |
let _secondFittest; | |
return { | |
bestFitness: () => _fittest.fitness(), | |
bestGenes: () => _fittest.genes().join(""), | |
evaluate: () => { | |
_individuals.forEach(i => i.computeFitness()); | |
_individuals.sort((i1, i2) => i2.fitness() - i1.fitness()); | |
}, | |
selection: () => { | |
_fittest = _individuals[0]; | |
_secondFittest = _individuals[1]; | |
}, | |
crossover: () => { | |
let crossOverPoint = Math.floor(Math.random() * 1000 % numOfGenes); | |
for (let i = 0; i < crossOverPoint; i++) { | |
let g1 = _fittest.genes(i); | |
let g2 = _secondFittest.genes(i); | |
_fittest.genes(i, g2); | |
_secondFittest.genes(i, g1); | |
} | |
}, | |
mutation: () => { | |
if (Math.floor(Math.random() * 1000 % 7) >= 5) { | |
return; | |
} | |
_fittest.mutate(); | |
_secondFittest.mutate(); | |
}, | |
addFittestOffspring: () => { | |
_fittest.computeFitness(); | |
_secondFittest.computeFitness(); | |
let fittestOffspring = (_fittest.fitness > _secondFittest.fitness) ? _fittest : _secondFittest; | |
_individuals[numOfIndividuals - 1] = {...fittestOffspring}; | |
} | |
} | |
} | |
function SimpleDemoGA() { | |
return { | |
execute: (numOfIndividuals = 10, numOfGenes = 5, maxGenerations = 100) => { | |
const population = new Population(numOfIndividuals, numOfGenes); | |
let generationCount = 0; | |
do { | |
population.evaluate(); | |
population.selection(); | |
population.crossover(); | |
population.mutation(); | |
population.addFittestOffspring(); | |
generationCount++; | |
console.log(`Generation ${generationCount} Fittest: ${population.bestFitness()}`); | |
} while (population.bestFitness() < numOfGenes && generationCount < maxGenerations); | |
console.log(""); | |
console.log(`Solution found in generation ${generationCount}`); | |
console.log(`Fitness: ${population.bestFitness()}`); | |
console.log(`Genes: ${population.bestGenes()}`); | |
} | |
} | |
} | |
new SimpleDemoGA().execute(numOfIndividuals=10, numOfGenes=5, maxGenerations=100); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment