genetic-search
Version:
Multiprocessing genetic algorithm implementation library
751 lines • 34.6 kB
JavaScript
"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());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __read = (this && this.__read) || function (o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m) return o;
var i = m.call(o), r, ar = [], e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
}
catch (error) { e = { error: error }; }
finally {
try {
if (r && !r.done && (m = i["return"])) m.call(i);
}
finally { if (e) throw e.error; }
}
return ar;
};
var __values = (this && this.__values) || function(o) {
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
if (m) return m.call(o);
if (o && typeof o.length === "number") return {
next: function () {
if (o && i >= o.length) o = void 0;
return { value: o && o[i++], done: !o };
}
};
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
};
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ComposedGeneticSearch = exports.GeneticSearch = void 0;
var utils_1 = require("./utils");
var itertools_1 = require("./itertools");
var stats_1 = require("./stats");
/**
* A genetic search algorithm.
*
* @template TGenome The type of genome objects in the population.
*
* @remarks
* This class implements the genetic search algorithm. The algorithm is
* configured using the [[GeneticSearchConfig]] object.
*
* The algorithm uses the following components, which can be customized by
* providing a custom implementation:
*
* - A [[PopulateStrategyInterface]] to generate the initial population.
* - A [[MutationStrategyInterface]] to mutate the population.
* - A [[CrossoverStrategyInterface]] to cross over the population.
* - A [[PhenomeStrategyInterface]] to calculate the phenome of the population.
* - A [[FitnessStrategyInterface]] to calculate the fitness of the population.
* - A [[PhenomeCacheInterface]] to cache the phenome of the population.
*
* @category Genetic Algorithm
*/
var GeneticSearch = /** @class */ (function () {
/**
* Constructs a new instance of the GeneticSearch class.
*
* @param config - The configuration for the genetic search.
* @param strategy - The strategy configuration for genetic operations.
* @param idGenerator - An optional ID generator for the genomes.
*/
function GeneticSearch(config, strategy, idGenerator) {
var _a;
this._generation = 1;
this._populationBuffer = [];
this.idGenerator = idGenerator !== null && idGenerator !== void 0 ? idGenerator : new utils_1.IdGenerator();
this.genomeStatsManager = new stats_1.GenomeStatsManager();
this.populationSummaryManager = new stats_1.PopulationSummaryManager();
this.strategy = strategy;
this.config = config;
this._population = strategy.populate.populate((_a = config.startPopulationSize) !== null && _a !== void 0 ? _a : config.populationSize, this.idGenerator);
this._populationBuffer = this.population;
}
Object.defineProperty(GeneticSearch.prototype, "generation", {
/**
* The current generation number.
*
* @returns The current generation number.
*/
get: function () {
return this._generation;
},
enumerable: false,
configurable: true
});
Object.defineProperty(GeneticSearch.prototype, "bestGenome", {
/**
* Gets the best genome from the population.
*
* @returns The best genome from the population.
*/
get: function () {
return this._population[0];
},
enumerable: false,
configurable: true
});
Object.defineProperty(GeneticSearch.prototype, "population", {
/**
* The current population of genomes.
*
* @returns The current population of genomes.
*/
get: function () {
return this._population;
},
/**
* Sets the current population of genomes.
*
* @param population The new population of genomes.
*/
set: function (population) {
this.setPopulation(population);
},
enumerable: false,
configurable: true
});
/**
* Sets the current population of genomes.
*
* @param population The new population of genomes.
* @param resetIdGenerator Whether to reset the ID generator. Defaults to true.
*/
GeneticSearch.prototype.setPopulation = function (population, resetIdGenerator) {
if (resetIdGenerator === void 0) { resetIdGenerator = true; }
if (resetIdGenerator) {
this.idGenerator.reset(population);
}
this._populationBuffer = population;
};
Object.defineProperty(GeneticSearch.prototype, "partitions", {
/**
* Calculates and returns the partitions of the population for the genetic operations.
*
* @returns A tuple containing:
* - The number of genomes that will survive.
* - The number of genomes that will be created by crossover.
* - The number of genomes that will be created by mutation.
*/
get: function () {
// Calculate the number of genomes that will survive based on the survival rate.
var countToSurvive = Math.round(this.config.populationSize * this.config.survivalRate);
// Calculate the number of genomes that will die (not survive).
var countToDie = this.config.populationSize - countToSurvive;
// Calculate the number of new genomes that will be created by crossover.
var countToCross = Math.round(countToDie * this.config.crossoverRate);
// Calculate the number of new genomes that will be created by mutation.
var countToMutate = countToDie - countToCross;
return [countToSurvive, countToCross, countToMutate];
},
enumerable: false,
configurable: true
});
Object.defineProperty(GeneticSearch.prototype, "cache", {
/**
* Retrieves the phenome cache used by the genetic search algorithm.
*
* @returns {PhenomeCacheInterface} The phenome cache instance.
*/
get: function () {
return this.strategy.cache;
},
enumerable: false,
configurable: true
});
/**
* Retrieves the population summary, optionally rounding the statistics to a specified precision.
*
* @param roundPrecision Optional. The number of decimal places to round the summary statistics to.
* If not provided, no rounding is applied.
* @returns The population summary, with statistics rounded to the specified precision if provided.
*/
GeneticSearch.prototype.getPopulationSummary = function (roundPrecision) {
return roundPrecision === undefined
? this.populationSummaryManager.get()
: this.populationSummaryManager.getRounded(roundPrecision);
};
/**
* Runs the genetic search algorithm.
*
* @param config The configuration for the genetic search algorithm.
* @returns A promise that resolves when the algorithm has finished running.
*/
GeneticSearch.prototype.fit = function (config) {
return __awaiter(this, void 0, void 0, function () {
var generationsCount, i, generation, result;
var _a;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
generationsCount = (_a = config.generationsCount) !== null && _a !== void 0 ? _a : Infinity;
i = 0;
_b.label = 1;
case 1:
if (!(i < generationsCount)) return [3 /*break*/, 4];
generation = this.generation;
// Refresh the population from the population buffer.
this.refreshPopulation();
// Clear the cache of phenome.
this.clearCache();
// Run the before step callback if specified.
if (config.beforeStep) {
config.beforeStep(generation);
}
return [4 /*yield*/, this.fitStep(config.scheduler)];
case 2:
result = _b.sent();
// Run the after step callback if specified.
if (config.afterStep) {
config.afterStep(generation, result);
}
// Check if the stop condition is met and stop the algorithm if it is.
if (config.stopCondition && config.stopCondition(result)) {
return [3 /*break*/, 4];
}
_b.label = 3;
case 3:
i++;
return [3 /*break*/, 1];
case 4: return [2 /*return*/];
}
});
});
};
/**
* Runs a single step of the genetic search algorithm.
*
* @param scheduler Optional. The scheduler to use for the genetic search algorithm.
* @returns A promise that resolves with the fitness of the best genome in the population.
*/
GeneticSearch.prototype.fitStep = function (scheduler) {
return __awaiter(this, void 0, void 0, function () {
var phenomeMatrix, fitnessColumn, sortedEvaluatedPopulation, _a, sortedPopulation, sortedFitnessColumn;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
// Refresh population from buffer.
this.refreshPopulation();
return [4 /*yield*/, this.strategy.phenome.collect(this._population, this.strategy.cache)];
case 1:
phenomeMatrix = _b.sent();
fitnessColumn = this.strategy.fitness.score(phenomeMatrix);
// Update genome statistics.
this.genomeStatsManager.update(this.population, phenomeMatrix, fitnessColumn);
sortedEvaluatedPopulation = this.strategy.sorting.sort((0, utils_1.createEvaluatedPopulation)(this._population, fitnessColumn, phenomeMatrix));
_a = __read((0, utils_1.extractEvaluatedPopulation)(sortedEvaluatedPopulation), 2), sortedPopulation = _a[0], sortedFitnessColumn = _a[1];
// Update population summary.
this.populationSummaryManager.update(sortedPopulation);
// Step the scheduler if provided.
if (scheduler !== undefined) {
scheduler.step(sortedEvaluatedPopulation);
}
// Run crossover and mutation.
this.refreshPopulationBuffer(sortedEvaluatedPopulation);
// Increase generation counter.
this._generation++;
// Return the sorted fitness column.
return [2 /*return*/, sortedFitnessColumn];
}
});
});
};
/**
* Clears the cache.
*
* @remarks
* This method clears the cache, which is used to store the phenome of the genomes.
* The cache is used to avoid re-calculating the phenome of the genomes if they remain unchanged.
*/
GeneticSearch.prototype.clearCache = function () {
this.strategy.cache.clear(this.population.map(function (genome) { return genome.id; }));
};
/**
* Refreshes the population.
*
* @remarks
* This method is used to refresh the population, which is the array of genomes that are currently being evaluated.
* The population is refreshed by swapping the current population with the population buffer.
*/
GeneticSearch.prototype.refreshPopulation = function () {
this._population = this._populationBuffer;
};
/**
* Crosses the given input population.
*
* @param input The population of genomes to cross.
* @param count The number of new genomes to create.
* @returns An array of new genomes created by crossing the input population.
*/
GeneticSearch.prototype.crossover = function (input, count) {
var e_1, _a;
var newPopulation = [];
try {
// Select parents for crossover. Then for each parents array, cross them and create a new genome.
for (var _b = __values(this.strategy.selection.selectForCrossover(input, count)), _c = _b.next(); !_c.done; _c = _b.next()) {
var parents = _c.value;
var crossedGenome = this.strategy.crossover.cross(parents, this.idGenerator.nextId());
// Initialize the statistics for the new genome.
this.genomeStatsManager.initItem(crossedGenome, 'crossover', parents);
newPopulation.push(crossedGenome);
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
}
finally { if (e_1) throw e_1.error; }
}
return newPopulation;
};
/**
* Mutates the given input population.
*
* @param input The population of genomes to mutate.
* @param count The number of new genomes to create.
* @returns An array of new genomes created by mutating the input population.
*/
GeneticSearch.prototype.mutate = function (input, count) {
var e_2, _a;
var newPopulation = [];
try {
// Select parents for mutation. Then for each parent, mutate it and create a new genome.
for (var _b = __values(this.strategy.selection.selectForMutation(input, count)), _c = _b.next(); !_c.done; _c = _b.next()) {
var genome = _c.value;
// Mutate the parent and create a new genome.
var mutatedGenome = this.strategy.mutation.mutate(genome, this.idGenerator.nextId());
// Initialize the statistics for the new genome.
this.genomeStatsManager.initItem(mutatedGenome, 'mutation', [genome]);
newPopulation.push(mutatedGenome);
}
}
catch (e_2_1) { e_2 = { error: e_2_1 }; }
finally {
try {
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
}
finally { if (e_2) throw e_2.error; }
}
// Return the new population.
return newPopulation;
};
/**
* Refreshes the population buffer from the evaluated population.
*
* @param input The population of genomes to refresh the population buffer with.
*/
GeneticSearch.prototype.refreshPopulationBuffer = function (input) {
var _a = __read(this.partitions, 3), countToSurvive = _a[0], countToCross = _a[1], countToMutate = _a[2];
var sortedPopulation = input.map(function (x) { return x.genome; });
// Select the top fittest genomes to survive.
var survivedEvaluatedPopulation = input.slice(0, countToSurvive);
var survivedPopulation = survivedEvaluatedPopulation.map(function (x) { return x.genome; });
// Select parents for crossover. Then for each parents array, cross them and create a new genome.
var crossedPopulation = this.crossover(input, countToCross);
// Select parents for mutation. Then for each parent, mutate it and create a new genome.
var mutatedPopulation = this.mutate(input, countToMutate);
// Set the current population to the sorted population.
this._population = sortedPopulation;
// Set the next population to the combination of the survived, crossed, and mutated populations.
this._populationBuffer = __spreadArray(__spreadArray(__spreadArray([], __read(survivedPopulation), false), __read(crossedPopulation), false), __read(mutatedPopulation), false);
};
return GeneticSearch;
}());
exports.GeneticSearch = GeneticSearch;
/**
* A composed genetic search algorithm that combines multiple genetic search strategies.
*
* @template TGenome The type of genome objects in the population.
*
* @remarks
* This class implements a composite genetic search algorithm that utilizes multiple
* genetic search strategies, including eliminators and a final strategy. The algorithm
* is configured using the [[ComposedGeneticSearchConfig]] object.
*
* The algorithm integrates the following components, which can be customized by
* providing custom implementations:
*
* - A [[GeneticSearchStrategyConfig]] to define the strategy for the genetic operations.
* - An [[IdGeneratorInterface]] to generate unique IDs for the genomes.
*
* @category Genetic Algorithm
*/
var ComposedGeneticSearch = /** @class */ (function () {
/**
* Constructs a new instance of the ComposedGeneticSearch class.
*
* @param config - The configuration for the composed genetic search algorithm.
* @param strategy - The strategy configuration for genetic operations.
* @param idGenerator - An optional ID generator for the genomes.
*/
function ComposedGeneticSearch(config, strategy, idGenerator) {
var _this = this;
this.config = config;
this.strategy = strategy;
this.idGenerator = idGenerator !== null && idGenerator !== void 0 ? idGenerator : new utils_1.IdGenerator();
this.eliminators = __spreadArray([], __read((0, itertools_1.repeat)(function () { return new GeneticSearch(config.eliminators, strategy, _this.idGenerator); }, config.final.populationSize)), false).map(function (factory) { return factory(); });
this.final = new GeneticSearch(config.final, strategy, this.idGenerator);
}
Object.defineProperty(ComposedGeneticSearch.prototype, "generation", {
/**
* The current generation number.
*
* @returns The current generation number.
*/
get: function () {
return this.final.generation;
},
enumerable: false,
configurable: true
});
Object.defineProperty(ComposedGeneticSearch.prototype, "bestGenome", {
/**
* Gets the best genome from the population.
*
* @returns The best genome from the population.
*/
get: function () {
return this.final.bestGenome;
},
enumerable: false,
configurable: true
});
Object.defineProperty(ComposedGeneticSearch.prototype, "population", {
/**
* The current population of genomes.
*
* @returns The current population of genomes.
*/
get: function () {
var e_3, _a;
// Initialize an empty population result array.
var result = [];
// Add genomes from the final population, limited to the configured size.
result.push.apply(result, __spreadArray([], __read(this.final.population.slice(0, this.config.final.populationSize)), false));
try {
// Add genomes from each eliminator's population.
for (var _b = __values(this.eliminators), _c = _b.next(); !_c.done; _c = _b.next()) {
var eliminators = _c.value;
result.push.apply(result, __spreadArray([], __read(eliminators.population), false));
}
}
catch (e_3_1) { e_3 = { error: e_3_1 }; }
finally {
try {
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
}
finally { if (e_3) throw e_3.error; }
}
// Return the combined population result.
return result;
},
set: function (population) {
this.setPopulation(population);
},
enumerable: false,
configurable: true
});
/**
* Sets the current population of genomes.
*
* @param population The new population of genomes.
* @param resetIdGenerator Whether to reset the ID generator. Defaults to true.
*/
ComposedGeneticSearch.prototype.setPopulation = function (population, resetIdGenerator) {
var e_4, _a;
if (resetIdGenerator === void 0) { resetIdGenerator = true; }
// If the resetIdGenerator option is specified, reset the ID generator.
if (resetIdGenerator) {
this.idGenerator.reset(population);
}
// Set the population of the final search algorithm.
this.final.setPopulation(population.slice(0, this.final.population.length), false);
// Remove the genomes that were assigned to the final search algorithm.
population = population.slice(this.final.population.length);
try {
// Assign the remaining genomes to the eliminators.
for (var _b = __values(this.eliminators), _c = _b.next(); !_c.done; _c = _b.next()) {
var eliminator = _c.value;
// Set the population of the eliminator.
eliminator.setPopulation(population.slice(0, eliminator.population.length), false);
// Remove the genomes that were assigned to the eliminator.
population = population.slice(eliminator.population.length);
}
}
catch (e_4_1) { e_4 = { error: e_4_1 }; }
finally {
try {
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
}
finally { if (e_4) throw e_4.error; }
}
};
Object.defineProperty(ComposedGeneticSearch.prototype, "partitions", {
/**
* Calculates and returns the partitions of the population for the genetic operations.
*
* @returns A tuple containing:
* - The number of genomes that will survive.
* - The number of genomes that will be created by crossover.
* - The number of genomes that will be created by mutation.
*/
get: function () {
var e_5, _a;
// Calculate the total number of genomes that will survive, be crossed, and be mutated.
// This is the sum of the counts from each eliminator.
var result = [0, 0, 0];
try {
for (var _b = __values(this.eliminators), _c = _b.next(); !_c.done; _c = _b.next()) {
var eliminators = _c.value;
var _d = __read(eliminators.partitions, 3), countToSurvive = _d[0], countToCross = _d[1], countToMutate = _d[2];
// Add the counts from the current eliminator to the result.
result[0] += countToSurvive;
result[1] += countToCross;
result[2] += countToMutate;
}
}
catch (e_5_1) { e_5 = { error: e_5_1 }; }
finally {
try {
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
}
finally { if (e_5) throw e_5.error; }
}
return result;
},
enumerable: false,
configurable: true
});
Object.defineProperty(ComposedGeneticSearch.prototype, "cache", {
/**
* Retrieves the phenome cache used by the genetic search algorithm.
*
* @returns {PhenomeCacheInterface} The phenome cache instance.
*/
get: function () {
return this.strategy.cache;
},
enumerable: false,
configurable: true
});
/**
* Retrieves the population summary, optionally rounding the statistics to a specified precision.
*
* @param roundPrecision Optional. The number of decimal places to round the summary statistics to.
* If not provided, no rounding is applied.
* @returns The population summary, with statistics rounded to the specified precision if provided.
*/
ComposedGeneticSearch.prototype.getPopulationSummary = function (roundPrecision) {
return this.final.getPopulationSummary(roundPrecision);
};
/**
* Runs the genetic search algorithm.
*
* @param config The configuration for the genetic search algorithm.
* @returns A promise that resolves when the algorithm has finished running.
*/
ComposedGeneticSearch.prototype.fit = function (config) {
return __awaiter(this, void 0, void 0, function () {
var generationsCount, i, result;
var _a;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
generationsCount = (_a = config.generationsCount) !== null && _a !== void 0 ? _a : Infinity;
i = 0;
_b.label = 1;
case 1:
if (!(i < generationsCount)) return [3 /*break*/, 4];
// Refresh the population for the current generation.
this.refreshPopulation();
// Clear any cached phenome to ensure accurate calculations.
this.clearCache();
// Execute the before-step callback if it is provided in the config.
if (config.beforeStep) {
config.beforeStep(i);
}
return [4 /*yield*/, this.fitStep(config.scheduler)];
case 2:
result = _b.sent();
// Execute the after-step callback if it is provided in the config.
if (config.afterStep) {
config.afterStep(i, result);
}
// Check if the stop condition is met, and break the loop if so.
if (config.stopCondition && config.stopCondition(result)) {
return [3 /*break*/, 4];
}
_b.label = 3;
case 3:
i++;
return [3 /*break*/, 1];
case 4: return [2 /*return*/];
}
});
});
};
/**
* Runs a single step of the genetic search algorithm.
*
* @param scheduler Optional. The scheduler to use for the genetic search algorithm.
* @returns A promise that resolves with the fitness of the best genome in the population.
*/
ComposedGeneticSearch.prototype.fitStep = function (scheduler) {
return __awaiter(this, void 0, void 0, function () {
var _a, _b, eliminators, e_6_1;
var e_6, _c;
return __generator(this, function (_d) {
switch (_d.label) {
case 0:
_d.trys.push([0, 5, 6, 7]);
_a = __values(this.eliminators), _b = _a.next();
_d.label = 1;
case 1:
if (!!_b.done) return [3 /*break*/, 4];
eliminators = _b.value;
return [4 /*yield*/, eliminators.fitStep()];
case 2:
_d.sent();
_d.label = 3;
case 3:
_b = _a.next();
return [3 /*break*/, 1];
case 4: return [3 /*break*/, 7];
case 5:
e_6_1 = _d.sent();
e_6 = { error: e_6_1 };
return [3 /*break*/, 7];
case 6:
try {
if (_b && !_b.done && (_c = _a.return)) _c.call(_a);
}
finally { if (e_6) throw e_6.error; }
return [7 /*endfinally*/];
case 7:
// Run crossing and mutation for the final population.
this.final.refreshPopulation();
// Set the population for the final population by combining the best genomes from the eliminators
// with the current population.
this.final.setPopulation(__spreadArray([], __read((0, itertools_1.distinctBy)(__spreadArray(__spreadArray([], __read(this.final.population), false), __read(this.bestGenomes), false), function (x) { return x.id; })), false), false);
return [4 /*yield*/, this.final.fitStep(scheduler)];
case 8:
// Run the final step of the genetic search algorithm.
return [2 /*return*/, _d.sent()];
}
});
});
};
/**
* Clears the cache.
*
* @remarks
* This method clears the cache, which is used to store the phenome of the genomes.
* The cache is used to avoid re-calculating the phenome of the genomes if they remain unchanged.
*/
ComposedGeneticSearch.prototype.clearCache = function () {
this.strategy.cache.clear(this.population.map(function (genome) { return genome.id; }));
};
/**
* Refreshes the population.
*
* @remarks
* This method is used to refresh the population, which is the array of genomes that are currently being evaluated.
* The population is refreshed by swapping the current population with the population buffer.
*/
ComposedGeneticSearch.prototype.refreshPopulation = function () {
var e_7, _a;
// Refresh the population for the final search algorithm.
this.final.refreshPopulation();
try {
// Refresh the population for each eliminator.
for (var _b = __values(this.eliminators), _c = _b.next(); !_c.done; _c = _b.next()) {
var eliminator = _c.value;
eliminator.refreshPopulation();
}
}
catch (e_7_1) { e_7 = { error: e_7_1 }; }
finally {
try {
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
}
finally { if (e_7) throw e_7.error; }
}
};
Object.defineProperty(ComposedGeneticSearch.prototype, "bestGenomes", {
/**
* Gets the best genomes from the eliminators.
*
* @remarks
* This method returns the best genomes from each eliminator.
* The best genomes are the genomes that have the highest fitness score.
* The best genomes are determined by calling {@link GeneticSearch.bestGenome} on each eliminator.
*
* @returns The best genomes from the eliminators.
*/
get: function () {
return this.eliminators.map(function (eliminators) { return eliminators.bestGenome; });
},
enumerable: false,
configurable: true
});
return ComposedGeneticSearch;
}());
exports.ComposedGeneticSearch = ComposedGeneticSearch;
//# sourceMappingURL=genetic.js.map