@adrianperea/genie.js
Version:
A highly flexible, data-agnostic, and UI-independent Genetic Algorithm Library
89 lines (73 loc) • 2.77 kB
JavaScript
;
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];
});
}