Загрузка данных
# Программа 3: Построение графиков для варианта 16
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
def f(x):
return x[0]**2 + x[1]**2 + 1.1*x[0]*x[1] + x[0] - x[1] + 1.1
def grad(x):
return np.array([2*x[0] + 1.1*x[1] + 1,
2*x[1] + 1.1*x[0] - 1])
# -------------------- Получение точек минимума (повторяем реализацию методов) --------------------
def simplex_min(f, x0, eps=1e-6):
n = len(x0)
simplex = np.zeros((n, n+1))
simplex[:,0] = x0
for i in range(n):
step = np.zeros(n)
step[i] = 0.5
simplex[:,i+1] = x0 + step
fx = np.array([f(simplex[:,i]) for i in range(n+1)])
it = 0
while np.var(fx) > eps and it < 10000:
ix = np.argsort(fx)
fx = fx[ix]
simplex = simplex[:, ix]
xo = np.mean(simplex[:,:-1], axis=1)
xr = xo + 1.0*(xo - simplex[:,-1])
fxr = f(xr)
if fx[0] <= fxr < fx[-2]:
simplex[:,-1] = xr
fx[-1] = fxr
elif fxr < fx[0]:
xe = xo + 2.0*(xr - xo)
if f(xe) < fxr:
simplex[:,-1] = xe
fx[-1] = f(xe)
else:
simplex[:,-1] = xr
fx[-1] = fxr
else:
xc = xo + 0.5*(simplex[:,-1] - xo)
if f(xc) < fx[-1]:
simplex[:,-1] = xc
fx[-1] = f(xc)
else:
for i in range(1, n+1):
simplex[:,i] = simplex[:,0] + 0.5*(simplex[:,i] - simplex[:,0])
fx = np.array([f(simplex[:,i]) for i in range(n+1)])
it += 1
return simplex[:, np.argmin(fx)]
def grad_min(f, grad, x0, alpha=0.2, eps=1e-6):
x = x0.copy()
f_prev = f(x)
for _ in range(10000):
g = grad(x)
if np.linalg.norm(g) < eps:
break
for _ in range(10):
x_new = x - alpha * g
f_new = f(x_new)
if f_new < f_prev:
x = x_new
f_prev = f_new
break
alpha *= 0.5
return x
x0 = np.array([1.0, 0.0])
x_nm = simplex_min(f, x0) # точка от Нелдера-Мида
x_gd = grad_min(f, grad, x0) # точка от градиентного метода
print("Точки минимумов для графика:")
print(f"Нелдер-Мид: {x_nm}")
print(f"Градиентный: {x_gd}")
# -------------------- Построение сетки --------------------
xx = np.linspace(-2, 2, 50)
X, Y = np.meshgrid(xx, xx)
Z = X**2 + Y**2 + 1.1*X*Y + X - Y + 1.1
# -------------------- 3D поверхность --------------------
fig = plt.figure(figsize=(12, 5))
ax1 = fig.add_subplot(121, projection='3d')
surf = ax1.plot_surface(X, Y, Z, cmap='viridis', edgecolor='none', alpha=0.8)
ax1.scatter(x_nm[0], x_nm[1], f(x_nm), color='red', s=60, label='Нелдер-Мид')
ax1.scatter(x_gd[0], x_gd[1], f(x_gd), color='blue', marker='^', s=60, label='Градиентный')
ax1.set_xlabel('x1')
ax1.set_ylabel('x2')
ax1.set_zlabel('f')
ax1.set_title('Поверхность функции')
ax1.legend()
fig.colorbar(surf, ax=ax1, shrink=0.5, aspect=10)
# -------------------- Контур + линии уровня + стрелки градиентов --------------------
ax2 = fig.add_subplot(122)
contour = ax2.contour(X, Y, Z, levels=20, cmap='viridis')
ax2.clabel(contour, inline=True, fontsize=8)
ax2.set_title('Линии уровня и градиенты')
# Стрелки градиентов (редкая сетка, нормированные)
Xq, Yq = np.meshgrid(np.linspace(-2, 2, 12), np.linspace(-2, 2, 12))
U, V = np.zeros_like(Xq), np.zeros_like(Yq)
for i in range(Xq.shape[0]):
for j in range(Xq.shape[1]):
g = grad([Xq[i,j], Yq[i,j]])
U[i,j], V[i,j] = g[0], g[1]
norm = np.sqrt(U**2 + V**2) + 1e-8
U /= norm
V /= norm
ax2.quiver(Xq, Yq, U, V, alpha=0.6, width=0.003, scale=25)
# Точки минимумов на контуре
ax2.plot(x_nm[0], x_nm[1], 'ro', markersize=8, label='Нелдер-Мид')
ax2.plot(x_gd[0], x_gd[1], 'b^', markersize=8, label='Градиентный')
ax2.set_xlabel('x1')
ax2.set_ylabel('x2')
ax2.legend()
ax2.grid(alpha=0.3)
ax2.axis('equal')
plt.tight_layout()
plt.show()