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