118 lines
4.3 KiB
Python
118 lines
4.3 KiB
Python
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,
|
||
"min_fitness_avg": 0.015, # критерий остановки
|
||
# при включенном сохранении графиков на время смотреть бессмысленно
|
||
# "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['min_fitness_avg']}")
|
||
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()
|