Use Genetic.js, be happy.
Last active
January 3, 2017 16:24
-
-
Save Fil/40666f940e4a2f1e4e326e831d4b1290 to your computer and use it in GitHub Desktop.
Genetic.js Hello World
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
license: mit |
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
<!DOCTYPE html> | |
<head> | |
<meta charset="utf-8"> | |
<script src="https://d3js.org/d3.v4.min.js"></script> | |
<script src="https://unpkg.com/genetic-js"></script> | |
<style> | |
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; font-family: monospace; } | |
td { | |
border: solid 0.5px #eee; | |
} | |
</style> | |
</head> | |
<body> | |
<table><thead><th>Generation</th><th>Fitness</th><th>Best Individual</th></thead><tbody> | |
</tbody></table> | |
<script> | |
// Feel free to change or delete any of the code you see in this editor! | |
var genetic = Genetic.create(); | |
genetic.optimize = Genetic.Optimize.Maximize; | |
genetic.select1 = Genetic.Select1.Tournament2; | |
genetic.select2 = Genetic.Select2.Tournament2; | |
genetic.seed = function() { | |
function randomString(len) { | |
var text = ""; | |
var charset = "abcdefghijklmnopqrstuvwxyz0123456789"; | |
for(var i=0;i<len;i++) | |
text += charset.charAt(Math.floor(Math.random() * charset.length)); | |
return text; | |
} | |
// create random strings that are equal in length to solution | |
return randomString(this.userData["solution"].length); | |
}; | |
genetic.mutate = function(entity) { | |
function replaceAt(str, index, character) { | |
return str.substr(0, index) + character + str.substr(index+character.length); | |
} | |
// chromosomal drift | |
var i = Math.floor(Math.random()*entity.length) | |
return replaceAt(entity, i, String.fromCharCode(entity.charCodeAt(i) + (Math.floor(Math.random()*2) ? 1 : -1))); | |
}; | |
genetic.crossover = function(mother, father) { | |
// two-point crossover | |
var len = mother.length; | |
var ca = Math.floor(Math.random()*len); | |
var cb = Math.floor(Math.random()*len); | |
if (ca > cb) { | |
var tmp = cb; | |
cb = ca; | |
ca = tmp; | |
} | |
var son = father.substr(0,ca) + mother.substr(ca, cb-ca) + father.substr(cb); | |
var daughter = mother.substr(0,ca) + father.substr(ca, cb-ca) + mother.substr(cb); | |
return [son, daughter]; | |
}; | |
genetic.fitness = function(entity) { | |
var fitness = 0; | |
var i; | |
for (i=0;i<entity.length;++i) { | |
// increase fitness for each character that matches | |
if (entity[i] == this.userData["solution"][i]) | |
fitness += 1; | |
// award fractions of a point as we get warmer | |
fitness += (127-Math.abs(entity.charCodeAt(i) - this.userData["solution"].charCodeAt(i)))/50; | |
} | |
return fitness; | |
}; | |
genetic.generation = function(pop, generation, stats) { | |
// stop running once we've reached the solution | |
return pop[0].entity != this.userData["solution"]; | |
}; | |
genetic.notification = function(pop, generation, stats, isFinished) { | |
console.log(stats); | |
function lerp(a, b, p) { | |
return a + (b-a)*p; | |
} | |
var value = pop[0].entity; | |
this.last = this.last||value; | |
if (pop != 0 && value == this.last) | |
return; | |
var solution = []; | |
var i; | |
for (i=0;i<value.length;++i) { | |
var diff = value.charCodeAt(i) - this.last.charCodeAt(i); | |
var style = "background: transparent;"; | |
if (diff > 0) { | |
style = "background: rgb(0,200,50); color: #fff;"; | |
} else if (diff < 0) { | |
style = "background: rgb(0,100,50); color: #fff;"; | |
} | |
solution.push("<span style=\"" + style + "\">" + value[i] + "</span>"); | |
} | |
var buf = ""; | |
buf += "<td>" + generation + "</td>"; | |
buf += "<td>" + pop[0].fitness.toPrecision(5) + "</td>"; | |
buf += "<td>" + solution.join("") + "</td>"; | |
d3.select("tbody").insert("tr", "*").html(buf); | |
this.last = value; | |
}; | |
var config = { | |
"iterations": 4000 | |
, "size": 250 | |
, "crossover": 0.3 | |
, "mutation": 0.3 | |
, "skip": 50 | |
, "webWorkers" : true | |
}; | |
genetic.evolve(config, { solution: 'Mimeme comes from a suitable Greek root, but I want a monosyllable that sounds a bit like gene' }); | |
</script> | |
</body> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment