task1
This commit is contained in:
167
task1/golden_section_search.py
Normal file
167
task1/golden_section_search.py
Normal file
@@ -0,0 +1,167 @@
|
||||
# golden_section_search.py
|
||||
# Метод золотого сечения для одномерной оптимизации (10 итераций)
|
||||
# Условия из задачи: f(x) = sqrt(x^2 + 9) / 4 + (5 - x) / 5, X = [-3, 8]
|
||||
|
||||
import math
|
||||
from pathlib import Path
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
|
||||
# Глобальный счётчик обращений к оракулу
|
||||
oracle_calls = 0
|
||||
|
||||
|
||||
def f(x: float) -> float:
|
||||
global oracle_calls
|
||||
oracle_calls += 1
|
||||
return math.sqrt(x**2 + 9) / 4 + (5 - x) / 5
|
||||
|
||||
|
||||
# Параметры
|
||||
a_init = -3.0
|
||||
b_init = 8.0
|
||||
num_iters = 10 # ровно 10 итераций
|
||||
|
||||
# Константы золотого сечения
|
||||
phi = (1 + math.sqrt(5)) / 2.0 # ~1.618...
|
||||
r = 1 / phi # ~0.618...
|
||||
c = 1 - r # ~0.382...
|
||||
|
||||
# Создаём папку для графиков
|
||||
Path("golden_section_plots").mkdir(exist_ok=True)
|
||||
|
||||
# История итераций
|
||||
history = []
|
||||
|
||||
# Начальные значения
|
||||
a = a_init
|
||||
b = b_init
|
||||
|
||||
# Начальные точки
|
||||
y = a + c * (b - a)
|
||||
z = a + r * (b - a)
|
||||
fy = f(y)
|
||||
fz = f(z)
|
||||
|
||||
print("Метод золотого сечения")
|
||||
print("=" * 80)
|
||||
|
||||
print("\nНачальное состояние:")
|
||||
print(f" Интервал: [{a:.6f}, {b:.6f}], длина = {b - a:.6f}")
|
||||
print(f" y = {y:.6f}, f(y) = {fy:.6f}")
|
||||
print(f" z = {z:.6f}, f(z) = {fz:.6f}")
|
||||
|
||||
# Основной цикл
|
||||
for k in range(1, num_iters + 1):
|
||||
# Сохраняем состояние до обновления
|
||||
history.append(
|
||||
{
|
||||
"iter": k,
|
||||
"a": a,
|
||||
"b": b,
|
||||
"y": y,
|
||||
"z": z,
|
||||
"fy": fy,
|
||||
"fz": fz,
|
||||
"interval_length": b - a,
|
||||
}
|
||||
)
|
||||
|
||||
print(f"\nИтерация {k}:")
|
||||
print(f" Интервал: [{a:.6f}, {b:.6f}], длина = {b - a:.6f}")
|
||||
print(f" y = {y:.6f}, f(y) = {fy:.6f}")
|
||||
print(f" z = {z:.6f}, f(z) = {fz:.6f}")
|
||||
|
||||
# Построение графика
|
||||
x_plot = np.linspace(a_init, b_init, 500)
|
||||
y_plot = [f(x) for x in x_plot]
|
||||
|
||||
plt.figure(figsize=(10, 6))
|
||||
plt.plot(x_plot, y_plot, "b-", linewidth=2, label="f(x)")
|
||||
plt.axvline(
|
||||
a, color="red", linestyle="--", alpha=0.7, label=f"Интервал [{a:.3f}, {b:.3f}]"
|
||||
)
|
||||
plt.axvline(b, color="red", linestyle="--", alpha=0.7)
|
||||
plt.plot(y, fy, "go", markersize=10, label=f"y = {y:.3f}, f(y) = {fy:.4f}")
|
||||
plt.plot(z, fz, "mo", markersize=10, label=f"z = {z:.3f}, f(z) = {fz:.4f}")
|
||||
|
||||
plt.xlabel("x", fontsize=12)
|
||||
plt.ylabel("f(x)", fontsize=12)
|
||||
plt.title(f"Золотое сечение - Итерация {k}", fontsize=14, fontweight="bold")
|
||||
plt.legend(fontsize=10)
|
||||
plt.grid(True, alpha=0.3)
|
||||
plt.tight_layout()
|
||||
plt.savefig(f"golden_section_plots/iteration_{k:02d}.png", dpi=150)
|
||||
plt.close()
|
||||
|
||||
# Обновление интервала
|
||||
if fy <= fz:
|
||||
print(f" f(y) <= f(z) -> новый интервал: [{a:.6f}, {z:.6f}]")
|
||||
b = z
|
||||
z = y
|
||||
fz = fy
|
||||
y = a + c * (b - a)
|
||||
fy = f(y)
|
||||
else:
|
||||
print(f" f(y) > f(z) -> новый интервал: [{y:.6f}, {b:.6f}]")
|
||||
a = y
|
||||
y = z
|
||||
fy = fz
|
||||
z = a + r * (b - a)
|
||||
fz = f(z)
|
||||
|
||||
# Итоговая оценка минимума
|
||||
x_star = (a + b) / 2.0
|
||||
f_star = f(x_star)
|
||||
|
||||
# Финальный график
|
||||
x_plot = np.linspace(a_init, b_init, 500)
|
||||
y_plot = [f(x) for x in x_plot]
|
||||
|
||||
plt.figure(figsize=(10, 6))
|
||||
plt.plot(x_plot, y_plot, "b-", linewidth=2, label="f(x)")
|
||||
plt.axvline(
|
||||
a,
|
||||
color="red",
|
||||
linestyle="--",
|
||||
alpha=0.7,
|
||||
label=f"Финальный интервал [{a:.6f}, {b:.6f}]",
|
||||
)
|
||||
plt.axvline(b, color="red", linestyle="--", alpha=0.7)
|
||||
plt.plot(
|
||||
x_star,
|
||||
f_star,
|
||||
"r*",
|
||||
markersize=20,
|
||||
label=f"x* = {x_star:.6f}, f(x*) = {f_star:.6f}",
|
||||
)
|
||||
|
||||
plt.xlabel("x", fontsize=12)
|
||||
plt.ylabel("f(x)", fontsize=12)
|
||||
plt.title("Золотое сечение - Финальный результат", fontsize=14, fontweight="bold")
|
||||
plt.legend(fontsize=10)
|
||||
plt.grid(True, alpha=0.3)
|
||||
plt.tight_layout()
|
||||
plt.savefig("golden_section_plots/final_result.png", dpi=150)
|
||||
plt.close()
|
||||
|
||||
print("\n" + "=" * 80)
|
||||
print(f"\nИтераций выполнено: {num_iters}")
|
||||
print(f"x* ~= {x_star:.6f}")
|
||||
print(f"f(x*) ~= {f_star:.6f}")
|
||||
print(f"Длина финального интервала: {b - a:.6f}")
|
||||
# print(f"\nОбращений к оракулу (вычислений функции): {oracle_calls}")
|
||||
print("\nГрафики сохранены в папке 'golden_section_plots/'")
|
||||
|
||||
# Таблица всех итераций
|
||||
print("\n" + "=" * 80)
|
||||
print("Сводная таблица:")
|
||||
print("-" * 80)
|
||||
for row in history:
|
||||
print(
|
||||
f"Итерация {row['iter']:2d}: "
|
||||
f"[{row['a']:7.4f}, {row['b']:7.4f}] (D={row['interval_length']:7.4f}), "
|
||||
f"y={row['y']:7.4f} (f={row['fy']:.4f}), "
|
||||
f"z={row['z']:7.4f} (f={row['fz']:.4f})"
|
||||
)
|
||||
Reference in New Issue
Block a user