genetic-js-no-ww
Version:
Advanced genetic and evolutionary algorithm library (no web workers fork)
109 lines (86 loc) • 2.69 kB
JavaScript
var Genetic = require("../lib/genetic");
var assert = require("assert");
var genetic;
beforeEach(function () {
genetic = Genetic.create();
genetic.optimize = Genetic.Optimize.Maximize;
genetic.seed = function() {
function randomString(len) {
var text = "";
var charset = "abcdefghijklmnopqrstuvwxyz";
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"];
};
});
function solveTest(sel1, sel2, config) {
it(sel1 + ", " + sel2, function (done) {
genetic.select1 = eval(sel1);
genetic.select2 = eval(sel2);
genetic.notification = function(pop, generation, stats, isFinished) {
if (isFinished) {
assert.equal(pop[0].entity, this.userData["solution"]);
done();
}
};
var userData = {
"solution": "thisisthesolution"
};
genetic.evolve(config, userData);
});
}
describe("Genetic String Solver", function() {
var config = {
"iterations": 2000
, "size": 20
, "crossover": 0.4
, "mutation": 0.3
};
var k;
for (k in Genetic.Select1) {
for (j in Genetic.Select2) {
solveTest("Genetic.Select1."+k, "Genetic.Select2."+j, config);
}
};
});