Усреднил значения
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import math
|
||||
import os
|
||||
import shutil
|
||||
import statistics
|
||||
|
||||
from gen import GARunConfig, genetic_algorithm
|
||||
from prettytable import PrettyTable
|
||||
@@ -19,6 +20,9 @@ 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] # вероятности мутации
|
||||
|
||||
# Количество запусков для усреднения результатов
|
||||
NUM_RUNS = 30
|
||||
|
||||
# Базовые параметры (как в main.py)
|
||||
BASE_CONFIG = {
|
||||
"x_min": 3.1,
|
||||
@@ -26,7 +30,7 @@ BASE_CONFIG = {
|
||||
"fitness_func": target_function,
|
||||
"precision_digits": 3,
|
||||
"max_generations": 200,
|
||||
"seed": 17,
|
||||
"seed": None, # None для случайности, т. к. всё усредняем
|
||||
"minimize": True,
|
||||
"fitness_avg_threshold": -0.049, # критерий остановки
|
||||
# при включенном сохранении графиков на время смотреть бессмысленно
|
||||
@@ -34,23 +38,42 @@ BASE_CONFIG = {
|
||||
}
|
||||
|
||||
|
||||
def run_single_experiment(pop_size: int, pc: float, pm: float) -> tuple[float, int]:
|
||||
def run_single_experiment(
|
||||
pop_size: int, pc: float, pm: float
|
||||
) -> tuple[float, float, float, float]:
|
||||
"""
|
||||
Запускает один эксперимент с заданными параметрами.
|
||||
Возвращает (время_в_мс, номер_поколения).
|
||||
Запускает несколько экспериментов с заданными параметрами и усредняет результаты.
|
||||
Возвращает (среднее_время_в_мс, стд_отклонение_времени, среднее_поколений, стд_отклонение_поколений).
|
||||
"""
|
||||
config = GARunConfig(
|
||||
**BASE_CONFIG,
|
||||
pop_size=pop_size,
|
||||
pc=pc,
|
||||
pm=pm,
|
||||
results_dir=os.path.join(
|
||||
BASE_DIR, str(pop_size), f"pc_{pc:.3f}", f"pm_{pm:.3f}"
|
||||
),
|
||||
)
|
||||
times = []
|
||||
generations = []
|
||||
|
||||
result = genetic_algorithm(config)
|
||||
return result.time_ms, result.generations
|
||||
for run_num in range(NUM_RUNS):
|
||||
config = GARunConfig(
|
||||
**BASE_CONFIG,
|
||||
pop_size=pop_size,
|
||||
pc=pc,
|
||||
pm=pm,
|
||||
results_dir=os.path.join(
|
||||
BASE_DIR,
|
||||
str(pop_size),
|
||||
f"pc_{pc:.3f}",
|
||||
f"pm_{pm:.3f}",
|
||||
f"run_{run_num}",
|
||||
),
|
||||
)
|
||||
|
||||
result = genetic_algorithm(config)
|
||||
times.append(result.time_ms)
|
||||
generations.append(result.generations)
|
||||
|
||||
# Вычисляем средние значения и стандартные отклонения
|
||||
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
|
||||
|
||||
return avg_time, std_time, avg_generations, std_generations
|
||||
|
||||
|
||||
def run_experiments_for_population(pop_size: int) -> PrettyTable:
|
||||
@@ -59,6 +82,7 @@ def run_experiments_for_population(pop_size: int) -> PrettyTable:
|
||||
Возвращает таблицу результатов.
|
||||
"""
|
||||
print(f"\nЗапуск экспериментов для популяции размером {pop_size}...")
|
||||
print(f"Количество запусков для усреднения: {NUM_RUNS}")
|
||||
|
||||
# Создаем таблицу
|
||||
table = PrettyTable()
|
||||
@@ -69,9 +93,13 @@ 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}")
|
||||
time_ms, generations = run_single_experiment(pop_size, pc, pm)
|
||||
# Форматируем результат: время(поколение)
|
||||
cell_value = f"{time_ms:.1f} ({generations})"
|
||||
avg_time, std_time, avg_generations, std_generations = (
|
||||
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})"
|
||||
row.append(cell_value)
|
||||
table.add_row(row)
|
||||
|
||||
@@ -86,6 +114,7 @@ def main():
|
||||
print(f"Размеры популяции: {POPULATION_SIZES}")
|
||||
print(f"Значения Pc: {PC_VALUES}")
|
||||
print(f"Значения Pm: {PM_VALUES}")
|
||||
print(f"Количество запусков для усреднения: {NUM_RUNS}")
|
||||
print(
|
||||
f"Критерий остановки: среднее значение > {BASE_CONFIG['fitness_avg_threshold']}"
|
||||
)
|
||||
@@ -103,7 +132,10 @@ def main():
|
||||
print(f"\n{'='*60}")
|
||||
print(f"РЕЗУЛЬТАТЫ ДЛЯ ПОПУЛЯЦИИ РАЗМЕРОМ {pop_size}")
|
||||
print(f"{'='*60}")
|
||||
print("Формат: время_в_мс (номер_поколения)")
|
||||
print(
|
||||
f"Формат: среднее_время±стд_отклонение_мс (среднее_поколения±стд_отклонение)"
|
||||
)
|
||||
print(f"Усреднено по {NUM_RUNS} запускам")
|
||||
print(table)
|
||||
|
||||
pop_exp_dir = os.path.join(BASE_DIR, str(pop_size))
|
||||
|
||||
@@ -205,9 +205,6 @@ def genetic_algorithm(config: GARunConfig) -> GARunResult:
|
||||
if config.variance_threshold is not None:
|
||||
fitness_variance = np.var(fits)
|
||||
if fitness_variance < config.variance_threshold:
|
||||
print(
|
||||
f"Остановка на поколении {generation}: дисперсия {fitness_variance:.6f} < {config.variance_threshold}"
|
||||
)
|
||||
stop_algorithm = True
|
||||
|
||||
# Критерий остановки по среднему значению фитнес функции
|
||||
@@ -216,10 +213,6 @@ def genetic_algorithm(config: GARunConfig) -> GARunResult:
|
||||
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} {comparator} {config.fitness_avg_threshold}"
|
||||
)
|
||||
stop_algorithm = True
|
||||
|
||||
# Сохраняем график последнего поколения при досрочной остановке
|
||||
|
||||
@@ -440,78 +440,80 @@
|
||||
\item $p_c = 0.3, 0.4, 0.5, 0.6, 0.7, 0.8$ -- вероятность кроссинговера.
|
||||
\item $p_m = 0.001, 0.01, 0.05, 0.1, 0.2$ -- вероятность мутации.
|
||||
\end{itemize}
|
||||
|
||||
Результаты измерений представлены в таблицах \ref{tab:pc_pm_results}--\ref{tab:pc_pm_results4}. В ячейках указано усредненное время в миллисекундах нахождения минимума функции. В скобках указано усредненное количество поколений, за которое было найдено решение. Каждый эксперимент запускался 30 раз. Если в ячейке стоит прочерк, то это означает, что решение не было найдено за 200 поколений. Лучшее значение по времени выполнения для каждого размера популяции выделено жирным шрифтом.
|
||||
|
||||
\newcolumntype{Y}{>{\centering\arraybackslash}X}
|
||||
|
||||
\begin{table}[ht]
|
||||
\begin{table}[h!]
|
||||
\centering
|
||||
\small
|
||||
\begin{tabularx}{\linewidth}{l *{5}{Y}}
|
||||
\toprule
|
||||
$\mathbf{P_c \;\backslash\; P_m}$ & \textbf{0.001} & \textbf{0.010} & \textbf{0.050} & \textbf{0.100} & \textbf{0.200} \\
|
||||
\midrule
|
||||
\textbf{0.3} & -- & 6.8 (83) & 4.7 (57) & 3.4 (37) & 2.3 (29) \\
|
||||
\textbf{0.4} & -- & 3.7 (48) & 3.6 (24) & 5.2 (64) & 2.3 (17) \\
|
||||
\textbf{0.5} & -- & -- & 6.2 (86) & 2.5 (27) & 2.8 (34) \\
|
||||
\textbf{0.6} & -- & 12.6 (163)& 5.7 (56) & 2.7 (34) & 2.1 (25) \\
|
||||
\textbf{0.7} & -- & -- & 7.9 (103) & 2.4 (23) & 2.3 (25) \\
|
||||
\textbf{0.8} & -- & 11.8 (159)& 2.9 (23) & 2.0 (23) & 1.3 (13) \\
|
||||
\textbf{0.3} & 11.5 (167) & 8.4 (123) & 5.4 (78) & 4.9 (71) & 3.3 (48) \\
|
||||
\textbf{0.4} & 10.1 (144) & 7.1 (104) & 6.3 (92) & 4.7 (67) & 4.7 (67) \\
|
||||
\textbf{0.5} & 11.4 (168) & 7.7 (112) & 5.4 (79) & 6.1 (83) & \textbf{3.1 (44)} \\
|
||||
\textbf{0.6} & 11.0 (160) & 6.7 (97) & 4.9 (70) & 4.7 (67) & 5.3 (74) \\
|
||||
\textbf{0.7} & 12.1 (174) & 9.3 (135) & 3.7 (52) & 4.7 (67) & 6.5 (92) \\
|
||||
\textbf{0.8} & 8.7 (126) & 8.3 (119) & 3.9 (57) & 7.9 (113)& 4.4 (61) \\
|
||||
\bottomrule
|
||||
\end{tabularx}
|
||||
\caption{Результаты для $N = 10$}
|
||||
\label{tab:pc_pm_results}
|
||||
\end{table}
|
||||
|
||||
\begin{table}[ht]
|
||||
\begin{table}[h!]
|
||||
\centering
|
||||
\small
|
||||
\begin{tabularx}{\linewidth}{l *{5}{Y}}
|
||||
\toprule
|
||||
$\mathbf{P_c \;\backslash\; P_m}$ & \textbf{0.001} & \textbf{0.010} & \textbf{0.050} & \textbf{0.100} & \textbf{0.200} \\
|
||||
\midrule
|
||||
\textbf{0.3} & 20.6 (146) & 13.5 (90) & 6.5 (43) & 5.3 (29) & 7.1 (48) \\
|
||||
\textbf{0.4} & 2.7 (13) & 6.7 (38) & 3.4 (20) & 3.0 (20) & 19.2 (122) \\
|
||||
\textbf{0.5} & -- & 3.0 (15) & 2.5 (16) & 3.7 (20) & -- \\
|
||||
\textbf{0.6} & 1.8 (11) & 14.3 (102)& 2.3 (13) & 2.4 (14) & -- \\
|
||||
\textbf{0.7} & 2.1 (12) & 3.3 (17) & 6.4 (36) & 2.5 (15) & 9.1 (60) \\
|
||||
\textbf{0.8} & -- & 2.6 (12) & 3.8 (22) & 3.7 (24) & 6.8 (47) \\
|
||||
\textbf{0.3} & 14.7 (111) & 8.2 (62) & 4.9 (37) & 4.7 (35) & 8.7 (63) \\
|
||||
\textbf{0.4} & 12.8 (95) & 7.3 (54) & 4.7 (35) & 4.3 (32) & 8.2 (61) \\
|
||||
\textbf{0.5} & 10.5 (78) & 5.4 (40) & \textbf{2.2 (16)} & 5.5 (40) & 12.1 (89) \\
|
||||
\textbf{0.6} & 14.0 (103) & 6.5 (48) & 3.4 (25) & 4.0 (30) & 14.0 (87) \\
|
||||
\textbf{0.7} & 11.5 (84) & 6.2 (46) & 3.0 (22) & 3.2 (24) & 11.6 (83) \\
|
||||
\textbf{0.8} & 9.2 (64) & 5.8 (41) & 2.5 (18) & 3.0 (22) & 11.2 (78) \\
|
||||
\bottomrule
|
||||
\end{tabularx}
|
||||
\caption{Результаты для $N = 25$}
|
||||
\label{tab:pc_pm_results2}
|
||||
\end{table}
|
||||
|
||||
\begin{table}[ht]
|
||||
\begin{table}[h!]
|
||||
\centering
|
||||
\small
|
||||
\begin{tabularx}{\linewidth}{l *{5}{Y}}
|
||||
\toprule
|
||||
$\mathbf{P_c \;\backslash\; P_m}$ & \textbf{0.001} & \textbf{0.010} & \textbf{0.050} & \textbf{0.100} & \textbf{0.200} \\
|
||||
\midrule
|
||||
\textbf{0.3} & 25.8 (101) & 6.3 (24) & 9.5 (30) & 7.2 (27) & -- \\
|
||||
\textbf{0.4} & 4.8 (18) & 4.6 (16) & 21.4 (86) & 42.5 (167)& 43.2 (175) \\
|
||||
\textbf{0.5} & 23.6 (95) & 21.3 (82) & 8.5 (34) & 6.4 (23) & 20.0 (76) \\
|
||||
\textbf{0.6} & 5.5 (20) & 10.9 (41) & 12.8 (43) & -- & 28.6 (113) \\
|
||||
\textbf{0.7} & -- & 7.4 (28) & 8.8 (35) & -- & -- \\
|
||||
\textbf{0.8} & -- & 11.7 (47) & 9.1 (36) & -- & -- \\
|
||||
\textbf{0.3} & 6.1 (26) & 5.2 (22) & 6.3 (26) & 11.6 (48) & 40.2 (147) \\
|
||||
\textbf{0.4} & 6.1 (26) & 4.5 (19) & 5.2 (22) & 9.8 (40) & 37.2 (149) \\
|
||||
\textbf{0.5} & 10.5 (44) & 4.9 (20) & 7.6 (28) & 17.1 (65) & 36.2 (144) \\
|
||||
\textbf{0.6} & 7.5 (31) & \textbf{4.6 (19)} & 5.6 (23) & 18.8 (76) & 42.0 (158) \\
|
||||
\textbf{0.7} & 7.6 (31) & 4.7 (20) & 7.6 (31) & 13.9 (55) & 34.3 (136) \\
|
||||
\textbf{0.8} & 10.8 (44) & 5.0 (21) & 6.1 (24) & 13.9 (56) & 36.5 (145) \\
|
||||
\bottomrule
|
||||
\end{tabularx}
|
||||
\caption{Результаты для $N = 50$}
|
||||
\label{tab:pc_pm_results3}
|
||||
\end{table}
|
||||
|
||||
\begin{table}[ht]
|
||||
\begin{table}[h!]
|
||||
\centering
|
||||
\small
|
||||
\begin{tabularx}{\linewidth}{l *{5}{Y}}
|
||||
\toprule
|
||||
$\mathbf{P_c \;\backslash\; P_m}$ & \textbf{0.001} & \textbf{0.010} & \textbf{0.050} & \textbf{0.100} & \textbf{0.200} \\
|
||||
\midrule
|
||||
\textbf{0.3} & 7.6 (16) & 9.5 (16) & 10.6 (23) & 18.0 (38) & -- \\
|
||||
\textbf{0.4} & 6.1 (13) & 10.0 (21) & 12.5 (25) & 67.1 (143) & -- \\
|
||||
\textbf{0.5} & 7.4 (15) & 7.9 (16) & 9.5 (20) & 79.7 (166) & -- \\
|
||||
\textbf{0.6} & 7.5 (16) & 10.1 (21) & -- & 51.1 (107) & -- \\
|
||||
\textbf{0.7} & 7.6 (16) & 28.6 (56) & 22.7 (48) & 43.7 (91) & -- \\
|
||||
\textbf{0.8} & 6.7 (14) & 10.4 (22) & 13.4 (25) & 23.0 (47) & -- \\
|
||||
\textbf{0.3} & \textbf{7.6 (16)} & 9.5 (21) & 29.0 (60) & 62.9 (128) & -- \\
|
||||
\textbf{0.4} & 8.0 (17) & 9.6 (21) & 31.5 (68) & 56.6 (120) & -- \\
|
||||
\textbf{0.5} & 9.1 (20) & 9.2 (20) & 22.6 (48) & 59.4 (124) & -- \\
|
||||
\textbf{0.6} & 17.8 (38) & 12.3 (26) & 30.0 (64) & 61.1 (128) & 95.3 (196) \\
|
||||
\textbf{0.7} & 10.0 (22) & 14.3 (31) & 30.3 (64) & 49.1 (103) & -- \\
|
||||
\textbf{0.8} & 16.4 (34) & 12.1 (25) & 31.4 (64) & 54.9 (114) & -- \\
|
||||
\bottomrule
|
||||
\end{tabularx}
|
||||
\caption{Результаты для $N = 100$}
|
||||
|
||||
Reference in New Issue
Block a user