UNPKG

tycho-solver

Version:

Evolutionary computation and optimization library

78 lines 3.49 kB
import { SequentialOperator } from '../../../core/pipeline/SequentialOperator'; /** * Orchestrates the main evolutionary loop for the Memetic Algorithm. * This is a standalone component to keep the core class minimal. */ export async function memeticLoop(population, config, localSearcher, updateBest, applyLocalSearch, rng) { let bestIndividual = null; for (let gen = 0; gen < config.generations; gen++) { // Step 1: Selection and offspring creation const selectionAndOffspringStep = { apply: async (pop) => { const newPopulation = []; const fitnesses = pop.map(ind => ind.fitness); while (newPopulation.length < config.populationSize) { const parents = config.selectionOperator.select(pop, fitnesses, 2); const parent1 = parents[0]; const parent2 = parents[1] ?? parent1; const r1 = rng ? rng.random() : Math.random(); let offspringGenome; if (r1 < config.crossoverRate) { const crossRes = config.crossoverOperator.crossover(parent1.genome, parent2.genome); const children = crossRes && typeof crossRes.then === 'function' ? await crossRes : crossRes; offspringGenome = children[0]; } else { offspringGenome = parent1.genome; } const r2 = rng ? rng.random() : Math.random(); if (r2 < config.mutationRate) { offspringGenome = config.mutationOperator.mutate(offspringGenome); } const r3 = rng ? rng.random() : Math.random(); if (r3 < config.localSearchRate) { offspringGenome = await applyLocalSearch(offspringGenome, config, localSearcher); } const offspringFitness = await config.evaluationOperator.evaluate(offspringGenome); newPopulation.push({ genome: offspringGenome, fitness: offspringFitness }); } return newPopulation; } }; // Step 2: Replacement const replacementStep = { apply: async (newPopulation) => { if (config.replacementOperator) { const replaced = await config.replacementOperator.replace(population, newPopulation, newPopulation.map(ind => ind.fitness)); population = replaced; } else { population = newPopulation; } return population; } }; const pipeline = new SequentialOperator([ selectionAndOffspringStep, replacementStep ]); population = await pipeline.apply(population); bestIndividual = updateBest(population); // Termination (optional) if (config.terminationOperator && config.terminationOperator.shouldTerminate({ generation: gen, fitness: bestIndividual?.fitness, population })) { break; } } return bestIndividual; } //# sourceMappingURL=LoopOperator.js.map