LoginSignup
0
0

More than 5 years have passed since last update.

jsdoで遺伝的アルゴリズム その2

Last updated at Posted at 2018-03-20

概要

遺伝的アルゴリズムを理解したかった。
jsdoで、やってみた。
genetic.jsを見つけた。

写真

image.png

one max

var genetic;
genetic = Genetic.create();
genetic.optimize = Genetic.Optimize.Minimize;
genetic.select1 = Genetic.Select1.Tournament2;
genetic.select2 = Genetic.Select2.Tournament2;
genetic.seed = function() {
    var a = [];
    for (var i = 0; i < this.userData["term"]; i++)
    {
        a.push(Math.random() - 0.01);
    }
    return a;
};
genetic.mutate = function(entity) {
    var drift = ((Math.random() - 0.5) * 2) * 0.05;
    var i = Math.floor(Math.random() * entity.length);
    entity[i] += drift;
    return entity;
};
genetic.crossover = function(mother, father) {
    function lerp(a, b, p) {
        return a + (b - a) * p;
    }
    var len = mother.length;
    var i = Math.floor(Math.random() * len);
    var r = Math.random();
    var son = [].concat(father);
    var daughter = [].concat(mother);
    son[i] = lerp(father[i], mother[i], r);
    daughter[i] = lerp(mother[i], father[i], r);
    return [son, daughter];
};
genetic.fitness = function(entity) {
    var sumSqErr = 0;
    var solutions = this.userData["solution"];
    for (var i = 0; i < entity.length; i++) 
    {
        var err = entity[i] - solutions[i];
        sumSqErr += err * err;
    }
    return Math.sqrt(sumSqErr);
};
genetic.generation = function(pop, generation, stats) {
};
genetic.notification = function(pop, generation, stats, isFinished) {
    if (isFinished) 
    {
        document.getElementById('helloWorld').innerHTML += pop[0].entity + "<br>";
        done();
    }
};
var config = {
    "iterations": 1000,
    "size": 40,
    "crossover": 0.3,
    "mutation": 0.3
};
var userData = {
    "term": 10,
    "solution": [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
};
genetic.evolve(config, userData);



sin fit

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
function draw(data, n) {
    var hcenter = 100;
    ctx.strokeStyle = "#f00";
    ctx.lineWidth = n;
    for (var i = 1; i < 20; i++) 
    {
        var x = data[i][0] * 20;
        var y = data[i][1] * 20 + hcenter;
        ctx.moveTo(x, y);
        ctx.lineTo(x + 1, y + 1);
    }
    ctx.stroke();
}
function drawf(data) {
    ctx.strokeStyle = "#00f";
    ctx.lineWidth = 2;
    for (var i = 0; i < 20; i++) 
    {
        var x = i * 20;
        var y = genetic.evaluatePoly(data, i) * 20 + 100;
        if (i == 0) 
        {
            ctx.moveTo(x, y);
        }
        else
        {
            ctx.lineTo(x, y);
        }
    }
    ctx.stroke();
}
var genetic = Genetic.create();
genetic.optimize = Genetic.Optimize.Minimize;
genetic.select1 = Genetic.Select1.Tournament2;
genetic.select2 = Genetic.Select2.FittestRandom;
var solutions = [];
genetic.seed = function() {
    var a = [];
    var i;
    for (i = 0; i < this.userData["terms"]; ++i)
    {
        a.push(Math.random() - 0.01);
    }
    return a;
};
genetic.mutate = function(entity) {
    var drift = ((Math.random() - 0.5) * 2) * 0.05;
    var i = Math.floor(Math.random() * entity.length);
    entity[i] += drift;
    return entity;
};
genetic.crossover = function(mother, father) {
    function lerp(a, b, p) {
        return a + (b - a) * p;
    }
    var len = mother.length;
    var i = Math.floor(Math.random() * len);
    var r = Math.random();
    var son = [].concat(father);
    var daughter = [].concat(mother);
    son[i] = lerp(father[i], mother[i], r);
    daughter[i] = lerp(mother[i], father[i], r);
    return [son, daughter];
};
genetic.evaluatePoly = function(coefficients, x) {
    var s = 0;
    var p = 1;
    var i;
    for (i = 0; i < coefficients.length; ++i)
    {
        s += p * coefficients[i];
        p *= x;
    }
    return s;
}
genetic.fitness = function(entity) {
    var sumSqErr = 0;
    var vertices = this.userData["vertices"];
    var i;
    for (i = 0; i < vertices.length; ++i) 
    {
        var err = this.evaluatePoly(entity, vertices[i][0]) - vertices[i][1];
        sumSqErr += err * err;
    }
    return Math.sqrt(sumSqErr);
};
genetic.generation = function(pop, generation, stats) {
};
genetic.notification = function(pop, generation, stats, isFinished) {
     function poly(entity) {
        var a = [];
        var i;
        for (i = entity.length - 1; i >= 0; --i)
        {
            var buf = entity[i].toPrecision(2);
            if (i > 1) buf += "<em><b>x<sup>" + i + "<sup></b></em>";
            else if (i == 1) buf += "<em><b>x</b></em>";
            a.push(buf);
        }
        return a.join(" + ");
    }
    var last = last || "";
    var str = pop[0].entity.join(",");
    if (last != str || isFinished) 
    {
        if (last != str)
        {
            last = str;
        }
        if (isFinished)
        {
            drawf(pop[0].entity);
            document.getElementById('helloWorld').innerHTML = poly(pop[0].entity);
        }
    }
};
var config = {
    "iterations": 1000,
    "size": 250,
    "crossover": 0.3,
    "mutation": 0.3,
    "skip": 10
};
var vertices = [];
var n = 20;
var off = Math.random() * 2 * 3.1415927;
var stride = 10 / n;
var i;
for (i = 0; i < n; ++i)
{
    vertices.push([i * stride, Math.sin((off + i / n) * 2 * 3.1415627) * 3 + 5]);
}
draw(vertices, 3);
var userData = {
    "terms": 4,
    "vertices": vertices
};
genetic.evolve(config, userData);



以上。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0