Genetic_Algorithm / index.html
traromal's picture
Update index.html
fe29288 verified
raw
history blame
6.74 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive Genetic Algorithm</title>
<style>
body {
font-family: 'Helvetica Neue', Arial, sans-serif;
text-align: center;
margin: 0;
padding: 0;
background: linear-gradient(135deg, #ffefba, #ffffff);
color: #333;
}
h1 {
color: #4a4e69;
}
p {
color: #9a8c98;
}
canvas {
border: 2px solid #c9ada7;
background: #f2e9e4;
margin: 20px auto;
display: block;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
}
.controls {
margin: 20px auto;
display: flex;
justify-content: center;
align-items: center;
gap: 20px;
flex-wrap: wrap;
}
.controls label {
display: flex;
align-items: center;
gap: 10px;
color: #6c5b7b;
}
.controls input, .controls button {
padding: 10px 20px;
font-size: 16px;
border: none;
border-radius: 5px;
cursor: pointer;
transition: background 0.3s, transform 0.3s;
}
.controls input {
width: 100px;
background: #f2e9e4;
border: 1px solid #c9ada7;
color: #6c5b7b;
}
.controls button {
background: #a29bfe;
color: white;
}
.controls button:hover {
background: #6c5b7b;
transform: scale(1.05);
}
.controls button:disabled {
background: #c9ada7;
cursor: not-allowed;
}
</style>
</head>
<body>
<h1> Genetic Algorithm</h1>
<p>Click on the canvas to set a target position. Adjust settings and evolve the population!</p>
<div class="controls">
<label>Population Size: <input id="populationSize" type="number" value="50" min="10" max="200"></label>
<label>Mutation Rate: <input id="mutationRate" type="number" value="1" min="0" max="100">%</label>
<button id="startButton">Start Evolution</button>
<button id="stepButton">Step</button>
<button id="resetButton">Reset</button>
</div>
<canvas id="gaCanvas" width="800" height="600"></canvas>
<script>
const canvas = document.getElementById('gaCanvas');
const ctx = canvas.getContext('2d');
const populationSizeInput = document.getElementById('populationSize');
const mutationRateInput = document.getElementById('mutationRate');
const startButton = document.getElementById('startButton');
const stepButton = document.getElementById('stepButton');
const resetButton = document.getElementById('resetButton');
let running = false;
let targetX = 400;
let targetY = 300;
let population = [];
let generation = 0;
class Creature {
constructor(x, y) {
this.x = x || Math.random() * canvas.width;
this.y = y || Math.random() * canvas.height;
}
getFitness() {
const dx = this.x - targetX;
const dy = this.y - targetY;
return 1 / (1 + Math.sqrt(dx * dx + dy * dy));
}
mutate(mutationRate) {
if (Math.random() < mutationRate) {
this.x += (Math.random() - 0.5) * 50;
this.y += (Math.random() - 0.5) * 50;
}
}
draw() {
ctx.fillStyle = `rgba(94, 135, 243, ${this.getFitness()})`;
ctx.beginPath();
ctx.arc(this.x, this.y, 8, 0, Math.PI * 2);
ctx.fill();
ctx.strokeStyle = 'rgba(0, 0, 0, 0.2)';
ctx.stroke();
}
}
function generatePopulation(size) {
const population = [];
for (let i = 0; i < size; i++) {
population.push(new Creature());
}
return population;
}
function selectParents(population) {
const sorted = population.sort((a, b) => b.getFitness() - a.getFitness());
return sorted.slice(0, Math.floor(population.length / 2));
}
function crossover(parent1, parent2) {
const childX = (parent1.x + parent2.x) / 2;
const childY = (parent1.y + parent2.y) / 2;
return new Creature(childX, childY);
}
function evolvePopulation(population, mutationRate) {
const parents = selectParents(population);
const newPopulation = [];
newPopulation.push(parents[0]);
while (newPopulation.length < population.length) {
const parent1 = parents[Math.floor(Math.random() * parents.length)];
const parent2 = parents[Math.floor(Math.random() * parents.length)];
const child = crossover(parent1, parent2);
child.mutate(mutationRate);
newPopulation.push(child);
}
return newPopulation;
}
function visualizePopulation(population, generation) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = 'red';
ctx.beginPath();
ctx.arc(targetX, targetY, 10, 0, Math.PI * 2);
ctx.fill();
population.forEach(creature => creature.draw());
ctx.fillStyle = 'black';
ctx.font = '16px Arial';
ctx.fillText(`Generation: ${generation}`, 10, 20);
}
canvas.addEventListener('click', (event) => {
const rect = canvas.getBoundingClientRect();
targetX = event.clientX - rect.left;
targetY = event.clientY - rect.top;
});
startButton.addEventListener('click', () => {
running = true;
startButton.disabled = true;
stepButton.disabled = true;
resetButton.disabled = true;
const evolutionInterval = setInterval(() => {
if (!running) {
clearInterval(evolutionInterval);
startButton.disabled = false;
stepButton.disabled = false;
resetButton.disabled = false;
return;
}
const populationSize = parseInt(populationSizeInput.value);
const mutationRate = parseInt(mutationRateInput.value) / 100;
if (population.length === 0) {
population = generatePopulation(populationSize);
}
visualizePopulation(population, generation);
population = evolvePopulation(population, mutationRate);
generation++;
}, 200);
});
stepButton.addEventListener('click', () => {
if (population.length === 0) {
const populationSize = parseInt(populationSizeInput.value);
population = generatePopulation(populationSize);
}
const mutationRate = parseInt(mutationRateInput.value) / 100;
visualizePopulation(population, generation);
population = evolvePopulation(population, mutationRate);
generation++;
});
resetButton.addEventListener('click', () => {
population = [];
generation = 0;
visualizePopulation(population, generation);
});
</script>
</body>
</html>