UNPKG

@adrianperea/genie.js

Version:

A highly flexible, data-agnostic, and UI-independent Genetic Algorithm Library

89 lines (73 loc) 2.77 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.selection = selection; exports.rouletteWheel = rouletteWheel; exports.stochasticUniversalSampling = stochasticUniversalSampling; function selection(population, numParents, selectionFunction) { return selectionFunction(population, numParents); } function rouletteWheel(population, num) { var wheel = _makeWheel(population); var parents = Array(num).fill(null).map(function () { return _getParentByRouletteWheel(wheel, population); }); return parents; } function _makeWheel(population) { var totalFitness = population.reduce(function (total, individual) { return total + individual.fitness; }, 0); // If all individuals have 0 fitness, // we should make all individuals have equal chances of getting chosen var relativeFitnesses = totalFitness !== 0 ? population.map(function (individual) { return individual.fitness / totalFitness; }) : Array(population.length).fill(null).map(function () { return 1 / population.length; }); var wheel = relativeFitnesses.reduce(function (probabilities, fitness, index) { index === 0 ? probabilities.push(fitness) : probabilities.push(probabilities[index - 1] + fitness); return probabilities; }, []); return wheel; } function _getParentByRouletteWheel(wheel, population) { var chance = Math.random(); var index = _modifiedBinarySearch(wheel, chance); return population[index]; } function _modifiedBinarySearch(array, target) { var l = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; var r = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : array.length - 1; if (l > r) { return -1; } var m = Math.floor((l + r) / 2); if (m !== 0 && array[m - 1] < target && target <= array[m] || m === 0 && target <= array[m]) { return m; } else if (m === 0 && target <= array[m]) { return m; } else if (array[m] < target) { return _modifiedBinarySearch(array, target, m + 1, r); } else if (array[m] > target) { return _modifiedBinarySearch(array, target, l, m - 1); } else { return -1; } } function stochasticUniversalSampling(population, num) { var wheel = _makeWheel(population); // Since the wheel is normalized to [0..1], // we simply get the pointer the locations by slicing 1 // with the number of parents to keep var pointerDistance = 1 / num; var start = Math.random() * pointerDistance; var pointers = Array(num).fill(null).map(function (_, i) { return start + i * pointerDistance; }); var parentIndices = pointers.map(function (pointer) { return _modifiedBinarySearch(wheel, pointer); }); return parentIndices.map(function (index) { return population[index]; }); }