Поиск минимума
This commit is contained in:
32
lab1/gen.py
32
lab1/gen.py
@@ -137,6 +137,7 @@ class GARunConfig:
|
||||
pm: float # вероятность мутации
|
||||
max_generations: int # максимальное количество поколений
|
||||
seed: int | None = None # seed для генератора случайных чисел
|
||||
minimize: bool = False # если True, ищем минимум вместо максимума
|
||||
save_generations: list[int] | None = (
|
||||
None # индексы поколений для сохранения графиков
|
||||
)
|
||||
@@ -144,7 +145,7 @@ class GARunConfig:
|
||||
variance_threshold: float | None = (
|
||||
None # порог дисперсии для остановки (если None - не используется)
|
||||
)
|
||||
min_fitness_avg: float | None = (
|
||||
fitness_avg_threshold: float | None = (
|
||||
None # порог среднего значения фитнес функции для остановки
|
||||
)
|
||||
|
||||
@@ -177,7 +178,7 @@ def genetic_algorithm(config: GARunConfig) -> GARunResult:
|
||||
start = time.perf_counter()
|
||||
history_best_x, history_best_f = [], []
|
||||
history_populations_x, history_populations_f = [], []
|
||||
best_x, best_f = 0, -float("inf")
|
||||
best_x, best_f = 0, (float("inf") if config.minimize else -float("inf"))
|
||||
|
||||
for generation in range(config.max_generations):
|
||||
xs, fits = eval_population(
|
||||
@@ -185,9 +186,11 @@ def genetic_algorithm(config: GARunConfig) -> GARunResult:
|
||||
)
|
||||
|
||||
# лучший в поколении + глобально лучший
|
||||
gi = int(np.argmax(fits))
|
||||
gi = int(np.argmin(fits)) if config.minimize else int(np.argmax(fits))
|
||||
gen_best_x, gen_best_f = xs[gi], fits[gi]
|
||||
if gen_best_f > best_f:
|
||||
if (config.minimize and gen_best_f < best_f) or (
|
||||
not config.minimize and gen_best_f > best_f
|
||||
):
|
||||
best_x, best_f = gen_best_x, gen_best_f
|
||||
|
||||
history_best_x.append(gen_best_x)
|
||||
@@ -208,11 +211,14 @@ def genetic_algorithm(config: GARunConfig) -> GARunResult:
|
||||
stop_algorithm = True
|
||||
|
||||
# Критерий остановки по среднему значению фитнес функции
|
||||
if config.min_fitness_avg is not None:
|
||||
if config.fitness_avg_threshold is not None:
|
||||
mean_fitness = np.mean(fits)
|
||||
if mean_fitness > config.min_fitness_avg:
|
||||
if (config.minimize and mean_fitness < config.fitness_avg_threshold) or (
|
||||
not config.minimize and mean_fitness > config.fitness_avg_threshold
|
||||
):
|
||||
comparator = "<" if config.minimize else ">"
|
||||
print(
|
||||
f"Остановка на поколении {generation}: среднее значение {mean_fitness:.6f} > {config.min_fitness_avg}"
|
||||
f"Остановка на поколении {generation}: среднее значение {mean_fitness:.6f} {comparator} {config.fitness_avg_threshold}"
|
||||
)
|
||||
stop_algorithm = True
|
||||
|
||||
@@ -229,6 +235,7 @@ def genetic_algorithm(config: GARunConfig) -> GARunResult:
|
||||
config.x_max,
|
||||
config.results_dir,
|
||||
config.fitness_func,
|
||||
minimize=config.minimize,
|
||||
)
|
||||
break
|
||||
|
||||
@@ -244,10 +251,12 @@ def genetic_algorithm(config: GARunConfig) -> GARunResult:
|
||||
config.x_max,
|
||||
config.results_dir,
|
||||
config.fitness_func,
|
||||
minimize=config.minimize,
|
||||
)
|
||||
|
||||
# селекция
|
||||
parents = reproduction(population, fits)
|
||||
# селекция (для минимума инвертируем знак, чтобы минимальные значения становились максимальными)
|
||||
fitnesses_for_selection = fits if not config.minimize else [-f for f in fits]
|
||||
parents = reproduction(population, fitnesses_for_selection)
|
||||
|
||||
# кроссинговер попарно
|
||||
next_population = crossover(parents, config.pc)
|
||||
@@ -283,6 +292,7 @@ def plot_generation_snapshot(
|
||||
x_max: float,
|
||||
results_dir: str,
|
||||
fitness_func: Callable[[float], float],
|
||||
minimize: bool = False,
|
||||
) -> str:
|
||||
"""
|
||||
График для конкретного поколения с отображением всей популяции.
|
||||
@@ -311,7 +321,9 @@ def plot_generation_snapshot(
|
||||
)
|
||||
|
||||
# Лучшая особь красной точкой
|
||||
best_idx = np.argmax(current_pop_f)
|
||||
best_idx = (
|
||||
int(np.argmin(current_pop_f)) if minimize else int(np.argmax(current_pop_f))
|
||||
)
|
||||
plt.scatter(
|
||||
[current_pop_x[best_idx]],
|
||||
[current_pop_f[best_idx]],
|
||||
|
||||
Reference in New Issue
Block a user