From c973c6f2bf973d9da8dd11cc4b39d5c5a17e2ef7 Mon Sep 17 00:00:00 2001 From: Marco de Zeeuw Date: Thu, 19 Apr 2018 22:41:14 +0200 Subject: [PATCH] Changed mutate to also check if it should mutate at all based on the rate. Doubled vehicle.maxforce so it has more control over itself. Changed the mutation rate because of the mentioned mutation-changes. Changed the border-inputs according to the entire canvas instead of the 50px wide stroke. Lastly I've added a fallback for when almost all vehicles die, which would probably never happen in the current reproduction-rate. --- week10/neuroevolution-steering/nn/nn.js | 32 ++++++++++++----------- week10/neuroevolution-steering/sketch.js | 11 +++++--- week10/neuroevolution-steering/vehicle.js | 18 +++++++------ 3 files changed, 35 insertions(+), 26 deletions(-) diff --git a/week10/neuroevolution-steering/nn/nn.js b/week10/neuroevolution-steering/nn/nn.js index db53b8c..3963962 100644 --- a/week10/neuroevolution-steering/nn/nn.js +++ b/week10/neuroevolution-steering/nn/nn.js @@ -162,23 +162,25 @@ class NeuralNetwork { } mutate(rate) { - // This is how we adjust weights ever so slightly - function mutate(x) { - if (Math.random() < rate) { - var offset = randomGaussian() * 0.5; - // var offset = random(-0.1, 0.1); - var newx = x + offset; - return newx; - } else { - return x; + // Check if this should be mutated at all + if (Math.random() < rate) { + // This is how we adjust weights ever so slightly + function mutate(x) { + // Mutate only so much of the values + if (Math.random() < rate) { + var offset = randomGaussian() * 0.5; + // var offset = random(-0.1, 0.1); + var newx = x + offset; + return newx; + } else { + return x; + } } + this.weights_ih.map(mutate); + this.weights_ho.map(mutate); + this.bias_h.map(mutate); + this.bias_o.map(mutate); } - this.weights_ih.map(mutate); - this.weights_ho.map(mutate); - this.bias_h.map(mutate); - this.bias_o.map(mutate); } - - } \ No newline at end of file diff --git a/week10/neuroevolution-steering/sketch.js b/week10/neuroevolution-steering/sketch.js index cb303dc..2ab06a3 100644 --- a/week10/neuroevolution-steering/sketch.js +++ b/week10/neuroevolution-steering/sketch.js @@ -28,7 +28,7 @@ let foodBuffer = 50; // How many sensors does each vehicle have? let totalSensors = 8; // How far can each vehicle see? -let sensorLength = 150; +let sensorLength = 50; // What's the angle in between sensors let sensorAngle = (Math.PI * 2) / totalSensors; @@ -94,14 +94,19 @@ function draw() { if (population.length < 20) { for (let v of population) { // Every vehicle has a chance of cloning itself according to score - // Argument to "clone" is probability - let newVehicle = v.clone(0.1 * v.score / record); + let probability = 0.1 * v.score / record; + let newVehicle = v.clone(probability); // If there is a child if (newVehicle != null) { population.push(newVehicle); } } } + // Make sure we never run out of vehicles, but favor reproduction + if (population.length <= 2) { + let vehicle = new Vehicle(); + population.push(vehicle); + } } // Draw all the food diff --git a/week10/neuroevolution-steering/vehicle.js b/week10/neuroevolution-steering/vehicle.js index 145a3a5..5e35e82 100644 --- a/week10/neuroevolution-steering/vehicle.js +++ b/week10/neuroevolution-steering/vehicle.js @@ -25,7 +25,7 @@ class Vehicle { this.velocity = createVector(); this.position = createVector(random(width), random(height)); this.r = 4; - this.maxforce = 0.1; + this.maxforce = 0.2; this.maxspeed = 4; this.minspeed = 0.25; this.maxhealth = 3; @@ -42,7 +42,8 @@ class Vehicle { // If a brain is passed via constructor copy it if (brain) { this.brain = brain.copy(); - this.brain.mutate(0.1); + // Mutation rate is set quite high because there is no crossover + this.brain.mutate(0.25); // Otherwise make a new brain } else { // inputs are all the sensors plus position and velocity info @@ -52,7 +53,7 @@ class Vehicle { this.brain = new NeuralNetwork(inputs, 32, 2); } - // Health keeps vehicl alive + // Health keeps vehicle alive this.health = 1; } @@ -135,11 +136,12 @@ class Vehicle { // Create inputs let inputs = []; - // This is goofy but these 4 inputs are mapped to distance from edges - inputs[0] = constrain(map(this.position.x, foodBuffer, 0, 0, 1), 0, 1); - inputs[1] = constrain(map(this.position.y, foodBuffer, 0, 0, 1), 0, 1); - inputs[2] = constrain(map(this.position.x, width - foodBuffer, width, 0, 1), 0, 1); - inputs[3] = constrain(map(this.position.y, height - foodBuffer, height, 0, 1), 0, 1); + // These inputs are the location of the vehicle + inputs[0] = this.position.x / width; + inputs[1] = this.position.y / height; + // These inputs are the distance of the vehicle to east- and west borders + inputs[2] = 1 - inputs[0]; + inputs[3] = 1 - inputs[1]; // These inputs are the current velocity vector inputs[4] = this.velocity.x / this.maxspeed; inputs[5] = this.velocity.y / this.maxspeed;