Document visualization workflow for lab 5 report
This commit is contained in:
129
lab5/experiments.py
Normal file
129
lab5/experiments.py
Normal file
@@ -0,0 +1,129 @@
|
||||
"""Parameter sweep experiments for the evolution strategy."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import statistics
|
||||
from pathlib import Path
|
||||
from typing import Iterable
|
||||
|
||||
import numpy as np
|
||||
from prettytable import PrettyTable
|
||||
|
||||
from es import EvolutionStrategyConfig, run_evolution_strategy
|
||||
from functions import axis_parallel_hyperellipsoid, default_bounds
|
||||
|
||||
POPULATION_SIZES = [5, 10, 20, 40]
|
||||
MUTATION_PROBABILITIES = [0.3, 0.5, 0.7, 0.9, 1.0]
|
||||
NUM_RUNS = 5
|
||||
LAMBDA_FACTOR = 5
|
||||
RESULTS_DIR = Path("lab5_experiments")
|
||||
|
||||
|
||||
def build_config(dimension: int, mu: int, mutation_probability: float) -> EvolutionStrategyConfig:
|
||||
x_min, x_max = default_bounds(dimension)
|
||||
search_range = x_max - x_min
|
||||
initial_sigma = np.full(dimension, 0.15 * search_range[0], dtype=np.float64)
|
||||
return EvolutionStrategyConfig(
|
||||
fitness_func=axis_parallel_hyperellipsoid,
|
||||
dimension=dimension,
|
||||
x_min=x_min,
|
||||
x_max=x_max,
|
||||
mu=mu,
|
||||
lambda_=mu * LAMBDA_FACTOR,
|
||||
mutation_probability=mutation_probability,
|
||||
initial_sigma=initial_sigma,
|
||||
max_generations=300,
|
||||
selection="comma",
|
||||
recombination="intermediate",
|
||||
parents_per_offspring=2,
|
||||
success_rule_window=5,
|
||||
success_rule_target=0.2,
|
||||
sigma_increase=1.22,
|
||||
sigma_decrease=0.82,
|
||||
sigma_scale_min=1e-3,
|
||||
sigma_scale_max=50.0,
|
||||
sigma_min=1e-5,
|
||||
sigma_max=2.0,
|
||||
best_value_threshold=1e-6,
|
||||
max_stagnation_generations=80,
|
||||
save_generations=None,
|
||||
results_dir=str(RESULTS_DIR / "tmp"),
|
||||
log_every_generation=False,
|
||||
seed=None,
|
||||
)
|
||||
|
||||
|
||||
def run_single_experiment(config: EvolutionStrategyConfig) -> tuple[float, int, float]:
|
||||
result = run_evolution_strategy(config)
|
||||
return result.time_ms, result.generations_count, result.best_generation.best.fitness
|
||||
|
||||
|
||||
def summarize(values: Iterable[float]) -> tuple[float, float]:
|
||||
values = list(values)
|
||||
if not values:
|
||||
return 0.0, 0.0
|
||||
if len(values) == 1:
|
||||
return values[0], 0.0
|
||||
return statistics.mean(values), statistics.stdev(values)
|
||||
|
||||
|
||||
def run_grid_for_dimension(dimension: int) -> PrettyTable:
|
||||
table = PrettyTable()
|
||||
table.field_names = ["mu \\ p_mut"] + [f"{pm:.2f}" for pm in MUTATION_PROBABILITIES]
|
||||
|
||||
for mu in POPULATION_SIZES:
|
||||
row = [str(mu)]
|
||||
for pm in MUTATION_PROBABILITIES:
|
||||
times: list[float] = []
|
||||
generations: list[int] = []
|
||||
best_values: list[float] = []
|
||||
|
||||
for run_idx in range(NUM_RUNS):
|
||||
config = build_config(dimension, mu, pm)
|
||||
# Для воспроизводимости меняем seed для каждого запуска
|
||||
config.seed = np.random.randint(0, 1_000_000)
|
||||
time_ms, gens, best = run_single_experiment(config)
|
||||
times.append(time_ms)
|
||||
generations.append(gens)
|
||||
best_values.append(best)
|
||||
|
||||
avg_time, std_time = summarize(times)
|
||||
avg_gen, std_gen = summarize(generations)
|
||||
avg_best, std_best = summarize(best_values)
|
||||
|
||||
cell = f"{avg_time:.1f}±{std_time:.1f} ({avg_gen:.0f}±{std_gen:.0f}) {avg_best:.4f}"
|
||||
row.append(cell)
|
||||
table.add_row(row)
|
||||
|
||||
return table
|
||||
|
||||
|
||||
def save_table(table: PrettyTable, path: Path) -> None:
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
with path.open("w", encoding="utf-8") as f:
|
||||
f.write(table.get_csv_string())
|
||||
|
||||
|
||||
def main() -> None:
|
||||
if RESULTS_DIR.exists():
|
||||
for child in RESULTS_DIR.iterdir():
|
||||
if child.is_file():
|
||||
child.unlink()
|
||||
|
||||
print("=" * 80)
|
||||
print("Исследование параметров эволюционной стратегии")
|
||||
print("Популяции:", POPULATION_SIZES)
|
||||
print("Вероятности мутации:", MUTATION_PROBABILITIES)
|
||||
print(f"Каждая конфигурация запускается {NUM_RUNS} раз")
|
||||
print("=" * 80)
|
||||
|
||||
for dimension in (2, 3):
|
||||
print(f"\nРезультаты для размерности n={dimension}")
|
||||
table = run_grid_for_dimension(dimension)
|
||||
print(table)
|
||||
save_table(table, RESULTS_DIR / f"dimension_{dimension}.csv")
|
||||
print(f"Таблица сохранена в {RESULTS_DIR / f'dimension_{dimension}.csv'}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user