UNPKG

genetic-search

Version:

Multiprocessing genetic algorithm implementation library

303 lines 11.4 kB
"use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); 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 __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; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.WeightedAgeAveragePhenomeCache = exports.AveragePhenomeCache = exports.SimplePhenomeCache = exports.DummyPhenomeCache = void 0; var utils_1 = require("./utils"); /** * A dummy phenome cache implementation that does nothing. * * This class is used when the {@link GeneticSearch} is created without a * phenome cache. * * @category Cache * @category Strategies */ var DummyPhenomeCache = /** @class */ (function () { function DummyPhenomeCache() { } DummyPhenomeCache.prototype.getReady = function (_) { return undefined; }; DummyPhenomeCache.prototype.get = function (_, defaultValue) { return defaultValue; }; DummyPhenomeCache.prototype.set = function (_, __) { return; }; DummyPhenomeCache.prototype.clear = function (_) { return; }; DummyPhenomeCache.prototype.export = function () { return {}; }; DummyPhenomeCache.prototype.import = function (_) { return; }; return DummyPhenomeCache; }()); exports.DummyPhenomeCache = DummyPhenomeCache; /** * A simple phenome cache implementation. * * This cache stores the constant phenome value for each genome. * * @category Cache * @category Strategies */ var SimplePhenomeCache = /** @class */ (function () { function SimplePhenomeCache() { this.cache = new Map(); } SimplePhenomeCache.prototype.get = function (genomeId, defaultValue) { return this.cache.has(genomeId) ? this.cache.get(genomeId) : defaultValue; }; SimplePhenomeCache.prototype.getReady = function (genomeId) { return this.cache.has(genomeId) ? this.get(genomeId) : undefined; }; SimplePhenomeCache.prototype.set = function (genomeId, phenome) { this.cache.set(genomeId, phenome); }; SimplePhenomeCache.prototype.clear = function (excludeGenomeIds) { var e_1, _a; var excludeIdsSet = new Set(excludeGenomeIds); try { for (var _b = __values(this.cache.keys()), _c = _b.next(); !_c.done; _c = _b.next()) { var id = _c.value; if (!excludeIdsSet.has(id)) { this.cache.delete(id); } } } 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; } } }; SimplePhenomeCache.prototype.export = function () { return Object.fromEntries(this.cache); }; SimplePhenomeCache.prototype.import = function (data) { var e_2, _a; this.cache.clear(); try { for (var _b = __values(Object.entries(data)), _c = _b.next(); !_c.done; _c = _b.next()) { var _d = __read(_c.value, 2), id = _d[0], cacheItem = _d[1]; this.cache.set(Number(id), cacheItem); } } 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 SimplePhenomeCache; }()); exports.SimplePhenomeCache = SimplePhenomeCache; /** * A phenome cache implementation that stores the phenome for each genome as a * weighted average of all phenome that have been set for that genome. * * @category Cache * @category Strategies */ var AveragePhenomeCache = /** @class */ (function () { function AveragePhenomeCache() { /** * A map of genome IDs to their respective phenome and the number of times they have been set. * * The key is the genome ID, and the value is an array with two elements. The first element is the * current phenome for the genome, and the second element is the number of times the phenome have * been set. */ this.cache = new Map(); } AveragePhenomeCache.prototype.get = function (genomeId, defaultValue) { if (!this.cache.has(genomeId)) { return defaultValue; } var _a = __read(this.cache.get(genomeId), 2), row = _a[0], count = _a[1]; return row.map(function (x) { return x / count; }); }; AveragePhenomeCache.prototype.getReady = function () { return undefined; }; AveragePhenomeCache.prototype.set = function (genomeId, phenome) { if (!this.cache.has(genomeId)) { this.cache.set(genomeId, [phenome, 1]); return; } var _a = __read(this.cache.get(genomeId), 2), row = _a[0], count = _a[1]; this.cache.set(genomeId, [row.map(function (x, i) { return x + phenome[i]; }), count + 1]); }; AveragePhenomeCache.prototype.clear = function (excludeGenomeIds) { var e_3, _a; var excludeIdsSet = new Set(excludeGenomeIds); try { for (var _b = __values(this.cache.keys()), _c = _b.next(); !_c.done; _c = _b.next()) { var id = _c.value; if (!excludeIdsSet.has(id)) { this.cache.delete(id); } } } 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; } } }; AveragePhenomeCache.prototype.export = function () { return Object.fromEntries(this.cache); }; AveragePhenomeCache.prototype.import = function (data) { var e_4, _a; this.cache.clear(); try { for (var _b = __values(Object.entries(data)), _c = _b.next(); !_c.done; _c = _b.next()) { var _d = __read(_c.value, 2), id = _d[0], cacheItem = _d[1]; this.cache.set(Number(id), cacheItem); } } 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; } } }; return AveragePhenomeCache; }()); exports.AveragePhenomeCache = AveragePhenomeCache; /** * A phenome cache implementation that stores the phenome for each genome as a * weighted average of all phenome that have been set for that genome. * * The closer the genome age is to 0, the closer the phenome are to the average phenome of the population, * which helps to combat outliers for new genomes. * * @category Cache * @category Strategies */ var WeightedAgeAveragePhenomeCache = /** @class */ (function (_super) { __extends(WeightedAgeAveragePhenomeCache, _super); /** * Constructs a new WeightedAgeAveragePhenomeCache. * @param weight The weight factor used for calculating the weighted average. */ function WeightedAgeAveragePhenomeCache(weight) { var _this = _super.call(this) || this; /** * The current average phenome row, or undefined if not yet calculated. */ _this.averageRow = undefined; _this.weight = weight; return _this; } WeightedAgeAveragePhenomeCache.prototype.set = function (genomeId, phenome) { _super.prototype.set.call(this, genomeId, phenome); this.resetAverageRow(); }; WeightedAgeAveragePhenomeCache.prototype.get = function (genomeId, defaultValue) { var _this = this; var row = _super.prototype.get.call(this, genomeId, defaultValue); if (row === undefined) { return undefined; } if (!this.refreshAverageRow()) { return row; } var _a = __read(this.cache.get(genomeId), 2), age = _a[1]; var averageDiff = (0, utils_1.arrayBinaryOperation)(row, this.averageRow, function (lhs, rhs) { return lhs - rhs; }); var weightedAverageDiff = averageDiff.map(function (x) { return x * _this.weight / age; }); return (0, utils_1.arrayBinaryOperation)(row, weightedAverageDiff, function (lhs, rhs) { return lhs - rhs; }); }; WeightedAgeAveragePhenomeCache.prototype.refreshAverageRow = function () { var e_5, _a; if (this.cache.size === 0) { this.resetAverageRow(); return false; } var weightedTotal = 0; var result = (0, utils_1.createFilledArray)(this.getPhenomeCount(), 0); try { for (var _b = __values(this.cache.values()), _c = _b.next(); !_c.done; _c = _b.next()) { var phenome = _c.value; var _d = __read(phenome, 2), row = _d[0], weight = _d[1]; for (var i = 0; i < row.length; ++i) { result[i] += row[i]; } weightedTotal += weight; } } 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; } } this.averageRow = result.map(function (x) { return x / weightedTotal; }); return true; }; WeightedAgeAveragePhenomeCache.prototype.resetAverageRow = function () { this.averageRow = undefined; }; WeightedAgeAveragePhenomeCache.prototype.getPhenomeCount = function () { return this.cache.values().next().value[0].length; }; return WeightedAgeAveragePhenomeCache; }(AveragePhenomeCache)); exports.WeightedAgeAveragePhenomeCache = WeightedAgeAveragePhenomeCache; //# sourceMappingURL=cache.js.map