拉格朗日乘数法算法详解Python实现
目录
- 一、拉格朗日乘数法算法详解
- 1.1 基本思想
- 1.2 数学推导
- 1.3 算法步骤
- 1.4 算法在编程中的实现
- 二、案例分析
- 案例一:二维最优化问题——求 f ( x , y ) = x 2 + y 2 f(x,y)=x^2+y^2 f(x,y)=x2+y2 在约束 x + y = 1 x+y=1 x+y=1 下的极值
- 2.1.1 问题描述
- 2.1.2 数学模型构建
- 2.1.3 算法流程图(Mermaid 语法)
- 2.1.4 Python 代码实现
- 案例二:乘积最大化问题——求 f ( x , y ) = x y f(x,y)=xy f(x,y)=xy 在约束 x 2 + y 2 = 1 x^2+y^2=1 x2+y2=1 下的极值
- 2.2.1 问题描述
- 2.2.2 数学模型构建
- 2.2.3 算法流程图(Mermaid 语法)
- 2.2.4 Python 代码实现
- 案例三:三变量最优化问题——最小化 f ( x , y , z ) = ( x − 1 ) 2 + ( y − 2 ) 2 + ( z − 3 ) 2 f(x,y,z)=(x-1)^2+(y-2)^2+(z-3)^2 f(x,y,z)=(x−1)2+(y−2)2+(z−3)2 在约束 x + y + z = 6 x+y+z=6 x+y+z=6 下
- 2.3.1 问题描述
- 2.3.2 数学模型构建
- 2.3.3 算法流程图(Mermaid 语法)
- 2.3.4 Python 代码实现
- 三、总结
- 四、扩展讨论
- 4.1 多约束问题
- 4.2 数值解法与符号求解
- 4.3 算法设计规范
- 五、结语
一、拉格朗日乘数法算法详解
在优化问题中,我们常常遇到带有约束条件的极值问题。传统的无约束极值求解方法无法直接处理此类问题,而拉格朗日乘数法正是为了解决这一问题而提出的。
1.1 基本思想
考虑一个目标函数
f ( x 1 , x 2 , … , x n ) f(x_1,x_2,\dots,x_n) f(x1,x2,…,xn)
在满足约束条件
g ( x 1 , x 2 , … , x n ) = 0 g(x_1,x_2,\dots,x_n)=0 g(x1,x2,…,xn)=0
下求极值。直观上,由于约束条件将可行域限制在一个低维曲面上,我们无法简单地求偏导令其为零。拉格朗日乘数法的基本思想是引入一个辅助变量 λ \lambda λ,构造拉格朗日函数
L ( x 1 , x 2 , … , x n , λ ) = f ( x 1 , x 2 , … , x n ) − λ g ( x 1 , x 2 , … , x n ) L(x_1,x_2,\dots,x_n,\lambda)=f(x_1,x_2,\dots,x_n)-\lambda g(x_1,x_2,\dots,x_n) L(x1,x2,…,xn,λ)=f(x1,x2,…,xn)−λg(x1,x2,…,xn)
在满足
∇ L ( x 1 , x 2 , … , x n , λ ) = 0 \nabla L(x_1,x_2,\dots,x_n,\lambda)=0 ∇L(x1,x2,…,xn,λ)=0
的条件下,即可得到极值点。直观上,这一方法可以理解为在原问题中加入一项“惩罚因子”,使得在求解无约束问题时自动满足约束条件。
1.2 数学推导
设目标函数 f ( x ) f(\mathbf{x}) f(x) 与约束条件 g ( x ) = 0 g(\mathbf{x})=0 g(x)=0,令
L ( x , λ ) = f ( x ) − λ g ( x ) L(\mathbf{x},\lambda)=f(\mathbf{x})-\lambda g(\mathbf{x}) L(x,λ)=f(x)−λg(x)
则有以下必要条件:
∂ L ∂ x i = ∂ f ∂ x i − λ ∂ g ∂ x i = 0 , i = 1 , 2 , … , n , \frac{\partial L}{\partial x_i} = \frac{\partial f}{\partial x_i} - \lambda \frac{\partial g}{\partial x_i} = 0,\quad i=1,2,\dots,n, ∂xi∂L=∂xi∂f−λ∂xi∂g=0,i=1,2,…,n,
∂ L ∂ λ = − g ( x ) = 0. \frac{\partial L}{\partial \lambda} = -g(\mathbf{x}) = 0. ∂λ∂L=−g(x)=0.
这组方程同时包含了目标函数在可行域上的导数信息与约束条件,因此可以同时求得变量 x \mathbf{x} x 与乘数 λ \lambda λ 的值。注意,在某些问题中,可能有多个约束,此时需要引入多个拉格朗日乘数,构造
L ( x , λ 1 , λ 2 , … , λ m ) = f ( x ) − ∑ j = 1 m λ j g j ( x ) L(\mathbf{x},\lambda_1,\lambda_2,\dots,\lambda_m)=f(\mathbf{x})-\sum_{j=1}^{m}\lambda_j g_j(\mathbf{x}) L(x,λ1,λ2,…,λm)=f(x)−j=1∑mλjgj(x)
并求解相应的梯度为零的方程组。
1.3 算法步骤
下面给出基于拉格朗日乘数法求解约束优化问题的一般步骤:
-
构造拉格朗日函数
根据目标函数 f ( x ) f(\mathbf{x}) f(x) 和约束条件 g ( x ) = 0 g(\mathbf{x})=0 g(x)=0 构造
L ( x , λ ) = f ( x ) − λ g ( x ) . L(\mathbf{x},\lambda)=f(\mathbf{x})-\lambda g(\mathbf{x}). L(x,λ)=f(x)−λg(x). -
求偏导并构造方程组
对每个变量 x i x_i xi 求偏导并令其为零,得到
∂ f ∂ x i − λ ∂ g ∂ x i = 0 , i = 1 , … , n , \frac{\partial f}{\partial x_i}-\lambda \frac{\partial g}{\partial x_i}=0,\quad i=1,\dots,n, ∂xi∂f−λ∂xi∂g=0,i=1,…,n,
同时,考虑约束条件
g ( x ) = 0. g(\mathbf{x})=0. g(x)=0. -
求解方程组
联立上述方程组,求解变量 x \mathbf{x} x 与 λ \lambda λ 的值。 -
验证极值与判别
求得的候选解可能为极大值、极小值或鞍点,必要时需要进一步验证(例如,通过二阶条件或实际问题背景判断)。
1.4 算法在编程中的实现
在实际工程中,我们通常将上述算法封装为一个类或函数。下面给出一个伪代码示例:
class LagrangeOptimizer:def __init__(self, f, constraints, variables, lambdas):self.f = f # 目标函数self.constraints = constraints # 约束条件列表self.variables = variables # 优化变量列表self.lambdas = lambdas # 拉格朗日乘数列表def construct_lagrangian(self):# 构造拉格朗日函数 L = f - \sum_i \lambda_i * constraint_iL = self.ffor lam, g in zip(self.lambdas, self.constraints):L -= lam * greturn Ldef solve(self):# 求解梯度方程组L = self.construct_lagrangian()eqs = []for var in self.variables:eqs.append(diff(L, var))for g in self.constraints:eqs.append(g) # 约束条件 g = 0solutions = solve(eqs, self.variables + self.lambdas)return solutions
以上伪代码利用符号计算(例如 sympy)构造拉格朗日函数,并求解梯度为零的方程组。接下来,将结合具体案例进行详细分析。
二、案例分析
接下来我们通过三个经典案例,对拉格朗日乘数法进行具体分析与代码实现。每个案例均包含:
- 问题描述
- 数学模型及求解步骤
- 完整的 Python 代码实现
- 基于 Mermaid 语法的流程图
- 控制与优化曲线的绘制
案例一:二维最优化问题——求 f ( x , y ) = x 2 + y 2 f(x,y)=x^2+y^2 f(x,y)=x2+y2 在约束 x + y = 1 x+y=1 x+y=1 下的极值
2.1.1 问题描述
考虑最小化目标函数
f ( x , y ) = x 2 + y 2 f(x,y)=x^2+y^2 f(x,y)=x2+y2
在约束条件
g ( x , y ) = x + y − 1 = 0 g(x,y)=x+y-1=0 g(x,y)=x+y−1=0
下求极值。直观上,函数 x 2 + y 2 x^2+y^2 x2+y2 表示二维平面上到原点的距离平方,约束条件 x + y = 1 x+y=1 x+y=1 则是一条直线。问题的几何意义即为求直线上离原点最近的点。
2.1.2 数学模型构建
构造拉格朗日函数:
L ( x , y , λ ) = x 2 + y 2 − λ ( x + y − 1 ) . L(x,y,\lambda)=x^2+y^2-\lambda (x+y-1). L(x,y,λ)=x2+y2−λ(x+y−1).
求解偏导得:
∂ L ∂ x = 2 x − λ = 0 , ( 1 ) \frac{\partial L}{\partial x}=2x-\lambda=0, \quad (1) ∂x∂L=2x−λ=0,(1)
∂ L ∂ y = 2 y − λ = 0 , ( 2 ) \frac{\partial L}{\partial y}=2y-\lambda=0, \quad (2) ∂y∂L=2y−λ=0,(2)
∂ L ∂ λ = − ( x + y − 1 ) = 0. ( 3 ) \frac{\partial L}{\partial \lambda}=-(x+y-1)=0. \quad (3) ∂λ∂L=−(x+y−1)=0.(3)
由 (1) 和 (2) 可知:
2 x = 2 y ⟹ x = y . 2x=2y \Longrightarrow x=y. 2x=2y⟹x=y.
代入 (3) 得:
x + x − 1 = 0 ⟹ x = 1 2 , y = 1 2 . x+x-1=0\Longrightarrow x=\frac{1}{2},\quad y=\frac{1}{2}. x+x−1=0⟹x=21,y=21.
同时由 (1) 可得:
λ = 2 x = 1. \lambda=2x=1. λ=2x=1.
因此,当 x = y = 1 2 x=y=\frac{1}{2} x=y=21 时取得极小值,且最小值为
f ( 1 2 , 1 2 ) = 1 4 + 1 4 = 1 2 . f\left(\frac{1}{2},\frac{1}{2}\right)=\frac{1}{4}+\frac{1}{4}=\frac{1}{2}. f(21,21)=41+41=21.
2.1.3 算法流程图(Mermaid 语法)
下面给出基于 Mermaid 语法的流程图,描述该案例的求解流程:
flowchart TDA[开始]B[输入目标函数 $f(x,y)=x^2+y^2$ 和约束 $g(x,y)=x+y-1=0$]C[构造拉格朗日函数 $L(x,y,\lambda)=x^2+y^2-\lambda(x+y-1)$]D[求偏导:$\frac{\partial L}{\partial x}=2x-\lambda=0$]E[求偏导:$\frac{\partial L}{\partial y}=2y-\lambda=0$]F[求偏导:$\frac{\partial L}{\partial \lambda}=-(x+y-1)=0$]G[得到 $x=y$]H[代入约束求解 $x=y=\frac{1}{2}$]I[计算最小值 $f=\frac{1}{2}$]J[结束]A --> BB --> CC --> DD --> EE --> FF --> GG --> HH --> II --> J
2.1.4 Python 代码实现
下面的代码实现利用 sympy 构造符号表达式,求解上述方程组,并利用 matplotlib 绘制目标函数及约束曲线的示意图。
# 案例一:最小化 f(x, y) = x^2 + y^2 在约束 x + y = 1 下的极值import sympy as sp
import numpy as np
import matplotlib.pyplot as pltdef case1_lagrange():# 定义符号变量x, y, lam = sp.symbols('x y lam', real=True)# 定义目标函数和约束条件f = x**2 + y**2g = x + y - 1# 构造拉格朗日函数L = f - lam * g# 求偏导并构造方程组eq1 = sp.Eq(sp.diff(L, x), 0) # 2x - lam = 0eq2 = sp.Eq(sp.diff(L, y), 0) # 2y - lam = 0eq3 = sp.Eq(g, 0) # x + y - 1 = 0# 求解方程组sol = sp.solve([eq1, eq2, eq3], (x, y, lam), dict=True)sol = sol[0]print("案例一求解结果:")print("x =", sol[x])print("y =", sol[y])print("lambda =", sol[lam])print("最小值 f =", f.subs({x: sol[x], y: sol[y]}))# 绘制目标函数和约束条件图形x_vals = np.linspace(-0.5, 1.5, 400)y_vals = np.linspace(-0.5, 1.5, 400)X, Y = np.meshgrid(x_vals, y_vals)Z = X**2 + Y**2plt.figure(figsize=(8,6))cp = plt.contour(X, Y, Z, levels=30, cmap='viridis')plt.clabel(cp, inline=True, fontsize=8)# 绘制约束直线 x+y=1plt.plot(x_vals, 1 - x_vals, 'r-', linewidth=2, label='Constraint: $x+y=1$')# 标出最优点plt.plot(sol[x], sol[y], 'ko', markersize=8, label='Optimal Point')plt.xlabel('x')plt.ylabel('y')plt.title('案例一:目标函数轮廓与约束直线')plt.legend()plt.grid(True)plt.show()if __name__ == '__main__':case1_lagrange()
运行上述代码,即可看到求解结果和图示,其中红色直线表示约束条件,黑色点为最优点。
案例二:乘积最大化问题——求 f ( x , y ) = x y f(x,y)=xy f(x,y)=xy 在约束 x 2 + y 2 = 1 x^2+y^2=1 x2+y2=1 下的极值
2.2.1 问题描述
本案例考虑在单位圆上求函数
f ( x , y ) = x y f(x,y)=xy f(x,y)=xy
的极值。约束条件为
g ( x , y ) = x 2 + y 2 − 1 = 0. g(x,y)=x^2+y^2-1=0. g(x,y)=x2+y2−1=0.
该问题在经济学和工程优化中有一定应用,比如在某些均衡问题中求得最大乘积值。
2.2.2 数学模型构建
构造拉格朗日函数:
L ( x , y , λ ) = x y − λ ( x 2 + y 2 − 1 ) . L(x,y,\lambda)=xy-\lambda (x^2+y^2-1). L(x,y,λ)=xy−λ(x2+y2−1).
求偏导得:
∂ L ∂ x = y − 2 λ x = 0 , ( 1 ) \frac{\partial L}{\partial x}=y-2\lambda x=0,\quad (1) ∂x∂L=y−2λx=0,(1)
∂ L ∂ y = x − 2 λ y = 0 , ( 2 ) \frac{\partial L}{\partial y}=x-2\lambda y=0,\quad (2) ∂y∂L=x−2λy=0,(2)
∂ L ∂ λ = − ( x 2 + y 2 − 1 ) = 0. ( 3 ) \frac{\partial L}{\partial \lambda}=-(x^2+y^2-1)=0.\quad (3) ∂λ∂L=−(x2+y2−1)=0.(3)
由 (1) 与 (2) 得:
- 当 x ≠ 0 , y ≠ 0 x\neq0,y\neq0 x=0,y=0 时,可以得到
λ = y 2 x = x 2 y ⟹ x 2 = y 2 . \lambda=\frac{y}{2x}=\frac{x}{2y}\Longrightarrow x^2=y^2. λ=2xy=2yx⟹x2=y2.
即 x = ± y x=\pm y x=±y。
情形 1:当 x = y x=y x=y 时
代入 (3) 得:
2 x 2 = 1 ⟹ x = ± 1 2 , y = ± 1 2 . 2x^2=1 \Longrightarrow x=\pm\frac{1}{\sqrt{2}}, \quad y=\pm\frac{1}{\sqrt{2}}. 2x2=1⟹x=±21,y=±21.
此时 f ( x , y ) = 1 2 f(x,y)=\frac{1}{2} f(x,y)=21 或 1 2 \frac{1}{2} 21。
情形 2:当 x = − y x=-y x=−y 时
代入 (3) 得:
2 x 2 = 1 ⟹ x = ± 1 2 , y = ∓ 1 2 , 2x^2=1 \Longrightarrow x=\pm\frac{1}{\sqrt{2}}, \quad y=\mp\frac{1}{\sqrt{2}}, 2x2=1⟹x=±21,y=∓21,
此时 f ( x , y ) = − 1 2 f(x,y)=-\frac{1}{2} f(x,y)=−21。
因此,极大值为 1 2 \frac{1}{2} 21,极小值为 − 1 2 -\frac{1}{2} −21。
2.2.3 算法流程图(Mermaid 语法)
下面是该案例的流程图:
flowchart TDA[开始]B[输入目标函数 $f(x,y)=xy$ 和约束 $g(x,y)=x^2+y^2-1=0$]C[构造拉格朗日函数 $L(x,y,\lambda)=xy-\lambda(x^2+y^2-1)$]D[求偏导:$\frac{\partial L}{\partial x}=y-2\lambda x=0$]E[求偏导:$\frac{\partial L}{\partial y}=x-2\lambda y=0$]F[求偏导:$\frac{\partial L}{\partial \lambda}=-(x^2+y^2-1)=0$]G[由 (D) 和 (E) 得到 $x^2=y^2$]H[考虑情形 $x=y$ 和 $x=-y$]I[代入约束求得候选解]J[计算目标函数值得到极值]K[结束]A --> BB --> CC --> DD --> EE --> FF --> GG --> HH --> II --> JJ --> K
2.2.4 Python 代码实现
下面给出基于 sympy 求解该问题的完整代码,同时绘制单位圆和目标函数等高线图,并标记出极值点。
# 案例二:最大化 f(x, y) = x*y 在约束 x^2 + y^2 = 1 下的极值import sympy as sp
import numpy as np
import matplotlib.pyplot as pltdef case2_lagrange():# 定义符号变量x, y, lam = sp.symbols('x y lam', real=True)# 定义目标函数和约束条件f = x * yg = x**2 + y**2 - 1# 构造拉格朗日函数L = f - lam * g# 求偏导并构造方程组eq1 = sp.Eq(sp.diff(L, x), 0) # y - 2*lam*x = 0eq2 = sp.Eq(sp.diff(L, y), 0) # x - 2*lam*y = 0eq3 = sp.Eq(g, 0) # x^2+y^2-1 = 0# 求解方程组sols = sp.solve([eq1, eq2, eq3], (x, y, lam), dict=True)print("案例二求解结果:")for sol in sols:print("解:x =", sol[x], ", y =", sol[y], ", lambda =", sol[lam])print("f(x,y) =", f.subs({x: sol[x], y: sol[y]}))print("------")# 绘制目标函数等高线和约束条件(单位圆)x_vals = np.linspace(-1.2, 1.2, 400)y_vals = np.linspace(-1.2, 1.2, 400)X, Y = np.meshgrid(x_vals, y_vals)Z = X * Yplt.figure(figsize=(8,6))cp = plt.contour(X, Y, Z, levels=30, cmap='plasma')plt.clabel(cp, inline=True, fontsize=8)# 绘制单位圆theta = np.linspace(0, 2*np.pi, 400)plt.plot(np.cos(theta), np.sin(theta), 'r-', linewidth=2, label='Constraint: $x^2+y^2=1$')# 标出候选解for sol in sols:x_opt = float(sol[x])y_opt = float(sol[y])plt.plot(x_opt, y_opt, 'ko', markersize=8)plt.xlabel('x')plt.ylabel('y')plt.title('案例二:目标函数等高线与单位圆')plt.legend()plt.grid(True)plt.show()if __name__ == '__main__':case2_lagrange()
运行代码后,可见单位圆(红色曲线)与目标函数等高线图,黑色点分别代表候选解,极大值和极小值一目了然。
案例三:三变量最优化问题——最小化 f ( x , y , z ) = ( x − 1 ) 2 + ( y − 2 ) 2 + ( z − 3 ) 2 f(x,y,z)=(x-1)^2+(y-2)^2+(z-3)^2 f(x,y,z)=(x−1)2+(y−2)2+(z−3)2 在约束 x + y + z = 6 x+y+z=6 x+y+z=6 下
2.3.1 问题描述
本案例考虑三维空间中的最小化问题。目标函数为
f ( x , y , z ) = ( x − 1 ) 2 + ( y − 2 ) 2 + ( z − 3 ) 2 , f(x,y,z)=(x-1)^2+(y-2)^2+(z-3)^2, f(x,y,z)=(x−1)2+(y−2)2+(z−3)2,
描述了点 ( x , y , z ) (x,y,z) (x,y,z) 与定点 ( 1 , 2 , 3 ) (1,2,3) (1,2,3) 之间的欧氏距离平方。约束条件为
g ( x , y , z ) = x + y + z − 6 = 0 , g(x,y,z)=x+y+z-6=0, g(x,y,z)=x+y+z−6=0,
即所有满足三个坐标和为 6 的点构成的平面。问题实际意义为:在给定平面上寻找与点 ( 1 , 2 , 3 ) (1,2,3) (1,2,3) 最近的点。
2.3.2 数学模型构建
构造拉格朗日函数:
L ( x , y , z , λ ) = ( x − 1 ) 2 + ( y − 2 ) 2 + ( z − 3 ) 2 − λ ( x + y + z − 6 ) . L(x,y,z,\lambda)=(x-1)^2+(y-2)^2+(z-3)^2-\lambda(x+y+z-6). L(x,y,z,λ)=(x−1)2+(y−2)2+(z−3)2−λ(x+y+z−6).
求偏导得:
- 对 x x x:
∂ L ∂ x = 2 ( x − 1 ) − λ = 0 , ( 1 ) \frac{\partial L}{\partial x}=2(x-1)-\lambda=0,\quad (1) ∂x∂L=2(x−1)−λ=0,(1) - 对 y y y:
∂ L ∂ y = 2 ( y − 2 ) − λ = 0 , ( 2 ) \frac{\partial L}{\partial y}=2(y-2)-\lambda=0,\quad (2) ∂y∂L=2(y−2)−λ=0,(2) - 对 z z z:
∂ L ∂ z = 2 ( z − 3 ) − λ = 0 , ( 3 ) \frac{\partial L}{\partial z}=2(z-3)-\lambda=0,\quad (3) ∂z∂L=2(z−3)−λ=0,(3) - 对 λ \lambda λ:
∂ L ∂ λ = − ( x + y + z − 6 ) = 0. ( 4 ) \frac{\partial L}{\partial \lambda}=-(x+y+z-6)=0.\quad (4) ∂λ∂L=−(x+y+z−6)=0.(4)
由 (1)、(2)、(3) 可得:
λ = 2 ( x − 1 ) = 2 ( y − 2 ) = 2 ( z − 3 ) . \lambda=2(x-1)=2(y-2)=2(z-3). λ=2(x−1)=2(y−2)=2(z−3).
令 2 ( x − 1 ) = 2 ( y − 2 ) 2(x-1)=2(y-2) 2(x−1)=2(y−2),得到 x − 1 = y − 2 ⟹ x = y + 1 x-1=y-2\Longrightarrow x=y+1 x−1=y−2⟹x=y+1。
同理,由 2 ( y − 2 ) = 2 ( z − 3 ) 2(y-2)=2(z-3) 2(y−2)=2(z−3) 得 y − 2 = z − 3 ⟹ y = z + 1 y-2=z-3\Longrightarrow y=z+1 y−2=z−3⟹y=z+1。
因此,关系为:
x = z + 2 , y = z + 1. x=z+2,\quad y=z+1. x=z+2,y=z+1.
将它们代入约束 (4) 中:
( z + 2 ) + ( z + 1 ) + z = 6 ⟹ 3 z + 3 = 6 ⟹ z = 1. (z+2)+(z+1)+z=6 \Longrightarrow 3z+3=6\Longrightarrow z=1. (z+2)+(z+1)+z=6⟹3z+3=6⟹z=1.
从而得到 y = 2 , x = 3 y=2,\; x=3 y=2,x=3。最终极小值为
f ( 3 , 2 , 1 ) = ( 3 − 1 ) 2 + ( 2 − 2 ) 2 + ( 1 − 3 ) 2 = 2 2 + 0 2 + ( − 2 ) 2 = 8. f(3,2,1)=(3-1)^2+(2-2)^2+(1-3)^2=2^2+0^2+(-2)^2=8. f(3,2,1)=(3−1)2+(2−2)2+(1−3)2=22+02+(−2)2=8.
2.3.3 算法流程图(Mermaid 语法)
以下是该案例的流程图:
flowchart TDA[开始]B[输入目标函数 $f(x,y,z)=(x-1)^2+(y-2)^2+(z-3)^2$ 和约束 $g(x,y,z)=x+y+z-6=0$]C[构造拉格朗日函数 $L(x,y,z,\lambda)= (x-1)^2+(y-2)^2+(z-3)^2 -\lambda(x+y+z-6)$]D[求偏导:$\frac{\partial L}{\partial x}=2(x-1)-\lambda=0$]E[求偏导:$\frac{\partial L}{\partial y}=2(y-2)-\lambda=0$]F[求偏导:$\frac{\partial L}{\partial z}=2(z-3)-\lambda=0$]G[求偏导:$\frac{\partial L}{\partial \lambda}=-(x+y+z-6)=0$]H[由 (D)-(F) 得到关系 $x=z+2$, $y=z+1$]I[代入约束求解 $z=1$, 得 $y=2$, $x=3$]J[计算目标函数值 $f=8$]K[结束]A --> BB --> CC --> DD --> EE --> FF --> GG --> HH --> II --> JJ --> K
2.3.4 Python 代码实现
下面给出完整的 Python 代码实现,同时利用三维图形绘制出目标函数的等值面和约束平面(为了直观展示求解结果)。
# 案例三:最小化 f(x,y,z) = (x-1)^2+(y-2)^2+(z-3)^2 在约束 x+y+z=6 下的极值import sympy as sp
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3Ddef case3_lagrange():# 定义符号变量x, y, z, lam = sp.symbols('x y z lam', real=True)# 定义目标函数和约束条件f = (x-1)**2 + (y-2)**2 + (z-3)**2g = x + y + z - 6# 构造拉格朗日函数L = f - lam * g# 求偏导并构造方程组eq1 = sp.Eq(sp.diff(L, x), 0) # 2(x-1) - lam = 0eq2 = sp.Eq(sp.diff(L, y), 0) # 2(y-2) - lam = 0eq3 = sp.Eq(sp.diff(L, z), 0) # 2(z-3) - lam = 0eq4 = sp.Eq(g, 0) # x+y+z-6 = 0# 求解方程组sol = sp.solve([eq1, eq2, eq3, eq4], (x, y, z, lam), dict=True)[0]print("案例三求解结果:")print("x =", sol[x])print("y =", sol[y])print("z =", sol[z])print("lambda =", sol[lam])print("最小值 f =", f.subs({x: sol[x], y: sol[y], z: sol[z]}))# 绘制三维图形:约束平面和目标函数等值面fig = plt.figure(figsize=(10,8))ax = fig.add_subplot(111, projection='3d')# 绘制约束平面 x+y+z=6xx, yy = np.meshgrid(np.linspace(-1, 7, 50), np.linspace(-1, 7, 50))zz = 6 - xx - yyax.plot_surface(xx, yy, zz, alpha=0.3, color='cyan', rstride=1, cstride=1, edgecolor='none', label='Constraint: $x+y+z=6$')# 绘制目标函数等值面 f(x,y,z)=常数# 固定一个等值 f0 = f(x_opt, y_opt, z_opt) + delta,选取不同deltadelta_vals = [2, 5, 10]for delta in delta_vals:f0 = f.subs({x: sol[x], y: sol[y], z: sol[z]}) + delta# 解方程 (x-1)^2+(y-2)^2+(z-3)^2 = f0 得到 z 作为函数# 这里简单绘制 z 面:令 z = 3 + sqrt(f0 - (x-1)^2-(y-2)^2) 和 z = 3 - sqrt(f0 - (x-1)^2-(y-2)^2)X = np.linspace(-1, 7, 100)Y = np.linspace(-1, 7, 100)X, Y = np.meshgrid(X, Y)under_sqrt = f0 - (X-1)**2 - (Y-2)**2under_sqrt[under_sqrt < 0] = 0 # 避免负数Z1 = 3 + np.sqrt(under_sqrt)Z2 = 3 - np.sqrt(under_sqrt)ax.plot_surface(X, Y, Z1, alpha=0.2, cmap='autumn')ax.plot_surface(X, Y, Z2, alpha=0.2, cmap='autumn')# 标出最优点ax.scatter(float(sol[x]), float(sol[y]), float(sol[z]), color='k', s=100, label='Optimal Point')ax.set_xlabel('x')ax.set_ylabel('y')ax.set_zlabel('z')ax.set_title('案例三:目标函数等值面与约束平面')ax.legend()plt.show()if __name__ == '__main__':case3_lagrange()
运行后,可见三维图中以半透明的方式绘制了约束平面和目标函数的不同等值面,并标记了最优点 ( 3 , 2 , 1 ) (3,2,1) (3,2,1)。
三、总结
本文详细介绍了拉格朗日乘数法的基本原理及数学推导,并通过三个不同维度和问题背景的案例,演示了如何利用该方法求解带约束条件的优化问题。主要内容总结如下:
-
理论部分
- 拉格朗日乘数法通过引入辅助变量 λ \lambda λ 将约束条件融入目标函数,从而转化为无约束问题求解。
- 通过构造拉格朗日函数 L ( x , λ ) = f ( x ) − λ g ( x ) L(x,\lambda)=f(x)-\lambda g(x) L(x,λ)=f(x)−λg(x),对所有变量求偏导并令其为零,可以得到候选极值点。
-
算法实现
- 采用符号计算工具 sympy 构造方程组,并利用求解器解出所有变量的值。
- 为了模块化设计,可将拉格朗日乘数法封装为一个类或函数,便于在不同问题中复用。
-
案例分析
- 案例一:二维最优化问题,直观地求解了约束直线上到原点最近的点;
- 案例二:在单位圆上求乘积极值,展示了如何处理非线性约束;
- 案例三:三变量问题中利用单一线性约束求最优解,进一步扩展了拉格朗日乘数法在高维问题中的应用。
-
图形展示
- 通过 Mermaid 语法绘制流程图,有助于理解算法执行的每个步骤;
- 利用 matplotlib 绘制控制曲线与优化曲线(二维等高线、单位圆、三维等值面与约束平面),使得数值解直观展示。
通过这些案例,我们可以看到,拉格朗日乘数法作为一种经典的求解带约束极值问题的方法,不仅在理论上具有严密性,而且在实际工程中有广泛应用。利用 Python 的符号计算和图形绘制能力,可以方便地实现和验证该方法。
四、扩展讨论
4.1 多约束问题
在实际应用中,经常会遇到多约束条件问题。对于目标函数 f ( x 1 , … , x n ) f(x_1,\dots,x_n) f(x1,…,xn) 和约束条件 g i ( x 1 , … , x n ) = 0 , i = 1 , … , m g_i(x_1,\dots,x_n)=0,\; i=1,\dots,m gi(x1,…,xn)=0,i=1,…,m,拉格朗日函数构造为
L ( x 1 , … , x n , λ 1 , … , λ m ) = f ( x 1 , … , x n ) − ∑ i = 1 m λ i g i ( x 1 , … , x n ) . L(x_1,\dots,x_n,\lambda_1,\dots,\lambda_m)=f(x_1,\dots,x_n)-\sum_{i=1}^{m}\lambda_i g_i(x_1,\dots,x_n). L(x1,…,xn,λ1,…,λm)=f(x1,…,xn)−i=1∑mλigi(x1,…,xn).
求解时,只需对所有变量求偏导,然后联立方程组求解即可。扩展后的问题在数值计算上可能会更加复杂,此时可以结合数值优化方法进行求解。
4.2 数值解法与符号求解
在上述案例中,我们使用了 sympy 进行符号求解。但在实际应用中,尤其是当问题较复杂或存在非线性、非凸性时,符号求解可能不适用。此时可以考虑数值优化算法,如牛顿法、梯度下降法或内点法等,并利用 Python 中的 SciPy 库进行求解。同时,可以将拉格朗日乘数法的思想与数值方法相结合,构造罚函数或对偶问题,进而实现求解。
4.3 算法设计规范
在实际开发过程中,代码需要符合良好的设计规范。上文的每个案例均遵循以下原则:
- 模块化设计:将求解过程封装为独立函数,便于测试和复用。
- 变量命名清晰:符号变量、目标函数、约束条件等命名直观。
- 注释充分:每个步骤均有详细说明,便于阅读和维护。
- 图形展示:通过绘图直观展示优化过程和结果,有助于调试和分析。
五、结语
拉格朗日乘数法作为求解约束极值问题的基本方法,其思想简单却极具威力。本文从理论、流程、代码实现、图形展示等多个角度进行了详细讲解。通过三个案例,不仅展示了该方法在二维和三维问题中的应用,还阐述了如何将算法模块化,方便在实际问题中调用。希望读者通过本文能对拉格朗日乘数法有更深入的理解,并能在工程实践中灵活运用这一方法解决实际问题。
在未来的工作中,还可以探索如下方向:
- 将拉格朗日乘数法与其他数值优化算法结合,处理大规模非线性约束问题;
- 开发更完善的 Python 库,将符号与数值计算无缝衔接;
- 利用可视化工具实时展示优化过程,帮助用户调试和理解算法行为。
希望本文能为读者提供系统而全面的参考,欢迎大家提出宝贵意见与建议,共同探讨优化算法在更多领域中的应用与发展。
相关文章:
拉格朗日乘数法算法详解Python实现
目录 一、拉格朗日乘数法算法详解1.1 基本思想1.2 数学推导1.3 算法步骤1.4 算法在编程中的实现 二、案例分析案例一:二维最优化问题——求 f ( x , y ) x 2 y 2 f(x,y)x^2y^2 f(x,y)x2y2 在约束 x y 1 xy1 xy1 下的极值2.1.1 问题描述2.1.2 数学模型构建2.1.…...
ip属地是手机号还是手机位置?一文理清
在数字化和网络化的今天,IP属地这一概念逐渐成为了人们关注的焦点。特别是在社交媒体和在线平台上,IP属地的显示往往让人联想到用户的地理位置。然而,关于IP属地到底与手机号还是手机位置有关,却存在着不少误解和混淆。本文将深入…...
C++常用拷贝和替换算法
算法简介: copy // 容器内指定的元素拷贝到另一容器replace // 将容器内指定范围的旧元素改为新元素replace_if // 容器内指定范围满足条件的元素替换为新元素swap //互换两个容器的元素 1. copy 功能描述: 将容器内指定范围的数据拷贝到另一容器中函…...
vue项目搭建
1.准备工作,按照下面的安装一下脚手架vue-cli node16安装vue-cli时报错:需要node>20(但根本就不是版本问题)-CSDN博客文章浏览阅读157次,点赞4次,收藏2次。这种情况我碰到不下5次了,…...
Java进阶面试八股文
1、Java SE和Java EE区别? Java SE 是 Java 的基础版本,Java EE 是 Java 的高级版本。Java SE 更适合开发桌面应用程序或简单的服务器应用程序,Java EE 更适合开发复杂的企业级应用程序或 Web 应用程序。 2、JVM和JRE和JDK区别?…...
Python Django 嵌入 Grafana Dashboard(随手记)
作为一名网络工程师/运维工程师,现在都在往DevOps的方向发展。其中大家都不可避免的会往自己开发平台的方向发展。 那么如何将自己制作的 Grafana 面板 引入到自己的平台上? 一般来说,大家都会选择Python来作为自己开发的语言,并会…...
[Android] IKTV专享版
[Android] IKTV专享版 链接:https://pan.xunlei.com/s/VOILXXuEd3ASo93c88UW79sxA1?pwd4tsw# 2025年2月最新免费K歌神器!家庭KTV软件,手机平板电视盒子电脑都可用...
阿里 Java 岗个人面经分享(技术三面 + 技术 HR 面):Java 基础 +Spring+JVM+ 并发编程 + 算法 + 缓存
技术一面 20 分钟 1、自我介绍 说了很多遍了,很流畅捡重点介绍完。 2、问我数据结构算法好不好 挺好的(其实心还是有点虚,不过最近刷了很多题也只能壮着胆子充胖子了) 3、找到单链表的三等分点,如果单链表是有环的…...
C++多线程编程——call_once和单例模式
目录 1. 前言 2. call_once和once_flag 3. 后记 3.1 单例类的析构问题 3.2 饿汉式单例模式的线程安全问题 1. 前言 之前在讲解单例模式时,有提到懒汉式单例模式使用了双重检测Double-Checked Locking Pattern (DCLP)来解决多线程的安全访问问题。但是该方法也…...
vue2-为啥data属性是一个函数而不是对象
vue2-为啥data属性是一个函数而不是对象 1. data在vue实例和组件中的表现差异 vue实例的时候,data既可以是一个对象也可以是一个函数 new Vue({data:{//对象name:tom},data(){//函数return{name:tom}} })而在组件中定义data,只能是函数,如…...
Spark--算子执行原理
一、sortByKey SortByKey是一个transformation算子,但是会触发action,因为在sortByKey方法内部,会对每个分区进行采样,构建分区规则(RangePartitioner)。 内部执行流程 1、创建RangePartitioner part&…...
keil 单步调试
一、常见错误分析 warningerror警告错误 不影响编译过程 能够输出Hex文件 无法完成编译 不输出Hex文件 注意的是,warning的信息是要去关注的。 下面的UNCALLED SEGMENT除外 二、单步调试配置 1、在keil中添加单片机型号 本文不详细介绍,如有需要可查看这篇文章:...
html的字符实体和颜色表示
在HTML中,颜色可以通过以下几种方式表示,以下是具体的示例: 1. 十六进制颜色代码 十六进制颜色代码以#开头,后面跟随6个字符,每两个字符分别表示红色、绿色和蓝色的强度。例如: • #FF0000:纯红…...
[数据结构] 线性表和顺序表
目录 线性表 顺序表的实现 顺序表各个方法的实现 boolean isFull() -- 判断数组是否放满 : void add(int data) -- 在数组末尾插入新元素 : void add(int pos,int data) -- 在指定位置插入元素 : boolean contain(int toFind) -- 判断是否包含某个元素 int indexOf(in…...
第12章:基于TransUnet和SwinUnet网络实现的医学图像语义分割:腹部13器官分割(网页推理)
目录 1. 前言 2. TransUnet 和 SwinUnet 3. 腹部多器官分割 4. 训练 5. 推理 6. 项目下载 1. 前言 TransUNet 是一种用于医学图像分割的混合架构,结合了 Transformer 和 U-Net 的优势。它利用 Transformer 的全局上下文建模能力和 U-Net 的精确定位特性&…...
DS图(下)(19)
文章目录 前言一、最短路径的概念二、单源最短路径-Dijkstra算法三、单源最短路径-Bellman-Ford算法四、多源最短路径-Floyd-Warshall算法总结 前言 加油,今天就是图的最后一篇了,撑住!! 今天我们要学的就是最短路径问题&…...
鸿蒙Harmony-Progress组件概述
鸿蒙Harmony-Progress组件概述 1.1Progress组件概述 作用:显示操作或任务的进度,支持线性,环形,刻度等多种样式适用场景:文件上传/下载、任务完成度、系统状态反馈等 2.1基础属性(参考官方文档ÿ…...
流数据库中的RisingWave和Materialize
流数据库(Streaming Database)是一种专门设计用于处理大量实时流数据的数据库,它能够在数据生成时立即进行处理,从而实现实时洞察和分析。RisingWave和Materialize都是这一领域的代表性技术。RisingWave和Materialize都是强大的流…...
【C++】多态详细讲解
本篇来聊聊C面向对象的第三大特性-多态。 1.多态的概念 多态通俗来说就是多种形态。多态分为编译时多态(静态多态)和运⾏时多态(动态多态)。 编译时多态:主要就是我们前⾯讲的函数重载和函数模板,他们传不同类型的参数就可以调⽤不同的函数,通…...
防火墙的安全策略
1.VLAN 2属于办公区;VLAN 3属于生产区,创建时间段 [FW]ip address-set BG type object [FW-object-address-set-BG]address 192.168.1.0 mask 25 [FW]ip address-set SC type object [FW-object-address-set-SC]address 192.168.1.129 mask 25 [FW]ip address-se…...
Android 进程间通信
什么是IPC? Android 进程间通信(IPC,Inter-Process Communication)是Android操作系统中不同进程间交换数据和资源的一种机制。由于Android是多任务操作系统,每个应用通常运行在自己的进程中,以提高安全性和…...
【优先算法】专题——位运算
在讲解位运算之前我们来总结一下常见的位运算 一、常见的位运算 1.基础为运算 << &:有0就是0 >> |:有1就是1 ~ ^:相同为0,相异位1 /无进位相加 2.给一个数 n,确定它的二进制表示…...
深入理解k8s中的容器存储接口(CSI)
CSI出现的原因 K8s原生支持一些存储类型的PV,像iSCSI、NFS等。但这种方式让K8s代码与三方存储厂商代码紧密相连,带来不少麻烦。比如更改存储代码就得更新K8s组件,成本高;存储代码的bug还会影响K8s稳定性;K8s社区维护和…...
ZZNUOJ(C/C++)基础练习1061——1070(详解版)
目录 1061 : 顺序输出各位数字 C语言版 C版 1062 : 最大公约数 C C 1063 : 最大公约与最小公倍 C C 1064 : 加密字符 C C 1065 : 统计数字字符的个数 C C 1066 : 字符分类统计 C C 1067 : 有问题的里程表 C C 1068 : 进制转换 C C C(容器stack…...
ES6 变量解构赋值总结
1. 数组的解构赋值 1.1 基本用法 // 基本数组解构 const [a, b, c] [1, 2, 3]; console.log(a); // 1 console.log(b); // 2 console.log(c); // 3// 跳过某些值 const [x, , y] [1, 2, 3]; console.log(x); // 1 console.log(y); // 3// 解构剩余元素 const [first, ...re…...
机理模型与数据模型融合的方式
机理模型与数据模型的融合旨在结合两者的优势,以提供更准确、可靠的预测和决策支持。以下是几种常见的融合方式及其示例: 1. 特征增强(Feature Augmentation) 描述:将由机理模型计算得到的结果作为额外特征加入到数据…...
高效 MyBatis SQL 写法一
高效 MyBatis SQL 写法一 前言 MyBatis 作为一款优秀的持久层框架,极大地简化了数据库操作。 然而,在实际开发中,XML 配置的编写仍然可能显得繁琐。 本文将分享一些 MyBatis 动态 SQL 的优质写法,帮助开发者提升效率并减少错误…...
vue3中的ref相关的api及用法
在 Vue 3 中,ref 相关的 API 主要用于管理响应式数据。以下是 ref 相关的 API 及其用法: 1. ref ref 用于创建响应式的基本数据类型或对象。 用法示例: <script setup> import { ref } from vue;const count ref(0);const incremen…...
3 卷积神经网络CNN
1 Image Classification (Neuron Version) – 1.1 Observation 1 1.2 Observation 2 如果不同的receptive field需要相同功能的neuron,可以使这些neuron共享参数 1.3 Benefit of Convolutional Layer 2 Image Classification (Filter Version) 不用担心filter大小…...
CSV数据分析智能工具(基于OpenAI API和streamlit)
utils.py: from langchain_openai import ChatOpenAI from langchain_experimental.agents.agent_toolkits import create_csv_agent import jsonPROMPT_TEMPLATE """你是一位数据分析助手,你的回应内容取决于用户的请求内容。1. 对于文…...
解决php8.3无法加载curl扩展
把它的值更改为扩展存在的目录的绝对路径(扩展存在的目录为有php_xxx.dll存在的目录) extension_dir "e:\serv\php83\ext" 然后从php根目录复制 libssh2.dll 和 libcrypto-*.dll 和 libssl-*.dll 到Apache根目录下的bin目录 重启apache服务即可...
拍照对比,X70 PRO与X90 PRO+的细节差异
以下是局部截图(上X70P下X90PP) 对比1 这里看不出差异。 对比2 X90PP的字明显更清楚。 对比3 中下的字,X90PP显然更清楚。...
《MPRnet》学习笔记
paper:2102.02808 GitHub:swz30/MPRNet: [CVPR 2021] Multi-Stage Progressive Image Restoration. SOTA results for Image deblurring, deraining, and denoising. 目录 摘要 1、介绍 2、相关工作 2.1 单阶段方法 2.2 多阶段方法 2.3 注意力机…...
机器学习-线性回归(参数估计之结构风险最小化)
前面我们已经了解过关于机器学习中的结构风险最小化准则,包括L1 正则化(Lasso)、L2 正则化(Ridge)、Elastic Net,现在我们结合线性回归的场景,来了解一下线性回归的结构风险最小化,通…...
C++11详解(二) -- 引用折叠和完美转发
文章目录 2. 右值引用和移动语义2.6 类型分类(实践中没什么用)2.7 引用折叠2.8 完美转发2.9 引用折叠和完美转发的实例 2. 右值引用和移动语义 2.6 类型分类(实践中没什么用) C11以后,进一步对类型进行了划分&#x…...
深度学习系列--01.入门
一.深度学习概念 深度学习(Deep Learning)是机器学习的分支,是指使用多层的神经网络进行机器学习的一种手法抖音百科。它学习样本数据的内在规律和表示层次,最终目标是让机器能够像人一样具有分析学习能力,能够识别文字…...
熵采样在分类任务中的应用
熵采样在分类任务中的应用 在机器学习的分类任务里,数据的标注成本常常制约着模型性能的提升。主动学习中的熵采样策略,为解决这一难题提供了新的思路。本文将带你深入了解熵采样在分类任务中的原理、应用及优势。 一、熵采样的原理(优化版) 熵,源于信息论,是对不确定…...
vite配置之---依赖优化选项
vite optimizeDeps 配置项主要在 开发环境 中对依赖项发挥作用 optimizeDeps.entries vite optimizeDeps.entries 是 Vite 配置中的一个选项,用来指定要优化的入口文件。这在开发环境中尤其有用,因为它告诉 Vite 需要预构建哪些文件,以便加速…...
Shell基础:中括号的使用
在Shell脚本中,中括号([ ... ] 和 [[ ... ]])是一种常见的条件测试结构。它们用于进行文件类型检查、值比较以及逻辑判断。通过了解它们的不同特点和用法,能够帮助你编写更加高效、安全且易读的脚本。本文将详细介绍Shell中单中括…...
oracle ORA-27054报错处理
现象 在oracle执行expdp,rman备份,xtts的时候,由于没有足够的本地空间,只能使用到NFS的文件系统但有时候会出现如下报错 ORA-27054: NFS file system where the file is created or resides is not mounted with correct options根据提示信…...
SpringCloud速通教程
视频地址 文档地址 3. SpringCloud - 快速通关...
MapReduce分区
目录 1. MapReduce分区1.1 哈希分区1.2 自定义分区 2. 成绩分组2.1 Map2.2 Partition2.3 Reduce 3. 代码和结果3.1 pom.xml中依赖配置3.2 工具类util3.3 GroupScores3.4 结果 参考 本文引用的Apache Hadoop源代码基于Apache许可证 2.0,详情请参阅 Apache许可证2.0。…...
python算法和数据结构刷题[3]:哈希表、滑动窗口、双指针、回溯算法、贪心算法
回溯算法 「所有可能的结果」,而不是「结果的个数」,一般情况下,我们就知道需要暴力搜索所有的可行解了,可以用「回溯法」。 回溯算法关键在于:不合适就退回上一步。在回溯算法中,递归用于深入到所有可能的分支&…...
JDK 中 NIO 框架设计与实现:深入剖析及实战样例
一、引言 在 Java 的发展历程中,I/O(Input/Output)操作一直是构建高效、稳定应用程序的关键环节。传统的 Java I/O 操作基于流(Stream)的方式,虽然简单易用,但在面对高并发、大规模数据传输等场…...
基于springboot校园点歌系统
基于Spring Boot的校园点歌系统是一种专为校园场景设计的音乐点播平台,它能够丰富学生的校园生活,提升学生的娱乐体验。以下是对该系统的详细介绍: 一、系统背景与意义 在校园环境中,学生们对于音乐有着浓厚的兴趣,传…...
Spring 核心技术解析【纯干货版】- IX:Spring 数据访问模块 Spring-Jdbc 模块精讲
在现代企业级应用中,数据访问层的稳定性和高效性至关重要。为了简化和优化数据库操作,Spring Framework 提供了 Spring-JDBC 模块,旨在通过高度封装的 JDBC 操作,简化开发者的编码负担,减少冗余代码,同时提…...
React开发中箭头函数返回值陷阱的深度解析
React开发中箭头函数返回值陷阱的深度解析 一、箭头函数的隐式返回机制:简洁背后的规则二、块函数体中的显式返回要求:容易被忽视的细节三、真实场景下的案例分析案例1:忘记return导致组件渲染失败案例2:异步操作中的返回值陷阱 四…...
线程同步时定义 std::mutex 为什么要在前面添加 mutable 关键字
在C中,mutable关键字用于修饰类的成员变量,表示即使在一个const对象中,该成员变量也可以被修改。对于mutex这样的同步原语,使用mutable是必要的,原因如下: 1. 为什么需要 mutable? mutex通常用…...
【多线程】线程池核心数到底如何配置?
🥰🥰🥰来都来了,不妨点个关注叭! 👉博客主页:欢迎各位大佬!👈 文章目录 1. 前置回顾2. 动态线程池2.1 JMX 的介绍2.1.1 MBeans 介绍 2.2 使用 JMX jconsole 实现动态修改线程池2.2.…...
Linux find 命令 | grep 命令 | 查找 / 列出文件或目录路径 | 示例
注:本文为 “Linux find 命令 | grep 命令使用” 相关文章合辑。 未整理去重。 如何在 Linux 中查找文件 作者: Lewis Cowles 译者: LCTT geekpi | 2018-04-28 07:09 使用简单的命令在 Linux 下基于类型、内容等快速查找文件。 如果你是 W…...