From 6e7354af93fe5a9f7f0b636fd9356ce1646e670e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9D=D0=B8=D0=BA=D0=B8=D1=82=D0=B0=20=D0=9F=D0=BE=D1=82?= =?UTF-8?q?=D0=B0=D0=BF=D0=BE=D0=B2?= Date: Sun, 27 Apr 2025 19:34:08 +0400 Subject: [PATCH] =?UTF-8?q?=D0=BF=D0=BE=D0=B3=D1=80=D0=B5=D1=88=D0=BD?= =?UTF-8?q?=D0=BE=D1=81=D1=82=D1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lab2/HookJeeves.py | 179 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 137 insertions(+), 42 deletions(-) diff --git a/lab2/HookJeeves.py b/lab2/HookJeeves.py index 81ef73d..f9af56c 100644 --- a/lab2/HookJeeves.py +++ b/lab2/HookJeeves.py @@ -1,4 +1,6 @@ import numpy as np +import AbsoluteMeasurementErrors as abserror +from itertools import product result_log = "" @@ -9,16 +11,42 @@ def log(*values, sep=" ", end="\n"): print(*values, sep=sep, end=end) -def point_info(x, f): - return f"x = {x}, f(x) = {f(x)}" +def get_errors_vector(x): + return np.array(list(map(abserror.get_error, x))) + + +def sum_errors_vector(a, b): + return np.array([abserror.sum_error(a[i], b[i]) for i in range(len(a))]) + + +def frac_errors_vector(a, b): + return np.array([abserror.frac_error(a[i], b) for i in range(len(a))]) + + +def point_info(x, f, x_err): + return f"x = {x}, x_err = {x_err}, f(x) = {f(x)}" def hooke_jeeves( - f, x0, delta0, epsilon, alpha, r=lambda x: True, fit=lambda a, b: a < b + f, + x0, + delta0, + epsilon, + alpha, + r=lambda x: True, + fit=lambda a, b: a < b, + x_err=None, + delta_err=None, ): x = np.array(x0) delta = np.array(delta0) + if x_err is None: + x_err = get_errors_vector(x) + + if delta_err is None: + delta_err = get_errors_vector(delta) + iteration = 0 while np.linalg.norm(delta) > epsilon: @@ -28,77 +56,141 @@ def hooke_jeeves( log("=" * 40) log("Итерация", iteration) - log("Текущая базовая точка", point_info(x, f)) + log("Текущая базовая точка", point_info(x, f, x_err)) - sample_x = exploratory_search(f, x, delta, r=r, fit=fit) + sample_x, sample_x_err = exploratory_search( + f, x, delta, r=r, fit=fit, x_err=x_err, delta_err=delta_err + ) if fit(f(sample_x), f(x)): log("Исследующий поиск УДАЧНЫЙ") - x_p = sample_search(f, x, sample_x, r=r, fit=fit) + x_p, x_p_err = sample_search( + f, x, sample_x, r=r, fit=fit, x1_err=x_err, x2_err=sample_x_err + ) if fit(f(x_p), f(x)): log("Поиск по образцу УДАЧНЫЙ") - x = x_p + x, x_err = x_p, x_p_err else: log("Поиск по образцу ПРОВАЛЕН") - x = sample_x + x, x_err = sample_x, sample_x_err log() - log("Новая базовая точка", point_info(x, f)) + log("Новая базовая точка", point_info(x, f, x_err)) else: log("Исследующий поиск ПРОВАЛЕН") log("Уменьшаем шаг", delta, "->", delta / alpha) delta = delta / alpha + delta_err = frac_errors_vector(delta, alpha) log("ε =", np.linalg.norm(delta)) - return x, f(x) + return x, f(x), x_err -def exploratory_search(f, x, delta, r=lambda x: True, fit=lambda a, b: a < b): +# def exploratory_search( +# f, x, delta, r=lambda x: True, fit=lambda a, b: a < b, x_err=None +# ): +# log() +# log("Выполняем исследующий поиск") + +# if x_err is None: +# x_err = get_errors_vector(x) + +# x_new = np.array(x) +# f_x_new = f(x_new) + +# for i in range(len(x)): +# x_up = x_new.copy() +# x_down = x_new.copy() + +# x_up[i] += delta[i] +# x_down[i] -= delta[i] + +# f_x_up = f(x_up) +# f_x_down = f(x_down) + +# if not r(x_up) or not r(x_down): +# log("Ограничение ОДЗ") + +# if fit(f_x_up, f_x_new) and fit(f_x_up, f_x_down) and r(x_up): +# x_new = x_up +# f_x_new = f_x_up +# elif fit(f_x_down, f_x_new) and r(x_down): +# x_new = x_down +# f_x_new = f_x_down + +# if any([x_new[i] != x[i] for i in range(len(x))]): +# log("Найдена точка", x_new, f(x_new)) + +# return x_new, x_err + + +def exploratory_search( + f, x, delta, r=lambda x: True, fit=lambda a, b: a < b, x_err=None, delta_err=None +): log() log("Выполняем исследующий поиск") - x_new = np.array(x) - f_x_new = f(x_new) + if x_err is None: + x_err = get_errors_vector(x) - for i in range(len(x)): - x_up = x_new.copy() - x_down = x_new.copy() + if delta_err is None: + delta_err = get_errors_vector(delta) - x_up[i] += delta[i] - x_down[i] -= delta[i] + dxs = product(*[[d, -d] for d in delta]) - f_x_up = f(x_up) - f_x_down = f(x_down) + x = np.array(x) + t_x_err = None + t_f = f(x) + t_x = None - if not r(x_up) or not r(x_down): - log("Ограничение ОДЗ") + for dx in dxs: + if fit(f(x + dx), t_f) and r(x + dx): + t_f = f(x + dx) + t_x = x + dx + t_x_err = x_err + delta_err - if fit(f_x_up, f_x_new) and fit(f_x_up, f_x_down) and r(x_up): - x_new = x_up - f_x_new = f_x_up - elif fit(f_x_down, f_x_new) and r(x_down): - x_new = x_down - f_x_new = f_x_down + if t_x is not None: + log("Найдена точка", t_x, t_f) + return t_x, t_x_err - if any([x_new[i] != x[i] for i in range(len(x))]): - log("Найдена точка", x_new, f(x_new)) - return x_new + return x, x_err -def sample_search(f, x1, x2, r=lambda x: True, fit=lambda a, b: a < b): +def sample_search( + f, x1, x2, r=lambda x: True, fit=lambda a, b: a < b, x1_err=None, x2_err=None +): log() log("Выполняем поиск по образцу") + + if x1_err is None: + x1_err = get_errors_vector(x1) + + if x2_err is None: + x2_err = get_errors_vector(x2) + + x2_last = x2.copy() + x2_last_err = x2_err.copy() + while fit(f(x2), f(x1)): + x2_last = x2.copy() + x2_last_err = x2_err.copy() + if not r(x2 + (x2 - x1)): log("Ограничение ОДЗ") break + x2, x1 = x2 + (x2 - x1), x2 - log("Найдена точка", x2, f(x2)) - return x2 + + t_err = x2_err.copy() + x2_err = x2_err + (x2_err + x1_err) + x1_err = t_err.copy() + + log("Найдена точка", x2_last, f(x2_last)) + return x2_last, x2_last_err def example(): @@ -143,18 +235,21 @@ def example(): ] ) - x, val = hooke_jeeves(f, x0, delta0, epsilon, alpha, r=r, fit=fit) - return x, val - - -if __name__ == "__main__": - - x, val = example() + x, val, x_err = hooke_jeeves(f, x0, delta0, epsilon, alpha, r=r, fit=fit) log() log("=" * 40) log("Точка экстремумв:", x) - log("Минимальное значение функции:", val) + log("Абсолютная погрешность:", x_err) + log("Максимальное значение функции:", val) with open("result.log", "w", encoding="utf-8") as file: file.write(result_log) + + +def main(): + example() + + +if __name__ == "__main__": + main()