UNPKG

tycho-solver

Version:

Evolutionary computation and optimization library

77 lines (76 loc) 4.07 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.memeticLoop = memeticLoop; const SequentialOperator_1 = require("../../../core/pipeline/SequentialOperator"); /** * Orchestrates the main evolutionary loop for the Memetic Algorithm. * This is a standalone component to keep the core class minimal. */ function memeticLoop(population, config, localSearcher, updateBest, applyLocalSearch) { return __awaiter(this, void 0, void 0, function* () { let bestIndividual = null; for (let gen = 0; gen < config.generations; gen++) { const fitnesses = population.map(ind => ind.fitness); // Step 1: Selection and offspring creation const selectionAndOffspringStep = { apply: (pop) => __awaiter(this, void 0, void 0, function* () { const newPopulation = []; const fitnesses = pop.map(ind => ind.fitness); while (newPopulation.length < config.populationSize) { const parents = config.selectionOperator.select(pop, fitnesses, 2); const [parent1, parent2] = parents; let offspringGenome = Math.random() < config.crossoverRate ? config.crossoverOperator.crossover(parent1.genome, parent2.genome)[0] : parent1.genome; if (Math.random() < config.mutationRate) { offspringGenome = config.mutationOperator.mutate(offspringGenome); } if (Math.random() < config.localSearchRate) { offspringGenome = yield applyLocalSearch(offspringGenome, config, localSearcher); } const offspringFitness = yield config.evaluationOperator.evaluate(offspringGenome); newPopulation.push({ genome: offspringGenome, fitness: offspringFitness }); } return newPopulation; }) }; // Step 2: Replacement const replacementStep = { apply: (newPopulation) => __awaiter(this, void 0, void 0, function* () { if (config.replacementOperator) { const replaced = yield config.replacementOperator.replace(population, newPopulation, newPopulation.map(ind => ind.fitness)); population = replaced; } else { population = newPopulation; } return population; }) }; const pipeline = new SequentialOperator_1.SequentialOperator([ selectionAndOffspringStep, replacementStep ]); population = yield pipeline.apply(population); bestIndividual = updateBest(population); // Termination (optional) if (config.terminationOperator && config.terminationOperator.shouldTerminate({ generation: gen, fitness: bestIndividual === null || bestIndividual === void 0 ? void 0 : bestIndividual.fitness, population })) { break; } } return bestIndividual; }); }