0%

【数学建模笔记 03】数学建模的非线性规划

03. 非线性规划

定义

如果目标函数或约束条件中包含非线性函数,就称这种规划问题为非线性规划问题。

非线性规划目前还没有适于各种问题的一般算法。

非线性规划模型描述如:

其中 ,而 都是实值函数。

一般非线性规划只能得到局部最优解,不能保证是全局最优解。

无约束非线性规划求解

具有连续的一阶偏导数,且 ​ 是无约束问题的局部极小点,则 其中 表示 的梯度。

具有对各个变量的二阶偏导数,称矩阵 为函数的黑塞矩阵,记

因此,只要找到 ,满足 ,且 为正定矩阵,则 为无约束优化问题的局部最优解。

找到 的具体方法有最速降线法、牛顿法等。

有约束非线性规划求解

有等式约束非线性规划的 Lagrange 乘数法

对于只有等式约束的非线性规划问题:

设函数 在可行点 的某个邻域 ​ 内可微,向量组 线性无关,令 其中

是局部最优解,则有 使得 ,即 从而将有约束条件转化为无约束条件。

有约束非线性规划的罚函数法

构造带参数的所谓增广目标函数,从而把有约束非线性规划问题转化为一系列无约束非线性规划问题。

增广目标函数通常由两部分组成:

  • 原问题的目标函数;
  • 约束条件构造出的惩罚项。

对于外点法,增广目标函数形式如下: 其中 M 是一个较大的正数。

从而转化为无约束问题: 罚函数法的计算精度可能较差。

Python 代码

利用 scipy、cvxopt、cvxpy 包,可以实现非线性规划求解。

scipy 求解

对于问题:

使用 scipy 求解,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# %%

import numpy as np
from scipy.optimize import minimize

# %%

def obj(x):
x1,x2,x3 = x
return (2+x1)/(1+x2)-3*x1+4*x3

bound = [(.1, .9) for _ in range(3)]
res = minimize(obj, np.ones(3), bounds=bound)

# %%

print('best obj =', res.fun)
print('success =', res.success)
print('best x =', res.x)

输出如下:

1
2
3
best obj = -0.7736842105263159
success = True
best x = [0.9 0.9 0.1]

cvxpy 求解

对于问题:

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# %%

import numpy as np
import cvxpy as cp

# %%

# 目标函数的平方项
c1 = np.array([1, 1, 3, 4, 2])

# 目标函数的一次项
c2 = np.array([-8, -2, -3, -1, -2])

# 约束项
a = np.array([[1, 1, 1, 1, 1],
[1, 2, 2, 1, 6],
[2, 1, 6, 0, 0],
[0, 0, 1, 1, 5]])
b = np.array([400, 800, 200, 200])

# 决策变量
x = cp.Variable(5, integer=True)

# 目标函数
obj = cp.Minimize(c1 @ x**2 + c2 @ x)

# 约束
con = [0 <= x, x <= 99, a@x <= b]

# 问题模型
prob = cp.Problem(obj, con)
prob.solve(solver='CPLEX')

# %%

print('best z =', prob.value)
print('best x =', x.value)

输出如下:

1
2
best z = -17.0
best x = [4. 1. 0. 0. 0.]