Files
genetic-algorithms/lab1/expirements.py
2025-09-11 11:40:37 +03:00

121 lines
4.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import math
import os
import shutil
from gen import GARunConfig, genetic_algorithm
from prettytable import PrettyTable
def target_function(x: float) -> float:
"""f(x) = sin(x)/x^2"""
return math.sin(x) / (x * x)
# Базовая папка для экспериментов
BASE_DIR = "experiments"
# Параметры для экспериментов
POPULATION_SIZES = [10, 50, 100]
PC_VALUES = [0.5, 0.6, 0.7, 0.8, 0.9] # вероятности кроссинговера
PM_VALUES = [0.001, 0.01, 0.05, 0.1, 0.2] # вероятности мутации
# Базовые параметры (как в main.py)
BASE_CONFIG = {
"x_min": 3.1,
"x_max": 20.0,
"fitness_func": target_function,
"precision_digits": 3,
"max_generations": 200,
"seed": 17,
"minimize": True,
"fitness_avg_threshold": -0.048, # критерий остановки
# при включенном сохранении графиков на время смотреть бессмысленно
"save_generations": [0, 50, 199],
}
def run_single_experiment(pop_size: int, pc: float, pm: float) -> tuple[float, int]:
"""
Запускает один эксперимент с заданными параметрами.
Возвращает (время_в_мс, номер_поколения).
"""
config = GARunConfig(
**BASE_CONFIG,
pop_size=pop_size,
pc=pc,
pm=pm,
results_dir=f"{BASE_DIR}/{pop_size}/{pc:.3f}/{pm:.3f}",
)
result = genetic_algorithm(config)
return result.time_ms, result.generations
def run_experiments_for_population(pop_size: int) -> PrettyTable:
"""
Запускает эксперименты для одного размера популяции.
Возвращает таблицу результатов.
"""
print(f"\nЗапуск экспериментов для популяции размером {pop_size}...")
# Создаем таблицу
table = PrettyTable()
table.field_names = ["Pc \\ Pm"] + [f"{pm:.3f}" for pm in PM_VALUES]
# Запускаем эксперименты для всех комбинаций Pc и Pm
for pc in PC_VALUES:
row = [f"{pc:.1f}"]
for pm in PM_VALUES:
print(f" Эксперимент: pop_size={pop_size}, Pc={pc:.1f}, Pm={pm:.3f}")
time_ms, generations = run_single_experiment(pop_size, pc, pm)
# Форматируем результат: время(поколение)
cell_value = f"{time_ms:.1f} ({generations})"
row.append(cell_value)
table.add_row(row)
return table
def main():
"""Основная функция для запуска всех экспериментов."""
print("=" * 60)
print("ЗАПУСК ЭКСПЕРИМЕНТОВ ПО ПАРАМЕТРАМ ГЕНЕТИЧЕСКОГО АЛГОРИТМА")
print("=" * 60)
print(f"Размеры популяции: {POPULATION_SIZES}")
print(f"Значения Pc: {PC_VALUES}")
print(f"Значения Pm: {PM_VALUES}")
print(
f"Критерий остановки: среднее значение > {BASE_CONFIG['fitness_avg_threshold']}"
)
print("=" * 60)
# Создаем базовую папку
if os.path.exists(BASE_DIR):
shutil.rmtree(BASE_DIR)
os.makedirs(BASE_DIR)
# Запускаем эксперименты для каждого размера популяции
for pop_size in POPULATION_SIZES:
table = run_experiments_for_population(pop_size)
print(f"\n{'='*60}")
print(f"РЕЗУЛЬТАТЫ ДЛЯ ПОПУЛЯЦИИ РАЗМЕРОМ {pop_size}")
print(f"{'='*60}")
print("Формат: время_в_мсомер_поколения)")
print(table)
pop_exp_dir = os.path.join(BASE_DIR, str(pop_size))
os.makedirs(pop_exp_dir, exist_ok=True)
with open(os.path.join(pop_exp_dir, "results.csv"), "w", encoding="utf-8") as f:
f.write(table.get_csv_string())
print(f"Результаты сохранены в папке: {pop_exp_dir}/")
print(f"\n{'='*60}")
print("ВСЕ ЭКСПЕРИМЕНТЫ ЗАВЕРШЕНЫ!")
print(f"Результаты сохранены в папке: {BASE_DIR}/")
print(f"{'='*60}")
if __name__ == "__main__":
main()