Hesse矩阵行列式判断极值点可视化

在预习多元函数的极值的时候,我不明白Hesse矩阵的行列式判断极值点的几何意义,所以采用了可视化玩玩,等待老师讲解。

不过很显然的一点就是,判断极值点需要研究:

\Delta f=\frac{1}{2}(A\Delta x^2+2B\Delta x \Delta y +C\Delta y)

也就是那个点附近的变化,A和C是fxx和fyy,B是fxy;

如果对于任何的x,y的变化值,这个f变化值都是变大或者都是变小,那就是极值点

那这个我们完全可以当成函数来研究啊:

z=Ax^2+2Bxy+Cy^2

研究这个函数就好了,这个函数很不错,用这个函数进行可视化可以看到所有可能的稳定点情况!

以下是python代码(不想用大又丑的MATLAB了),这个动画超级棒!!

看它在0点附近的变化,四面八方的变化是否统一就可以作为判断是否极值点的条件

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider

# 创建初始参数
A = 1
B = 1
C = 1

# 确定切点
x0 = 5
y0 = 5

# 生成 x 和 y 的值
x = np.linspace(-10, 10, 400)
y = np.linspace(-10, 10, 400)
X, Y = np.meshgrid(x, y)


def compute_surface(A, B, C):
    """计算 z 的值"""
    return A * X ** 2 + 2 * B * X * Y + C * Y ** 2


# 创建绘图
fig = plt.figure(figsize=(12, 10))
ax = fig.add_subplot(111, projection='3d')

# 绘制初始表面
Z = compute_surface(A, B, C)
surf = ax.plot_surface(X, Y, Z, cmap='viridis', edgecolor='none', alpha=0.3)  # 减弱曲面的透明度

# 标出 (0, 0, 0) 点
ax.scatter(0, 0, 0, color='red', s=100, label='(0, 0, 0)')
ax.text(0, 0, 0, "(0, 0, 0)", color='red')

# 添加标签
ax.set_xlabel('X axis')
ax.set_ylabel('Y axis')
ax.set_zlabel('Z axis')
ax.set_title('Surface Plot with Curves and Tangent Plane')
ax.legend()


# 绘制曲线
def plot_curve(A, B, C):
    """绘制在表面上的曲线"""
    t = np.linspace(-10, 10, 100)

    # 曲线1: y = x
    x_curve1 = t
    y_curve1 = t
    z_curve1 = A * x_curve1 ** 2 + 2 * B * x_curve1 * y_curve1 + C * y_curve1 ** 2
    ax.plot(x_curve1, y_curve1, z_curve1, color='orange', linewidth=2, label='Curve 1: y=x')

    # 曲线2: y = -x
    x_curve2 = t
    y_curve2 = -t
    z_curve2 = A * x_curve2 ** 2 + 2 * B * x_curve2 * y_curve2 + C * y_curve2 ** 2
    ax.plot(x_curve2, y_curve2, z_curve2, color='blue', linewidth=2, label='Curve 2: y=-x')

    ax.legend()


plot_curve(A, B, C)


def plot_tangent_plane(x0, y0, A, B, C):
    """计算并绘制切平面和切线"""
    # 直接计算 z0
    z0 = A * x0 ** 2 + 2 * B * x0 * y0 + C * y0 ** 2

    # 切平面的法向量
    dz_dx = 2 * A * x0 + 2 * B * y0
    dz_dy = 2 * B * x0 + 2 * C * y0

    # 切平面的方程
    def tangent_plane(x, y):
        return z0 + dz_dx * (x - x0) + dz_dy * (y - y0)

    # 生成切平面
    x_tangent = np.linspace(2, 8, 10)
    y_tangent = np.linspace(2, 8, 10)
    X_tangent, Y_tangent = np.meshgrid(x_tangent, y_tangent)
    Z_tangent = tangent_plane(X_tangent, Y_tangent)

    # 绘制切平面
    ax.plot_surface(X_tangent, Y_tangent, Z_tangent, alpha=0.7, color='red', label='Tangent Plane')  # 提高切平面的可见性

    # 切线
    t_vals = np.linspace(-1, 1, 100)
    z_tangent1 = z0 + dz_dx * (t_vals) + dz_dy * (t_vals)  # 切线方向1
    z_tangent2 = z0 + dz_dx * (t_vals) - dz_dy * (t_vals)  # 切线方向2

    ax.plot(x0 + t_vals, y0 + t_vals, z_tangent1, color='green', linewidth=2, label='Tangent Line 1')
    ax.plot(x0 + t_vals, y0 - t_vals, z_tangent2, color='purple', linewidth=2, label='Tangent Line 2')

    ax.scatter(x0, y0, z0, color='black', s=100, label='Tangent Point')
    ax.text(x0, y0, z0, f"({x0}, {y0}, {z0:.2f})", color='black')


plot_tangent_plane(x0, y0, A, B, C)

# 创建滑动条
axcolor = 'lightgoldenrodyellow'
ax_A = plt.axes([0.2, 0.01, 0.65, 0.03], facecolor=axcolor)
ax_B = plt.axes([0.2, 0.05, 0.65, 0.03], facecolor=axcolor)
ax_C = plt.axes([0.2, 0.09, 0.65, 0.03], facecolor=axcolor)

s_A = Slider(ax_A, 'A', -50.0, 50.0, valinit=A)
s_B = Slider(ax_B, 'B', -50.0, 50.0, valinit=B)
s_C = Slider(ax_C, 'C', -50.0, 50.0, valinit=C)


def update(val):
    """更新表面、曲线和切平面图"""
    A = s_A.val
    B = s_B.val
    C = s_C.val
    ax.cla()  # 清除当前轴
    Z = compute_surface(A, B, C)
    ax.plot_surface(X, Y, Z, cmap='viridis', edgecolor='none', alpha=0.3)  # 减弱曲面的透明度
    ax.scatter(0, 0, 0, color='red', s=100, label='(0, 0, 0)')
    ax.text(0, 0, 0, "(0, 0, 0)", color='red')

    # 重新绘制曲线
    plot_curve(A, B, C)

    # 重新绘制切平面及切线
    plot_tangent_plane(x0, y0, A, B, C)

    ax.set_xlabel('X axis')
    ax.set_ylabel('Y axis')
    ax.set_zlabel('Z axis')
    ax.set_title('Surface Plot with Curves and Tangent Plane')
    ax.legend()
    plt.draw()


s_A.on_changed(update)
s_B.on_changed(update)
s_C.on_changed(update)

plt.show()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值