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
class Car { | |
constructor(outerDi, innerDi, screenHt, screenWd, carDi, obsts) { | |
this.x = | |
0.5 * (screenWd - (innerDi + outerDi) / 2) + round(random() * 80) - 40; // Slight variation in starting x | |
this.y = screenHt / 2 - 5; // Right above the starting line | |
this.angle = -PI / 2; // Facing upward | |
//Dimensions for later usage | |
this.carDi = carDi; |
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
<head> | |
<!-- Load in Tensorflow, P5, and our Car Class--> | |
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@2.0.0/dist/tf.min.js"></script> | |
<script | |
src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.1.9/p5.min.js" | |
integrity="sha512-WIklPM6qPCIp6d3fSSr90j+1unQHUOoWDS4sdTiR8gxUTnyZ8S2Mr8e10sKKJ/bhJgpAa/qG068RDkg6fIlNFA==" | |
crossorigin="anonymous" | |
></script> | |
<script src="car.js"></script> |
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
function startNewGen() { | |
totalFitness = endGen(); | |
let newCarArr = []; // The next generation | |
mutationRate = mrateInput.value() // Pull mutation rate | |
//Get parent weights | |
let parentWeights = []; | |
cars.forEach((c) => { | |
parentWeights.push(c.copyWeights()); |
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
frameCount += 1; | |
// If 200 frames has passed plus a scaled of the highestScore, then start next generation | |
if (frameCount > 200 + topFitnessScore * 3) { | |
startNewGen(); | |
frameCount = 0; | |
} else if (frameCount > 80) { // Check for inactivity after 80 frames | |
let stillActive = false; | |
// Make sure atleast one car has made progress without dying | |
cars.forEach((car) => { | |
if (car.fitness > 3 && car.dead == false) { |
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
function startNewGen() { | |
totalFitness = endGen(); | |
let newCarArr = []; // The next generation | |
//Get parent weights | |
let parentWeights = []; | |
cars.forEach((c) => { | |
parentWeights.push(c.copyWeights()); | |
}); |
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
copyWeights() { | |
// Turn weights from Tensorformat to array format | |
const weights = this.model.getWeights(); // Pull weights | |
const weightCopies = []; | |
weights.forEach((wLayer) => { | |
let values = wLayer.dataSync(); // turn that layer from Tensor into array | |
weightCopies.push(values); | |
}); |
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
function endGen() { | |
let totalFitness = 0 | |
bestOfGen = 0 | |
// Calculate total fitness and find highest performing car | |
cars.forEach((car, ind) => { | |
car.dead = true | |
totalFitness += car.fitness | |
if(car.fitness > bestOfGen) {bestOfGen = car.fitness} | |
}) |
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
function selectRandParent(tFit) { | |
let randVal = tFit * random() // Random value between (0, tFit) | |
let count = 0 // Cumulitive Fitness | |
for(let i = 0; i < cars.length; i++) { | |
count += cars[i].fitness | |
if(randVal <= count) { | |
return i | |
} | |
} |
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
cars.forEach((car) => { | |
//Draw car | |
//Draw Wheels | |
fill("black"); | |
strokeWeight(0); | |
ellipse( | |
car.x + (carDi / 2) * cos(car.angle + PI / 4), | |
car.y + (carDi / 2) * sin(car.angle + PI / 4), | |
carDi / 2.5 |
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
setupModel() { | |
// Create a sequential neural network | |
this.model = tf.sequential(); | |
let hidden1 = tf.layers.dense({ | |
units: 8, | |
activation: "relu", | |
inputDim: 5, | |
}); | |
let outputLayer = tf.layers.dense({ | |
units: 4, |
NewerOlder