xxxxxxxxxx
181
// Define global variables
let populationSize = 100;
let agents = [];
let maxGenerations = 100;
let currentGeneration = 1;
let groundY;
let maxSteps = 1000;
// Define agent class
class Agent {
constructor() {
this.x = 50;
this.y = 0;
this.velY = 0;
this.gravity = 0.2;
this.walkForce = 1;
this.genome = []; // Genome representing walking behavior
this.fitness = 0; // Fitness score based on walking performance
this.stepIndex = 0; // Current index in the genome
}
update() {
this.applyWalkForce();
this.applyGravity();
this.updatePosition();
}
applyWalkForce() {
let force = this.genome[this.stepIndex];
this.velY += force * this.walkForce;
this.stepIndex++;
if (this.stepIndex >= this.genome.length) {
this.stepIndex = 0;
}
}
applyGravity() {
this.velY += this.gravity;
}
updatePosition() {
this.y += this.velY;
if (this.y > groundY) {
this.y = groundY;
this.velY = 0;
}
}
show() {
fill(255);
rect(this.x, this.y, 20, 40);
}
}
// Initialize the population
function initializePopulation() {
groundY = height - 50;
for (let i = 0; i < populationSize; i++) {
agents[i] = new Agent();
// Initialize the genome with random walking behavior
for (let j = 0; j < maxSteps; j++) {
agents[i].genome[j] = random(-1, 1);
}
}
}
// Evaluate the fitness of each agent in the population
function evaluateFitness() {
for (let i = 0; i < populationSize; i++) {
let agent = agents[i];
// Calculate the fitness based on the agent's walking performance
agent.fitness = agent.x; // Example fitness calculation (distance traveled)
}
}
// Perform selection, crossover, and mutation to create the next generation
function evolvePopulation() {
let newAgents = [];
// Selection
for (let i = 0; i < populationSize; i++) {
let parentA = selectParent();
let parentB = selectParent();
let child = crossover(parentA, parentB);
mutate(child);
newAgents[i] = child;
}
// Replace the existing population with the new offspring
agents = newAgents;
}
// Select a parent based on fitness (roulette wheel selection)
function selectParent() {
let totalFitness = agents.reduce((sum, agent) => sum + agent.fitness, 0);
let rand = random(totalFitness);
let partialSum = 0;
for (let i = 0; i < populationSize; i++) {
let agent = agents[i];
partialSum += agent.fitness;
if (partialSum >= rand) {
return agent;
}
}
return agents[populationSize - 1]; // Fallback option
}
// Perform crossover between two parents to create a child
function crossover(parentA, parentB) {
let child = new Agent();
let crossoverPoint = floor(random(parentA.genome.length));
for (let i = 0; i < parentA.genome.length; i++) {
if (i < crossoverPoint) {
child.genome[i] = parentA.genome[i];
} else {
child.genome[i] = parentB.genome[i];
}
}
return child;
}
// Introduce random mutations in the agent's genome
function mutate(agent) {
for (let i = 0; i < agent.genome.length; i++) {
if (random() < mutationRate) {
agent.genome[i] += random(-mutationMagnitude, mutationMagnitude);
}
}
}
// Run the simulation
function draw() {
background(0);
// Update and render each agent in the population
for (let i = 0; i < populationSize; i++) {
agents[i].update();
agents[i].show();
}
// Check if all agents have finished walking
let allFinished = agents.every(agent => agent.x >= width - 20);
if (allFinished) {
// Evaluate the fitness of the population
evaluateFitness();
// Evolve the population
evolvePopulation();
// Increment the generation count
currentGeneration++;
}
if (currentGeneration > maxGenerations) {
noLoop();
console.log("Training finished.");
}
}
// Setup p5.js
function setup() {
createCanvas(600, 400);
initializePopulation();
frameRate(30); // Adjust the frame rate as needed
}
// Start the simulation
function startSimulation() {
loop();
}
// Stop the simulation
function stopSimulation() {
noLoop();
}