Цвета в табличках, остановка по лучшему решению

This commit is contained in:
2025-10-09 13:15:09 +03:00
parent 745cfea282
commit ee79d6ad41
3 changed files with 157 additions and 27 deletions

View File

@@ -19,6 +19,7 @@ BASE_DIR = "experiments"
POPULATION_SIZES = [10, 25, 50, 100]
PC_VALUES = [0.3, 0.4, 0.5, 0.6, 0.7, 0.8] # вероятности кроссинговера
PM_VALUES = [0.001, 0.01, 0.05, 0.1, 0.2] # вероятности мутации
SAVE_AVG_BEST_FITNESS = True
# Количество запусков для усреднения результатов
NUM_RUNS = 1
@@ -31,7 +32,9 @@ BASE_CONFIG = {
"max_generations": 200,
"seed": None, # None для случайности, т. к. всё усредняем
"minimize": True,
"fitness_avg_threshold": 0.05, # критерий остановки
# "fitness_avg_threshold": 0.05, # критерий остановки
# "max_best_repetitions": 10,
"best_value_threshold": 0.005,
# при включенном сохранении графиков на время смотреть бессмысленно
# "save_generations": [1, 50, 199],
}
@@ -39,13 +42,15 @@ BASE_CONFIG = {
def run_single_experiment(
pop_size: int, pc: float, pm: float
) -> tuple[float, float, float, float]:
) -> tuple[float, float, float, float, float, float]:
"""
Запускает несколько экспериментов с заданными параметрами и усредняет результаты.
Возвращает (среднееремя_в_мс, стд_отклонениеремени, среднее_поколений, стд_отклонение_поколений).
Возвращает (среднееремя_в_мс, стд_отклонениеремени, среднее_поколений,
стд_отклонение_поколений, среднееучшее_значение_фитнеса, стд_отклонениеучшего_значения_фитнеса).
"""
times = []
generations = []
best_fitnesses = []
for run_num in range(NUM_RUNS):
config = GARunConfig(
@@ -65,14 +70,26 @@ def run_single_experiment(
result = genetic_algorithm(config)
times.append(result.time_ms)
generations.append(result.generations_count)
best_fitnesses.append(result.best_generation.best_fitness)
# Вычисляем средние значения и стандартные отклонения
avg_time = statistics.mean(times)
std_time = statistics.stdev(times) if len(times) > 1 else 0.0
avg_generations = statistics.mean(generations)
std_generations = statistics.stdev(generations) if len(generations) > 1 else 0.0
avg_best_fitness = statistics.mean(best_fitnesses)
std_best_fitness = (
statistics.stdev(best_fitnesses) if len(best_fitnesses) > 1 else 0.0
)
return avg_time, std_time, avg_generations, std_generations
return (
avg_time,
std_time,
avg_generations,
std_generations,
avg_best_fitness,
std_best_fitness,
)
def run_experiments_for_population(pop_size: int) -> PrettyTable:
@@ -92,14 +109,22 @@ def run_experiments_for_population(pop_size: int) -> PrettyTable:
row = [f"{pc:.1f}"]
for pm in PM_VALUES:
print(f" Эксперимент: pop_size={pop_size}, Pc={pc:.1f}, Pm={pm:.3f}")
avg_time, std_time, avg_generations, std_generations = (
run_single_experiment(pop_size, pc, pm)
)
(
avg_time,
std_time,
avg_generations,
std_generations,
avg_best_fitness,
std_best_fitness,
) = run_single_experiment(pop_size, pc, pm)
# Форматируем результат: среднееремя±стд_отклонение (среднее_поколения±стд_отклонение)
# cell_value = f"{avg_time:.1f}±{std_time:.1f} ({avg_generations:.1f}±{std_generations:.1f})"
cell_value = f"{avg_time:.1f} ({avg_generations:.0f})"
if SAVE_AVG_BEST_FITNESS:
cell_value += f" {avg_best_fitness:.5f}"
if avg_generations == BASE_CONFIG["max_generations"]:
cell_value = ""
@@ -118,9 +143,6 @@ def main():
print(f"Значения Pc: {PC_VALUES}")
print(f"Значения Pm: {PM_VALUES}")
print(f"Количество запусков для усреднения: {NUM_RUNS}")
print(
f"Критерий остановки: среднее значение > {BASE_CONFIG['fitness_avg_threshold']}"
)
print("=" * 60)
# Создаем базовую папку