|
| 1 | +import random |
| 2 | +import copy |
| 3 | +import logging |
| 4 | +from typing import Dict, List |
| 5 | +from backend.integrations.grid_interface import GridInterface |
| 6 | + |
| 7 | +class EvolutionaryOptimizer: |
| 8 | + """ |
| 9 | + The 'Discovery Engine'. |
| 10 | + Uses Genetic Algorithms to explore the parameter space and find |
| 11 | + 'Functionalities you don't know about' (Novel Optimizations). |
| 12 | + """ |
| 13 | + def __init__(self): |
| 14 | + self.grid = GridInterface() |
| 15 | + self.logger = logging.getLogger("EvoOptimizer") |
| 16 | + self.population_size = 10 |
| 17 | + self.generations = 5 |
| 18 | + |
| 19 | + def evolve_profile(self, profile: Dict) -> Dict: |
| 20 | + """ |
| 21 | + Takes a base profile and evolves it to maximize efficiency/stability. |
| 22 | + Returns the 'Best Mutant'. |
| 23 | + """ |
| 24 | + self.logger.info("Starting Evolutionary Discovery...") |
| 25 | + |
| 26 | + # 1. Initialize Population (Mutants) |
| 27 | + population = [self._mutate(profile) for _ in range(self.population_size)] |
| 28 | + |
| 29 | + for gen in range(self.generations): |
| 30 | + # 2. Evaluate Fitness via Simulation |
| 31 | + fitness_scores = [] |
| 32 | + for mutant in population: |
| 33 | + score = self._evaluate_fitness(mutant) |
| 34 | + fitness_scores.append((score, mutant)) |
| 35 | + |
| 36 | + # 3. Selection (Survival of the Fittest) |
| 37 | + fitness_scores.sort(key=lambda x: x[0], reverse=True) |
| 38 | + top_performers = [x[1] for x in fitness_scores[:int(self.population_size / 2)]] |
| 39 | + |
| 40 | + self.logger.info(f"Generation {gen}: Best Score = {fitness_scores[0][0]}") |
| 41 | + |
| 42 | + # 4. Reproduction (Breeding/Mutation) |
| 43 | + new_population = top_performers[:] |
| 44 | + while len(new_population) < self.population_size: |
| 45 | + parent = random.choice(top_performers) |
| 46 | + child = self._mutate(parent) |
| 47 | + new_population.append(child) |
| 48 | + |
| 49 | + population = new_population |
| 50 | + |
| 51 | + best_mutant = fitness_scores[0][1] |
| 52 | + return best_mutant |
| 53 | + |
| 54 | + def _mutate(self, profile: Dict) -> Dict: |
| 55 | + """ |
| 56 | + Randomly alters profile parameters (Feed Rate, Strategy). |
| 57 | + """ |
| 58 | + mutant = copy.deepcopy(profile) |
| 59 | + for segment in mutant.get("segments", []): |
| 60 | + # Mutation: Random Feed Rate Adjustment |
| 61 | + if random.random() < 0.3: |
| 62 | + feed = segment.get("optimized_feed", 1000) |
| 63 | + # Try something wild? |
| 64 | + new_feed = feed * random.uniform(0.8, 1.5) |
| 65 | + segment["optimized_feed"] = int(new_feed) |
| 66 | + |
| 67 | + # Mutation: Strategy Switch (Novelty) |
| 68 | + if random.random() < 0.1: |
| 69 | + segment["strategy"] = random.choice(["trochoidal", "adaptive", "plunge"]) |
| 70 | + |
| 71 | + return mutant |
| 72 | + |
| 73 | + def _evaluate_fitness(self, profile: Dict) -> float: |
| 74 | + """ |
| 75 | + Simulates the profile and assigns a score. |
| 76 | + Score = Speed - Risk - Energy |
| 77 | + """ |
| 78 | + total_time = 0 |
| 79 | + risk_penalty = 0 |
| 80 | + |
| 81 | + for segment in profile.get("segments", []): |
| 82 | + # Simulation |
| 83 | + status = self.grid.simulate_segment(segment) |
| 84 | + if status == "COLLISION": |
| 85 | + return -1000.0 # Instant Death |
| 86 | + elif status == "RISK": |
| 87 | + risk_penalty += 50 |
| 88 | + |
| 89 | + # Efficiency |
| 90 | + feed = segment.get("optimized_feed", 1000) |
| 91 | + dist = 10 # Mock distance |
| 92 | + time_taken = dist / feed |
| 93 | + total_time += time_taken |
| 94 | + |
| 95 | + # Fitness Function |
| 96 | + score = (1.0 / total_time) * 1000 - risk_penalty |
| 97 | + return score |
0 commit comments