求解优化问题, 拉格朗日乘子法是常用的方法之一
已知目标函数 f ( x , y ) = x 2 + y 2 f(x, y) = x^2 + y^2 f(x,y)=x2+y2, 在约束条件 x y = 3 xy=3 xy=3下, 求 f ( x , y ) f(x, y) f(x,y)的最小值
解: 这是一个典型的约束优化问题, 在之前最简单的办法就是通过约束条件将其中的变量进行变换, 带入目标函数求出极点
将 y = 3 x y=\frac{3}{x} y=x3, 带入 f ( x , y ) = x 2 + y 2 f(x, y)=x^2+y^2 f(x,y)=x2+y2, 可导 f ( x ) = x 2 + 9 x 2 f(x)=x^2+\frac{9}{x^2} f(x)=x2+x29, 求 f ( x ) f(x) f(x)的最小值
根据求极值方法 f ′ ( x ) = 0 f'(x)=0 f′(x)=0(无变化率), 令 x 2 + 9 x 2 = 0 x^2+\frac{9}{x^2}=0 x2+x29=0, 得到点 ( 3 , 3 ) , ( − 3 , − 3 ) (\sqrt{3}, \sqrt{3}), (-\sqrt{3}, -\sqrt{3}) (3,3),(−3,−3)两个点处, f ( x ) f(x) f(x)最小值为6
已知目标函数 V ( x , y , z ) = x y z V(x, y, z)=xyz V(x,y,z)=xyz, 在约束条件 2 x y + 2 y z + 2 x z = S 2xy+2yz+2xz=S 2xy+2yz+2xz=S下, 求体积 V V V的最大值, 如何来求解呢
已知目标函数 f ( x , y ) = x 2 + y 2 f(x, y) = x^2 + y^2 f(x,y)=x2+y2, 在约束条件 x y = 3 xy=3 xy=3下, 求 f ( x , y ) f(x, y) f(x,y)的最小值
首先将 x 2 + y 2 = c x^2+y^2=c x2+y2=c画出来, 当 x y = 3 xy=3 xy=3和曲面相切时, 切点到原点的距离最短, 同等 f ( x , y ) = c f(x, y)=c f(x,y)=c的等高线和双曲线 g ( x , y ) g(x, y) g(x,y)相切时, 可以得到上述优化问题的极值, 那么当 f ( x , y ) = c f(x, y)=c f(x,y)=c和 g ( x , y ) g(x, y) g(x,y)切时, x , y x, y x,y的值是多少?
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as patches
# 设置中文字体
plt.rcParams['font.sans-serif']=['Hiragino Sans GB'] # 修改字体
plt.rcParams['axes.unicode_minus'] = False # 正常显示负号
def add_circle(c, plt, linestyle="solid"):
# 设置常数 C
r = np.sqrt(c)
# 生成角度 θ 的数组
theta = np.linspace(0, 2 * np.pi, 100)
# 参数化生成 x 和 y
x = r * np.cos(theta)
y = r * np.sin(theta)
plt.plot(x, y, label=f'$x^2 + y^2 = {c}$', linestyle=linestyle)
x1 = np.linspace(0, 10, 100)
x2 = np.linspace(-10, 0, 100)
# 绘图
plt.figure(figsize=(6, 6))
add_circle(6, plt)
add_circle(8, plt, "--")
add_circle(10, plt, "--")
plt.plot(x1, 3 / x1, label='$y = \\frac{3}{x}$', color="red")
plt.plot(x2, 3 / x2, color="red")
plt.title("$x^2+y^2=c$和双曲线$xy=3$的关系")
plt.xlabel('x')
plt.ylabel('y')
plt.axis('equal') # 保持坐标轴比例一致,避免椭圆变形
plt.grid(True)
plt.legend()
plt.show()
在梯度问题中, 函数 z = f ( x , y ) z=f(x, y) z=f(x,y)在点 ( x 0 , y 0 ) (x_0, y_0) (x0,y0)的梯度方向过点 ( x 0 , y 0 ) (x_0, y_0) (x0,y0)的等高线 f ( x , y ) = c f(x, y)=c f(x,y)=c在这点的法线方向相同, 且从数值较低的等高线指向数值较高等高线, 而梯度的模等于函数在这个法线方向的方向导数. 法线方向就是方向导数的最大值方向
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as patches
# 设置中文字体
plt.rcParams['font.sans-serif']=['Hiragino Sans GB'] # 修改字体
plt.rcParams['axes.unicode_minus'] = False # 正常显示负号
# 定义网格范围
x = np.linspace(-2, 2, 100)
y = np.linspace(-2, 2, 100)
X, Y = np.meshgrid(x, y)
Z = X**2 + Y**2 # 定义函数 f(x, y)
# 创建图像
plt.figure(figsize=(8, 6))
# 绘制等高线
contour = plt.contour(X, Y, Z, colors='black', linewidths=1)
plt.clabel(contour, inline=True, fontsize=8, fmt='%.1f')
# 设置坐标轴比例一致,确保圆形等高线不变形
plt.axis('equal')
# 选定一个点 (1, 1)
point = (1, 1)
plt.plot(point[0], point[1], 'ro', label='点 $(1, 1)$')
# 计算梯度方向 (2x, 2y)
grad_x, grad_y = 2 * point[0], 2 * point[1]
# 绘制梯度方向箭头
plt.quiver(point[0], point[1], grad_x, grad_y,
angles='xy', scale_units='xy', scale=0.5,
color='r', headwidth=3, label='梯度方向(法线方向)')
# 绘制切线方向(垂直于梯度方向),取方向向量 (-1, 1)
tan_x, tan_y = -1, 1
plt.quiver(point[0], point[1], tan_x, tan_y,
angles='xy', scale_units='xy', scale=5,
color='b', headwidth=3, label='切线方向(方向导数为 0)')
# 添加文字标注
plt.text(point[0] + 0.1, point[1] + 0.1, '梯度方向\n(法线方向)', color='r', fontsize=10)
plt.text(point[0] - 1.5, point[1] + 0.5, '切线方向\n(方向导数为 0)', color='b', fontsize=10)
plt.text(-1.9, 1.8, '等高线 $f(x, y) = c$', color='black', fontsize=10)
# 设置标题和图例
plt.title('梯度方向与等高线法线方向的关系')
plt.xlabel('$x$')
plt.ylabel('$y$')
plt.legend(loc='upper left', fontsize=10)
plt.grid(True)
# 显示图形
plt.show()
根据梯度和等高线的关系, 上面问题 f ( x , y ) f(x, y) f(x,y)和 g ( x , y ) g(x, y) g(x,y)相切时, 切线相同即法向量是相互平行的, 因此可以得到 ▽ f ( x , y ) = − λ ⋅ ▽ g ( x , y ) \bigtriangledown f(x, y)=-\lambda \cdot \bigtriangledown g(x, y) ▽f(x,y)=−λ⋅▽g(x,y)分别求导, 可以得到 ∂ f ∂ x = − λ ∂ g ∂ x \frac{\partial f}{\partial x}=-\lambda \frac{\partial g}{\partial x} ∂x∂f=−λ∂x∂g, ∂ f ∂ y = − λ ∂ g ∂ y \frac{\partial f}{\partial y}=-\lambda \frac{\partial g}{\partial y} ∂y∂f=−λ∂y∂g, 和约束条件 x y = 3 xy=3 xy=3
可得到方程组
{ ∂ f ∂ x = − λ ∂ g ∂ x ∂ f ∂ y = − λ ∂ g ∂ y x y = 3 \begin{cases} \frac{\partial f}{\partial x} = -\lambda \frac{\partial g}{\partial x} \\ \frac{\partial f}{\partial y} = -\lambda \frac{\partial g}{\partial y} \\ xy=3 \end{cases} ⎩ ⎨ ⎧∂x∂f=−λ∂x∂g∂y∂f=−λ∂y∂gxy=3
{ 2 x = − λ y 2 y = − λ x x y = 3 \begin{cases} 2x = -\lambda y \\ 2y = -\lambda x \\ xy=3 \end{cases} ⎩ ⎨ ⎧2x=−λy2y=−λxxy=3
求得到解 x = 3 , y = 3 , λ = − 2 x=\sqrt{3}, y=\sqrt{3}, \lambda=-2 x=3,y=3,λ=−2或者 x = − 3 , y = − 3 , λ = − 2 x=-\sqrt{3}, y=-\sqrt{3}, \lambda=-2 x=−3,y=−3,λ=−2, 通过引入拉格朗日乘子法( λ \lambda λ)将约束问题转化为无约束的方程组问题
已知目标函数为 V ( x , y , z ) = x y z V(x, y, z) = xyz V(x,y,z)=xyz, 在约束条件 2 x y + 2 x z + 2 y z = 12 2xy + 2xz + 2yz = 12 2xy+2xz+2yz=12下, 求体积 V V V得最大值
解: 构造函数为 F ( x , y , z , λ ) = x y z + λ ⋅ ( 2 x y + 2 x z + 2 y z − 12 ) F(x, y, z, \lambda) = xyz + \lambda \cdot(2xy + 2xz + 2yz - 12) F(x,y,z,λ)=xyz+λ⋅(2xy+2xz+2yz−12)
求偏导可以得到方程组
{ y z + λ ⋅ ( 2 y + 2 z ) = 0 x z + λ ⋅ ( 2 x + 2 z ) = 0 x y + λ ⋅ ( 2 x + 2 y ) = 02 x y + 2 x z + 2 y z − 12 = 0 \begin{cases} yz + \lambda \cdot (2y + 2z) = 0 \\ xz + \lambda \cdot (2x + 2z) = 0 \\ xy + \lambda \cdot (2x + 2y) = 0 2xy + 2xz + 2yz - 12 = 0 \end{cases} ⎩ ⎨ ⎧yz+λ⋅(2y+2z)=0xz+λ⋅(2x+2z)=0xy+λ⋅(2x+2y)=02xy+2xz+2yz−12=0
解得: z = y = z = 2 , λ = − 2 4 z=y=z=\sqrt{2}, \lambda=-\frac{\sqrt{2}}{4} z=y=z=2,λ=−42, 目标函数最大值为 2 2 2\sqrt{2} 22
已知目标函数为 u = x 3 y 2 z u=x^3y^2z u=x3y2z, 约束条件为 x + y + z = 12 x+y+z=12 x+y+z=12, 求最大值
解: F ( x , y , z , λ ) = x 3 y 2 z + λ ⋅ ( x + y + z − 12 ) F(x, y, z, \lambda) = x^3y^2z + \lambda \cdot (x + y +z - 12) F(x,y,z,λ)=x3y2z+λ⋅(x+y+z−12)
求偏导可得方程组
{ 3 x 2 y 2 z + λ = 0 2 x 3 y z + λ = 0 x 2 y 2 + λ = 0 x + y + z − 12 = 0 \begin{cases} 3x^2y^2z + \lambda = 0 \\ 2x^3yz + \lambda = 0 \\ x^2y^2 + \lambda = 0 \\ x+ y + z - 12 = 0 \end{cases} ⎩ ⎨ ⎧3x2y2z+λ=02x3yz+λ=0x2y2+λ=0x+y+z−12=0
解唯一驻点 ( x , y , z ) = ( 6 , 4 , 2 ) (x, y, z)=(6,4,2) (x,y,z)=(6,4,2), u m a x = 6912 u_{max}=6912 umax=6912