From 1732a1dbb674efecca777d18f372d3ffacc3458d Mon Sep 17 00:00:00 2001 From: Arity-T Date: Thu, 11 Sep 2025 11:06:19 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A4=D0=B8=D1=82=D0=BD=D0=B5=D1=81=20=D1=84?= =?UTF-8?q?=D1=83=D0=BD=D0=BA=D1=86=D0=B8=D1=8F=20=D0=BA=D0=B0=D0=BA=20?= =?UTF-8?q?=D0=BF=D0=B0=D1=80=D0=B0=D0=BC=D0=B5=D1=82=D1=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lab1/expirements.py | 8 ++++++++ lab1/gen.py | 36 +++++++++++++++++------------------- lab1/main.py | 8 ++++++++ 3 files changed, 33 insertions(+), 19 deletions(-) diff --git a/lab1/expirements.py b/lab1/expirements.py index 8499d73..112f6b8 100644 --- a/lab1/expirements.py +++ b/lab1/expirements.py @@ -1,9 +1,16 @@ +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" @@ -16,6 +23,7 @@ PM_VALUES = [0.001, 0.01, 0.05, 0.1, 0.2] # вероятности мутаци BASE_CONFIG = { "x_min": 3.1, "x_max": 20.0, + "fitness_func": target_function, "precision_digits": 3, "max_generations": 200, "seed": 17, diff --git a/lab1/gen.py b/lab1/gen.py index 26dacbc..32b207d 100644 --- a/lab1/gen.py +++ b/lab1/gen.py @@ -10,11 +10,6 @@ import matplotlib.pyplot as plt import numpy as np -def target_function(x: float) -> float: - """f(x) = sin(x)/x^2""" - return math.sin(x) / (x * x) - - def bits_for_precision(x_min: float, x_max: float, digits_after_decimal: int) -> int: """ Подбор числа бит L так, чтобы шаг сетки был ≤ 10^{-digits_after_decimal}. @@ -133,13 +128,14 @@ def mutation(chrom: List[int], pm: float) -> None: @dataclass class GARunConfig: - x_min: float = 3.1 - x_max: float = 20.0 - precision_digits: int = 3 # точность сетки ~0.001 - pop_size: int = 100 # размер популяции - pc: float = 0.7 # вероятность кроссинговера - pm: float = 0.01 # вероятность мутации - max_generations: int = 200 # максимальное количество поколений + x_min: float + x_max: float + fitness_func: Callable[[float], float] + precision_digits: int # точность сетки ~0.001 + pop_size: int # размер популяции + pc: float # вероятность кроссинговера + pm: float # вероятность мутации + max_generations: int # максимальное количество поколений seed: int | None = None # seed для генератора случайных чисел save_generations: list[int] | None = ( None # индексы поколений для сохранения графиков @@ -166,10 +162,7 @@ class GARunResult: L: int # число бит -def genetic_algorithm( - config: GARunConfig, - fitness_func: Callable[[float], float] = target_function, -) -> GARunResult: +def genetic_algorithm(config: GARunConfig) -> GARunResult: if config.seed is not None: random.seed(config.seed) np.random.seed(config.seed) @@ -187,7 +180,9 @@ def genetic_algorithm( best_x, best_f = 0, -float("inf") for generation in range(config.max_generations): - xs, fits = eval_population(population, config.x_min, config.x_max, fitness_func) + xs, fits = eval_population( + population, config.x_min, config.x_max, config.fitness_func + ) # лучший в поколении + глобально лучший gi = int(np.argmax(fits)) @@ -233,6 +228,7 @@ def genetic_algorithm( config.x_min, config.x_max, config.results_dir, + config.fitness_func, ) break @@ -247,6 +243,7 @@ def genetic_algorithm( config.x_min, config.x_max, config.results_dir, + config.fitness_func, ) # селекция @@ -285,6 +282,7 @@ def plot_generation_snapshot( x_min: float, x_max: float, results_dir: str, + fitness_func: Callable[[float], float], ) -> str: """ График для конкретного поколения с отображением всей популяции. @@ -292,10 +290,10 @@ def plot_generation_snapshot( os.makedirs(results_dir, exist_ok=True) xs = np.linspace(x_min, x_max, 1500) - ys = np.sin(xs) / (xs * xs) + ys = [fitness_func(x) for x in xs] fig = plt.figure(figsize=(10, 6)) - plt.plot(xs, ys, label="f(x)=sin(x)/x^2", alpha=0.7, color="blue") + plt.plot(xs, ys, label="Целевая функция", alpha=0.7, color="blue") # Отображаем всю популяцию текущего поколения if generation < len(history_populations_x): diff --git a/lab1/main.py b/lab1/main.py index 209a1a8..13576c5 100644 --- a/lab1/main.py +++ b/lab1/main.py @@ -1,11 +1,19 @@ +import math import os from gen import GARunConfig, genetic_algorithm + +def target_function(x: float) -> float: + """f(x) = sin(x)/x^2""" + return math.sin(x) / (x * x) + + # Запуск эксперимента с генетическим алгоритмом config = GARunConfig( x_min=3.1, x_max=20.0, + fitness_func=target_function, precision_digits=3, pop_size=15, pc=0.7,