Skip to content

Instantly share code, notes, and snippets.

@borgeslt
Last active January 22, 2020 11:06
Show Gist options
  • Save borgeslt/7350901f9139f83c44a709918e923084 to your computer and use it in GitHub Desktop.
Save borgeslt/7350901f9139f83c44a709918e923084 to your computer and use it in GitHub Desktop.
A Simple Genetic Algorithms in Javascript
/*
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