# Digitale Evolution mit genetischem Algorithmus ``` <!-- MIT License Copyright (c) 2025 Rob de Roy | Wolfram Consult GmbH & Co. KG Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --> <!DOCTYPE html> <html lang="de"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Genetischer Algorithmus</title> <style> /* Allgemeine Stile */ body { margin: 0; padding: 0; font-family: Arial, sans-serif; color: white; background-color: #121212; overflow: auto; /* Erlaube Scrollen, wenn der Inhalt zu groß wird */ } /* Partikelanimation */ canvas { position: fixed; /* Animation bleibt fixiert im Hintergrund */ top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; z-index: -1; /* Stelle sicher, dass die Animation hinter dem Content bleibt */ } /* Hauptcontainer */ .container { display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 20px; /* Füge Padding hinzu, um den Content vom Rand abzurücken */ max-width: 800px; /* Begrenze die Breite des Containers */ margin: 0 auto; /* Zentriere den Container horizontal */ } h1 { font-size: 3em; margin: 0 0 20px; text-shadow: 0 0 10px rgba(255, 255, 255, 0.5); } p.explanation { font-size: 1.2em; margin: 0 0 20px; max-width: 600px; text-align: center; line-height: 1.6; } input[type="text"], input[type="number"] { padding: 15px; width: 400px; font-size: 18px; border: none; border-radius: 5px; margin-bottom: 20px; background-color: rgba(255, 255, 255, 0.1); color: white; box-shadow: 0 0 10px rgba(255, 255, 255, 0.3); } button { padding: 10px 20px; font-size: 16px; color: white; border: none; border-radius: 5px; cursor: pointer; transition: transform 0.3s ease, box-shadow 0.3s ease; margin: 5px; } button.start { background-color: #4CAF50; box-shadow: 0 0 10px rgba(76, 175, 80, 0.5); } button.reset { background-color: #f44336; box-shadow: 0 0 10px rgba(244, 67, 54, 0.5); } button.speed { background-color: #2196F3; box-shadow: 0 0 10px rgba(33, 150, 243, 0.5); } label { font-size: 16px; margin-right: 10px; } input[type="checkbox"] { transform: scale(1.5); margin-right: 10px; } button:hover { transform: scale(1.1); box-shadow: 0 0 20px rgba(255, 255, 255, 0.8); } #output { margin-top: 20px; width: 100%; /* Mache das Ausgabefeld responsive */ max-width: 600px; /* Begrenze die maximale Breite */ height: 300px; overflow-y: auto; border: 2px solid rgba(255, 255, 255, 0.3); padding: 10px; background-color: rgba(0, 0, 0, 0.5); font-family: Courier, monospace; font-size: 14px; color: white; scrollbar-width: thin; scrollbar-color: rgba(255, 255, 255, 0.5) transparent; } #info { margin-top: 10px; font-size: 18px; color: rgba(255, 255, 255, 0.8); } #bestPhrase { color: #4CAF50; /* Grüne Schriftfarbe für die beste Phrase */ font-weight: bold; } #totalYears { color: #FFC107; /* Gelbe Schriftfarbe für die Gesamtdauer */ font-weight: bold; } </style> </head> <body> <!-- Partikelanimation --> <canvas id="particleCanvas"></canvas> <!-- Hauptinhalt --> <div class="container"> <h1>Genetischer Algorithmus</h1> <p class="explanation"> Willkommen beim <strong>Genetischen Algorithmus-Tool</strong>! Dieses Tool simuliert den Evolutionsprozess, um aus einer zufälligen Phrase dein Ziel zu erreichen. Dabei verwendet es Prinzipien wie Mutation, Selektion und Kreuzung, um nach und nach die richtige Lösung zu finden. <br> </p> <input type="text" id="targetInput" placeholder="Gib dein Ziel ein..." /> <label for="populationSize">Populationgröße (50–500): </label> <input type="number" id="populationSize" min="50" max="500" value="300" /> <label><input type="checkbox" id="eliteMode" checked> Elite behalten</label> <div> <button class="start" onclick="startEvolution()">Start Evolution</button> <button class="reset" onclick="resetEvolution()">Reset</button> <button class="speed" onclick="changeSpeed(-1)">Verlangsamen</button> <button class="speed" onclick="changeSpeed(1)">Beschleunigen</button> </div> <div id="info"> Generation: <span id="generation">0</span><br> Beste Phrase: <span id="bestPhrase"></span><br> Gesamtdauer: <span id="totalYears">0 Jahre</span> </div> <div id="output"></div> </div> <script> // Partikelanimation const canvas = document.getElementById("particleCanvas"); const ctx = canvas.getContext("2d"); canvas.width = window.innerWidth; canvas.height = window.innerHeight; window.addEventListener("resize", () => { canvas.width = window.innerWidth; canvas.height = window.innerHeight; }); class Particle { constructor(x, y) { this.x = x; this.y = y; this.size = Math.random() * 2 + 1; this.color = `rgba(255, 255, 255, ${Math.random() * 0.5 + 0.1})`; this.velocity = { x: (Math.random() - 0.5) * 2, y: (Math.random() - 0.5) * 2 }; this.gravity = 0.05; } update() { this.velocity.y += this.gravity; this.x += this.velocity.x; this.y += this.velocity.y; if (this.y + this.size > canvas.height) { this.velocity.y *= -0.5; } if (this.x + this.size > canvas.width || this.x - this.size < 0) { this.velocity.x *= -1; } } draw() { ctx.beginPath(); ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2); ctx.fillStyle = this.color; ctx.fill(); ctx.closePath(); } } let particles = []; function initParticles() { for (let i = 0; i < 100; i++) { particles.push(new Particle(Math.random() * canvas.width, Math.random() * canvas.height)); } } function animateParticles() { requestAnimationFrame(animateParticles); ctx.clearRect(0, 0, canvas.width, canvas.height); particles.forEach((particle, index) => { particle.update(); particle.draw(); // Verbinde Partikel particles.forEach((otherParticle, otherIndex) => { if (index !== otherIndex) { const dx = particle.x - otherParticle.x; const dy = particle.y - otherParticle.y; const distance = Math.sqrt(dx * dx + dy * dy); if (distance < 100) { ctx.strokeStyle = `rgba(255, 255, 255, ${1 - distance / 100})`; ctx.lineWidth = 0.5; ctx.beginPath(); ctx.moveTo(particle.x, particle.y); ctx.lineTo(otherParticle.x, otherParticle.y); ctx.stroke(); } } }); }); } initParticles(); animateParticles(); // Genetischer Algorithmus const charset = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~äöüßÄÖÜ"; // Erweiterter Zeichensatz let mutationRate = 0.02; let populationSize = 300; // Standardwert let population = []; let target = ""; let generation = 0; let evolutionInterval = null; // Für Geschwindigkeitssteuerung let speedFactor = 1; // Standardgeschwindigkeit let bestPhrase = ""; // Best Phrase global deklarieren class GeneticDNA { constructor(numGenes) { this.genes = []; this.fitness = 0; for (let i = 0; i < numGenes; i++) { this.genes[i] = charset[Math.floor(Math.random() * charset.length)]; } } calculateFitness(target) { let score = 0; for (let i = 0; i < this.genes.length; i++) { if (this.genes[i] === target[i]) { score++; } } this.fitness = score / target.length; } crossover(partner) { let child = new GeneticDNA(this.genes.length); let midpoint = Math.floor(Math.random() * this.genes.length); for (let i = 0; i < this.genes.length; i++) { if (i < midpoint) { child.genes[i] = this.genes[i]; } else { child.genes[i] = partner.genes[i]; } } return child; } mutate(mutationRate) { for (let i = 0; i < this.genes.length; i++) { if (Math.random() < mutationRate) { this.genes[i] = charset[Math.floor(Math.random() * charset.length)]; } } } getPhrase() { return this.genes.join(""); } } function startEvolution() { if (evolutionInterval) return; // Verhindert mehrere gleichzeitige Evolutionsprozesse target = document.getElementById("targetInput").value; if (!target) { alert("Bitte gib ein Ziel ein!"); return; } // Lese die Populationgröße aus dem Eingabefeld populationSize = parseInt(document.getElementById("populationSize").value, 10); if (isNaN(populationSize) || populationSize < 50 || populationSize > 500) { alert("Die Populationgröße muss zwischen 50 und 500 liegen."); return; } population = []; for (let i = 0; i < populationSize; i++) { population[i] = new GeneticDNA(target.length); } generation = 0; updateUI(); evolutionInterval = setInterval(evolve, 100 / speedFactor); // Anpassung an Geschwindigkeit } function evolve() { let highestFitness = 0; for (let phrase of population) { phrase.calculateFitness(target); if (phrase.fitness > highestFitness) { highestFitness = phrase.fitness; bestPhrase = phrase.getPhrase(); // Aktualisiere die globale Variable } } if (highestFitness === 1) { clearInterval(evolutionInterval); evolutionInterval = null; // Zeige das Ergebnis im Alert-Fenster const yearsPerGeneration = 30; // Durchschnittliche menschliche Generation const totalYears = generation * yearsPerGeneration; alert(`Ziel erreicht: "${target}"\nDie beteiligten Generationen hätten in der Realität ${totalYears} Jahre benötigt, um dieses Ziel zu erreichen.`); } let matingPool = []; for (let phrase of population) { let n = Math.floor(phrase.fitness * 100); for (let j = 0; j < n; j++) { matingPool.push(phrase); } } // Elitism-Option let eliteMode = document.getElementById("eliteMode").checked; let elites = []; if (eliteMode) { population.sort((a, b) => b.fitness - a.fitness); // Sortiere nach Fitness elites = population.slice(0, Math.ceil(populationSize * 0.1)); // Behalte die besten 10 % als Elite } for (let i = 0; i < population.length - elites.length; i++) { let partnerA = matingPool[Math.floor(Math.random() * matingPool.length)]; let partnerB = matingPool[Math.floor(Math.random() * matingPool.length)]; let child = partnerA.crossover(partnerB); child.mutate(mutationRate); population[i] = child; } // Füge die Elite zurück in die Population if (eliteMode) { population.splice(population.length - elites.length, 0, ...elites); } generation++; updateUI(); // UI mit bestPhrase und Gesamtdauer aktualisieren } function resetEvolution() { clearInterval(evolutionInterval); evolutionInterval = null; population = []; generation = 0; document.getElementById("targetInput").value = ""; document.getElementById("populationSize").value = 300; // Setze Standardwert zurück document.getElementById("info").innerHTML = ` Generation: <span id="generation">0</span><br> Beste Phrase: <span id="bestPhrase"></span><br> Gesamtdauer: <span id="totalYears">0 Jahre</span> `; document.getElementById("output").textContent = ""; } function changeSpeed(direction) { speedFactor += direction * 0.5; // Ändere Geschwindigkeit in Schritten von 0.5 speedFactor = Math.max(0.1, speedFactor); // Mindestgeschwindigkeit 0.1 if (evolutionInterval) { clearInterval(evolutionInterval); evolutionInterval = setInterval(evolve, 100 / speedFactor); // Aktualisiere Intervalldauer } } function updateUI() { // Berechne die Gesamtdauer in Jahren const yearsPerGeneration = 30; // Durchschnittliche menschliche Generation const totalYears = generation * yearsPerGeneration; // Aktualisiere das UI document.getElementById("info").innerHTML = ` Generation: <span id="generation">${generation}</span><br> Beste Phrase: <span id="bestPhrase">${bestPhrase || "noch keine Phrase"}</span><br> Gesamtdauer: <span id="totalYears">${totalYears} Jahre</span> `; // Aktualisiere das Ausgabefeld mit der aktuellen Population let output = document.getElementById("output"); output.textContent = population.map(p => p.getPhrase()).join("\n"); } </script> </body> <br> <p style="text-align: center;"><span style="color:#FFFFFF">&copy;</span><a href="https://wolfram-consult.com"><span style="color:#FFFFFF">by Wolfram Consult GmbH&amp;Co. KG</span></a></p> </html> ```