python与数学建模(一)——线性规划
python与数学建模(一)——线性与非线性规划
数学建模国赛刚刚结束,博主想做一个有关使用python进行数学建模的专题。python作为一个简单高效的语言,虽然执行速度慢,不过能够快速开发。相比matlab, python更加轻量,集成度更高,使用在数学建模上完全可以胜任。
一、什么是线性规划?
我们不阐述具体的概念,可以将由以下形式的优化问题看成线性规划问题:
m
i
n
∑
j
=
1
n
c
j
x
j
s
.
t
.
∑
j
=
1
n
a
i
j
x
j
=
b
i
,
i
=
1
,
.
.
.
,
m
,
x
j
>
=
0
,
i
=
1
,
.
.
.
,
m
,
min\sum_{j=1}^{n}c_{j}x_{j}\\s.t.\sum_{j=1}^{n}a_{ij}x_{j}=b_{i}, i=1,...,m,\\x_{j}>=0,i=1,...,m,
minj=1∑ncjxjs.t.j=1∑naijxj=bi,i=1,...,m,xj>=0,i=1,...,m,
或者我们可以用矩阵表示:
m
i
n
cx
s
.
t
.
Ax
=
b
,
x
>
=
0
,
min\quad\textbf{cx}\\ s.t.\quad\textbf{Ax}=\textbf{b},\\ \quad\quad\quad\textbf{x}>=\textbf{0},
mincxs.t.Ax=b,x>=0,
很多时候,我们遇到的线性规划或者是非线性规划问题的约束条件不都是等式,需要加入松弛变量转化为标准形式。此处不深入讨论,我们看下面的代码求解说明,仅考虑最简单的情形。
二、python求解线性规划问题
假设我们要最小化目标函数f=2x+y
,满足以下约束条件:
x >= 0
y >= 0
x + y <= 8
2x + y <= 12
from scipy.optimize import linprog
# 定义目标函数的系数
c = [2, 1]
# 定义不等式约束的系数矩阵
A = [
[-1, 0],
[0, -1],
[1, 1],
[2, 1]
]
# 定义不等式约束的上界
b = [0, 0, 8, 12]
# 求解线性规划问题
res = linprog(c, A_ub=A, b_ub=b)
if res.success:
print("最小值为:", res.fun)
print("最优解为: x =", res.x)
else:
print("无法找到最优解。")
在这个例子中,c
是目标函数的系数,A
是不等式约束的系数矩阵,b
是不等式约束的上界。linprog
函数将会返回一个OptimizeResult
对象,其中fun
表示目标函数的最小值,x
表示最优解。
输出结果
# 最小值为: 0.0
# 最优解为: x = [0. 0.]
三、python求解非线性规划
求解非线性规划,转化为线性规划问题即可。
假设我们要最小化目标函数 f = x^2 + y^2
,同时满足以下约束条件:
-
x >= 1
-
y >= 1
-
x + y <= 10
-
x^2+y^2 = 5
from scipy.optimize import minimize # 定义目标函数 def objective_function(x): return x[0]**2 + x[1]**2 # 定义约束条件 def constraint1(x): return x[0] - 1 def constraint2(x): return x[1] - 1 def constraint3(x): return 10 - x[0] - x[1] # 定义等式约束 def eq_constraint(x): return x[0]**2 + x[1]**2 - 5 # 定义初始猜测点 x0 = [0, 0] # 定义约束条件,ineq表示大于0的不等式等式约束,eq表示等式约束 constraints = [{'type': 'ineq', 'fun': constraint1}, {'type': 'ineq', 'fun': constraint2}, {'type': 'ineq', 'fun': constraint3}, {'type': 'eq', 'fun': eq_constraint}] # 求解非线性规划问题 res = minimize(objective_function, x0, constraints=constraints) if res.success: print("最小值为:", res.fun) print("最优解为: x =", res.x) else: print("无法找到最优解。")
-
ineq
: 表示不等式约束,即将约束函数的结果限制在非负区间。对于函数fun(x)
,如果约束条件为fun(x) >= 0
,则使用{'type': 'ineq', 'fun': fun}
来表示。如果约束条件为fun(x) <= 0
,则需要在定义约束函数时取反:fun(x) <= 0
等价于-fun(x) >= 0
。 -
eq
: 表示等式约束,即将约束函数的结果限制为一个常数。对于函数fun(x)
,如果约束条件为fun(x) = 0
,则使用{'type': 'eq', 'fun': fun}
来表示。
-
等式约束,即将约束函数的结果限制为一个常数。对于函数fun(x)
,如果约束条件为fun(x) = 0
,则使用{'type': 'eq', 'fun': fun}
来表示。
输出结果
# 无法找到最优解。