非线性规划
原创 发布时间:2026-06-15 | 更新时间:2026-06-15

现实生活中,有些问题是非线性的,这就是非线性规划(Nonlinear Programming)

(关于基础概念和符号定义请看前文线性规划(Linear Programming))

现实例子#

老王是一名农夫,他想紧靠着屋墙围出一块长方形的地方养鸡。

他想围出尽可能大的地方,而手头上只有 8 米的篱笆,靠墙一侧不需要围栏。

请问他该如何设计长方形的边长才能围出最大面积的围栏?

Wall x y y

数学表达#

问题拆解如下:

  • 决策变量:设长方形靠墙的一边为长,长为 $x$ 米,宽为 $y$ 米,因为面积为 $xy$,所求就是 $argmax_{x,y}\left(xy\right)$

  • 目标函数:求面积的最大值(max),即 $max(xy)$

  • 约束条件:$x+2y=8$,$x \gt 0$,$y \gt 0$

完整的数学表达为:$argmax_{x,y} \left(xy\right) \quad s.t. \quad x+2y=8, x>0, y>0$

因为目标函数为 $xy$,次数高于1,所以是非线性规划

数学求解#

整理约束条件 $x+2y=8$ 得

\[ x=8-2y \]

代入目标函数得

\[ xy=(8-2y)y=-2y^2+8y \]

函数 $f(y)=-2y^2+8y$ 的图像是一条开口向下的抛物线

-10 -9 -8 -7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 7 8 9 10 y -10 -9 -8 -7 -6 -5 -4 -3 -2 -1 1 2 3 4 5 6 7 8 9 10 f(y) (2,8)

求这个函数的导数并让其等于 0 即可计算出抛物线的最值(因为开口向下,所以一定是最大值)

$f^’(y)=-2 \times 2y+8=0$ 得 $y=2$

当 $y=2$ 时,

$f(y) = -2y^2 + 8y = 8$

$x=8-2y=4$

也就是当长方形的长为 4 米,宽为 2 米时,鸡圈可达到最大面积 8 平方米。

程序求解#

方法一:利用 Scipy#

Scipy 有一个 minimize 模块,可以很方便计算出非线性规划的最优解

# pip install scipy
from scipy.optimize import minimize
import numpy as np

# 最小化目标函数:我们要最大化 xy,等价于最小化 -xy
def objective(x):
    return - (x[0] * x[1])  # x[0]=x, x[1]=y

# 等式约束:x + 2y = 8
def constraint(x):
    return x[0] + 2 * x[1] - 8

# 约束条件定义
cons = ({'type': 'eq', 'fun': constraint})

# 变量边界:x>0, y>0
bounds = ((1e-6, None), (1e-6, None))  # 用极小值代替严格>0

# 初始值(随便给一个满足约束的点)
x0 = np.array([2, 3])

# 求解
result = minimize(objective, x0, method='SLSQP', bounds=bounds, constraints=cons)

# 输出结果
print("求解状态:", result.success)
print("最优解 x =", round(result.x[0], 4))
print("最优解 y =", round(result.x[1], 4))
print("最大值 xy =", round(-result.fun, 4))

输出

求解状态: True
最优解 x = 4.0
最优解 y = 2.0
最大值 xy = 8.0

方法一:利用 CVXPY#

通过 CVXPY 库也可以计算这种非线性规划问题,以更直观的方式通过表达式描述问题

# pip install cvxpy
import cvxpy as cp

# 定义变量
x = cp.Variable(nonneg=True)
y = cp.Variable(nonneg=True)

# 目标函数
objective = cp.Maximize(x * y)

# 约束
constraints = [x + 2*y == 8]

# 构建问题
prob = cp.Problem(objective, constraints)

# 必须指定 solver=cp.SCS 且 qcp=True
prob.solve(qcp=True, solver=cp.SCS)

# 输出结果
print("最优解 x =", round(x.value, 4))
print("最优解 y =", round(y.value, 4))
print("最大值 xy =", round(prob.value, 4))

输出

最优解 x = 4.0
最优解 y = 2.0
最大值 xy = 8.0

techunder_official 关注「Techunder技术人文」微信公众号,获取最新文章通知

版权所有 © 2026 Techunder (Guanhua Liu) | Copyright All Rights Reserved | 电子邮箱 Email:techunder@163.com

粤公网安备44060502004200号   粤ICP备2026007783号