29 lines
1.2 KiB
Python
29 lines
1.2 KiB
Python
import numpy as np
|
||
|
||
from .types import Fitnesses, Population
|
||
|
||
|
||
def roulette_selection(population: Population, fitnesses: Fitnesses) -> Population:
|
||
"""Селекция методом рулетки.
|
||
|
||
Чем больше значение фитнеса, тем больше вероятность выбора особи. Для минимизации
|
||
значения фитнеса нужно предварительно инвертировать.
|
||
"""
|
||
# Чтобы работать с отрицательными f, сдвигаем значения фитнес функции на минимальное
|
||
# значение в популяции. Вычитаем min_fit, т. к. min_fit может быть отрицательным.
|
||
min_fit = np.min(fitnesses)
|
||
shifted_fitnesses = fitnesses - min_fit + 1e-12
|
||
|
||
# Получаем вероятности для каждой особи
|
||
probs = shifted_fitnesses / np.sum(shifted_fitnesses)
|
||
cum = np.cumsum(probs)
|
||
|
||
# Выбираем особей методом рулетки
|
||
selected = []
|
||
for _ in population:
|
||
r = np.random.random()
|
||
idx = int(np.searchsorted(cum, r, side="left"))
|
||
selected.append(population[idx])
|
||
|
||
return selected
|