Поиск минимума
This commit is contained in:
@@ -27,9 +27,10 @@ BASE_CONFIG = {
|
|||||||
"precision_digits": 3,
|
"precision_digits": 3,
|
||||||
"max_generations": 200,
|
"max_generations": 200,
|
||||||
"seed": 17,
|
"seed": 17,
|
||||||
"min_fitness_avg": 0.015, # критерий остановки
|
"minimize": True,
|
||||||
|
"fitness_avg_threshold": -0.048, # критерий остановки
|
||||||
# при включенном сохранении графиков на время смотреть бессмысленно
|
# при включенном сохранении графиков на время смотреть бессмысленно
|
||||||
# "save_generations": [0, 50, 199],
|
"save_generations": [0, 50, 199],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -83,7 +84,9 @@ def main():
|
|||||||
print(f"Размеры популяции: {POPULATION_SIZES}")
|
print(f"Размеры популяции: {POPULATION_SIZES}")
|
||||||
print(f"Значения Pc: {PC_VALUES}")
|
print(f"Значения Pc: {PC_VALUES}")
|
||||||
print(f"Значения Pm: {PM_VALUES}")
|
print(f"Значения Pm: {PM_VALUES}")
|
||||||
print(f"Критерий остановки: среднее значение > {BASE_CONFIG['min_fitness_avg']}")
|
print(
|
||||||
|
f"Критерий остановки: среднее значение > {BASE_CONFIG['fitness_avg_threshold']}"
|
||||||
|
)
|
||||||
print("=" * 60)
|
print("=" * 60)
|
||||||
|
|
||||||
# Создаем базовую папку
|
# Создаем базовую папку
|
||||||
|
|||||||
32
lab1/gen.py
32
lab1/gen.py
@@ -137,6 +137,7 @@ class GARunConfig:
|
|||||||
pm: float # вероятность мутации
|
pm: float # вероятность мутации
|
||||||
max_generations: int # максимальное количество поколений
|
max_generations: int # максимальное количество поколений
|
||||||
seed: int | None = None # seed для генератора случайных чисел
|
seed: int | None = None # seed для генератора случайных чисел
|
||||||
|
minimize: bool = False # если True, ищем минимум вместо максимума
|
||||||
save_generations: list[int] | None = (
|
save_generations: list[int] | None = (
|
||||||
None # индексы поколений для сохранения графиков
|
None # индексы поколений для сохранения графиков
|
||||||
)
|
)
|
||||||
@@ -144,7 +145,7 @@ class GARunConfig:
|
|||||||
variance_threshold: float | None = (
|
variance_threshold: float | None = (
|
||||||
None # порог дисперсии для остановки (если None - не используется)
|
None # порог дисперсии для остановки (если None - не используется)
|
||||||
)
|
)
|
||||||
min_fitness_avg: float | None = (
|
fitness_avg_threshold: float | None = (
|
||||||
None # порог среднего значения фитнес функции для остановки
|
None # порог среднего значения фитнес функции для остановки
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -177,7 +178,7 @@ def genetic_algorithm(config: GARunConfig) -> GARunResult:
|
|||||||
start = time.perf_counter()
|
start = time.perf_counter()
|
||||||
history_best_x, history_best_f = [], []
|
history_best_x, history_best_f = [], []
|
||||||
history_populations_x, history_populations_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):
|
for generation in range(config.max_generations):
|
||||||
xs, fits = eval_population(
|
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]
|
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
|
best_x, best_f = gen_best_x, gen_best_f
|
||||||
|
|
||||||
history_best_x.append(gen_best_x)
|
history_best_x.append(gen_best_x)
|
||||||
@@ -208,11 +211,14 @@ def genetic_algorithm(config: GARunConfig) -> GARunResult:
|
|||||||
stop_algorithm = True
|
stop_algorithm = True
|
||||||
|
|
||||||
# Критерий остановки по среднему значению фитнес функции
|
# Критерий остановки по среднему значению фитнес функции
|
||||||
if config.min_fitness_avg is not None:
|
if config.fitness_avg_threshold is not None:
|
||||||
mean_fitness = np.mean(fits)
|
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(
|
print(
|
||||||
f"Остановка на поколении {generation}: среднее значение {mean_fitness:.6f} > {config.min_fitness_avg}"
|
f"Остановка на поколении {generation}: среднее значение {mean_fitness:.6f} {comparator} {config.fitness_avg_threshold}"
|
||||||
)
|
)
|
||||||
stop_algorithm = True
|
stop_algorithm = True
|
||||||
|
|
||||||
@@ -229,6 +235,7 @@ def genetic_algorithm(config: GARunConfig) -> GARunResult:
|
|||||||
config.x_max,
|
config.x_max,
|
||||||
config.results_dir,
|
config.results_dir,
|
||||||
config.fitness_func,
|
config.fitness_func,
|
||||||
|
minimize=config.minimize,
|
||||||
)
|
)
|
||||||
break
|
break
|
||||||
|
|
||||||
@@ -244,10 +251,12 @@ def genetic_algorithm(config: GARunConfig) -> GARunResult:
|
|||||||
config.x_max,
|
config.x_max,
|
||||||
config.results_dir,
|
config.results_dir,
|
||||||
config.fitness_func,
|
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)
|
next_population = crossover(parents, config.pc)
|
||||||
@@ -283,6 +292,7 @@ def plot_generation_snapshot(
|
|||||||
x_max: float,
|
x_max: float,
|
||||||
results_dir: str,
|
results_dir: str,
|
||||||
fitness_func: Callable[[float], float],
|
fitness_func: Callable[[float], float],
|
||||||
|
minimize: bool = False,
|
||||||
) -> str:
|
) -> 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(
|
plt.scatter(
|
||||||
[current_pop_x[best_idx]],
|
[current_pop_x[best_idx]],
|
||||||
[current_pop_f[best_idx]],
|
[current_pop_f[best_idx]],
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ config = GARunConfig(
|
|||||||
pm=0.01,
|
pm=0.01,
|
||||||
max_generations=200,
|
max_generations=200,
|
||||||
seed=17,
|
seed=17,
|
||||||
|
minimize=True,
|
||||||
save_generations=[
|
save_generations=[
|
||||||
0,
|
0,
|
||||||
1,
|
1,
|
||||||
@@ -34,7 +35,7 @@ config = GARunConfig(
|
|||||||
], # поколения для сохранения графиков
|
], # поколения для сохранения графиков
|
||||||
results_dir="results",
|
results_dir="results",
|
||||||
# variance_threshold=1e-6, # порог дисперсии для остановки
|
# variance_threshold=1e-6, # порог дисперсии для остановки
|
||||||
min_fitness_avg=0.015, # порог среднего значения для остановки
|
fitness_avg_threshold=-0.048, # порог среднего значения для остановки
|
||||||
)
|
)
|
||||||
|
|
||||||
# Запускаем генетический алгоритм
|
# Запускаем генетический алгоритм
|
||||||
|
|||||||
Reference in New Issue
Block a user