文章目录
前言
通过模型算法,熟练对Matlab和python的应用。
学习视频链接:
https://www.bilibili.com/video/BV1EK41187QF?p=19&vd_source=67471d3a1b4f517b7a7964093e62f7e6
一、线性规划模型
线性规划(Linear Programming, LP)是一种数学优化方法,旨在找到一个线性目标函数的最大值或最小值,同时满足一组线性约束条件。
1.应用场景
- XXX共有多少多少,怎么样去安排或者分配,使……最大/最小/最优
- 若要生产两种机床,利润分别为XXX,机器有不同的损耗费用,不同的工作时间,怎么安排生产能够让总利润最大呢?
- 若总资产是A,有 n 种资产可以进行配置,每种资产配置平均收益率XXX,风险损失率XXX,手续费XXX,怎么组合投资使得收益最大,风险最小?
- 若商品有 n 个产地和 p 个销售地,需要从产地运输到销售地,各产地的产量是XXX,各销售地的需求量是XXX,不同产地运输到不同销售地的运价是XXX,怎么调运才能使总运费最省?
- 不同类型的车辆承载量不同,工地各点之间需安排车辆运输,工地里有多条线路,满足用工需求的情况下,怎么安排车辆能使车次安排最合理?
2.线性规划模型的三要素
决策变量:问题中要确定的未知量,用于表明规划问题中的用数量表示的方案、措施等,可由决策者决定和控制;
目标函数:决策变量的函数,优化目标通常是求该函数的最大值或最小值;
约束条件: 决策变量的取值所受到的约束和限制条件,通常用含有决策变量的等式或不等式表示。
3.线性规划模型建立步骤
从实际问题中建立数学模型一般有以下三个步骤:
1.根据影响所要达到目的的因素找到决策变量
2.由决策变量和所在达到目的之间的函数关系确定目标函数
3.由决策变量所受的限制条件确定决策变量所要满足的约束条件
4.线性规划的表现形式
-
一般形式/代数形式
m a x ( 或 ( m i n ) ) z = c 1 x 1 + c 2 x 2 + ⋯ + c n x n , s . t . { a 11 x 1 + a 12 x 2 + ⋯ + a 1 n x n ≤ ( 或=, ≥ ) b 1 , a 21 x 1 + a 22 x 2 + ⋯ + a 2 n x n ≤ ( 或=, ≥ ) b 2 , ⋮ a m 1 x 1 + a m 2 x 2 + ⋯ + a m n x n ≤ ( 或=, ≥ ) b m , x 1 , x 2 , ⋯ , x n ≥ 0. {max(\text{或}(min))}z=c_1x_1+c_2x_2+\cdots+c_nx_n,\\[1em]\\{\mathrm{s.t.}\begin{cases}a_{11}x_1+a_{12}x_2+\cdots+a_{1n}x_n\leq(\text{或=,}\geq)b_1,\\a_{21}x_1+a_{22}x_2+\cdots+a_{2n}x_n\leq(\text{或=,}\geq)b_2,\\\vdots\\a_{m1}x_1+a_{m2}x_2+\cdots+a_{mn}x_n\leq(\text{或=,}\geq)b_m,\\x_1,x_2,\cdots,x_n\geq0.\end{cases}} max(或(min))z=c1x1+c2x2+⋯+cnxn,s.t.⎩ ⎨ ⎧a11x1+a12x2+⋯+a1nxn≤(或=,≥)b1,a21x1+a22x2+⋯+a2nxn≤(或=,≥)b2,⋮am1x1+am2x2+⋯+amnxn≤(或=,≥)bm,x1,x2,⋯,xn≥0. -
简写形式: m a x ( 或 m i n ) z = ∑ j = 1 n c j x j , s.t. { ∑ j = 1 n a i j x j ≤ ( 或 = , ≥ ) b i , i = 1 , 2 , ⋯ , m , x j ≥ 0 , j = 1 , 2 , ⋯ , n . \begin{aligned}&max(\text{或}min) z=\sum_{j=1}^{n}c_{j}x_{j},\\&\text{s.t.}\begin{cases}\sum_{j=1}^{n}a_{ij}x_{j}\leq(\text{或}=,\geq)b_{i}, i=1,2,\cdots,m,\\x_{j}\geq0, j=1,2,\cdots,n.\end{cases}\end{aligned} max(或min)z=j=1∑ncjxj,s.t.{∑j=1naijxj≤(或=,≥)bi,i=1,2,⋯,m,xj≥0,j=1,2,⋯,n.
-
矩阵表现形式:
m a x ( 或 m i n ) z = c T x , s . t . { A x ≤ ( 或 = , ≥ ) b , x ≥ 0. max(\text{或}min) z=c^Tx,\\{s.t.\begin{cases}Ax\leq(\text{或}=,\geq)b,\\x\geq0.\end{cases}} max(或min)z=cTx,s.t.{Ax≤(或=,≥)b,x≥0.
c = [ c 1 , c 2 , … , c n ] T c=[c_{1} ,c_{2} ,\dots,c_{n}]^{T} c=[c1,c2,…,cn]T —— 目标函数的系数向量,即价值向量;
x = [ x 1 , x 2 , … , x n ] T x=[x_{1} ,x_{2} ,\dots,x_{n}]^{T} x=[x1,x2,…,xn]T —— 决策向量;
A = ( a i j ) m × n A=\left(a_{ij}\right)_{m\times n} A=(aij)m×n —— 约束方程组的系数矩阵;
b = [ b 1 , b 2 , . . . , b m ] T b=[b_1 ,b_2 ,... ,b_m]^T b=[b1,b2,...,bm]T —— 约束方程组的常数向量。
5.线性规划的模型特点
- 要解决的问题是优化类的(即在有限的资源条件下,获取最大的收益)
- 目标函数和约束条件都是决策变量的线性函数,即不存在 x 2 , e x , 1 x , sin x , log 2 x x^{2} ,e^{x} ,\frac{1}{x} ,\sin x ,\log_{2}x x2,ex,x1,sinx,log2x等
- 线性规划模型:在一组线性约束条件下,求线性目标函数的最大值或最小值
二、例题(1998年国赛A题)
- 市场上有 n 种资产(如股票、债券、……) s i ( i = 1 , 2 , … , n ) s_i (\mathrm{i=1,2,\ldots,n}) si(i=1,2,…,n) 供投资者选择,某公司有数额为 M 的一笔相当大的资金可用作一个时期的投资。公司财务分析人员对这 n 种资产进行了评估,估算出在这一时期内购买资产 s i s_i si 的平均收益率为 r i r_i ri,并预测出购买 s i s_i si 的风险损失率为 q i q_i qi 。考虑到投资越分散,总的风险越小,公司确定,当用这笔资金购买若干种资产时,总体风险可用所投资的 s i s_i si 中最大的一个风险来度量。
- 购买 s i s_i si 要付交易费,费率为 p i p_i pi ,并且当购买额不超过给定值 u i u_i ui 时,交易费按购买 u i u_i ui 计算(不买当然无须付费)。另外,假定同期银行存款利率是 r 0 ( r 0 = 5 % ) r_0(r_0=5\%) r0(r0=5%) ,且既无交易费又无风险。
- 已知 n = 4 时的相关数据如表所示。
各变量含义:
- 资产(如股票、债券、……银行): 共 n + 1 种
- 总投资资金: M
- 不同资产: s i ( i = 1 , 2 , … , n ) s_i (\mathrm{i=1,2,\ldots,n}) si(i=1,2,…,n)
- 平均收益率: r i r_i ri
- 风险损失率为: q i q_i qi
- 付交易费的费率为: p i p_i pi
- 购买额的分界线: u i u_i ui (不超过给定值 u i u_i ui 时,交易费按购买 u i u_i ui ,超过时交 p i p_i pi 的费率。
问题分析:
- 决策变量:投资不同项目 s i s_i si 的购买额为 x i ( i = 1 , 2 , … , n ) x_i (\mathrm{i=1,2,\ldots,n}) xi(i=1,2,…,n)
- 目标函数: 净收益 Q 尽可能大、总风险尽可能小
- 约束条件:总资金 M 有限,每一笔投资都是非负数
- 且已知,目标函数和约束条件都是决策变量的线性函数
模型假设:
- 可供投资的资金数额 M 相当大
- 投资越分散,总的风险越小,总体风险可用所投资的 s i s_i si 中最大的一个风险来度量
- 可供选择的 n+1 种资产(含银行存款)之间是相互独立的
- 每种资产可购买的数量为任意值
- 在当前投资周期内, r i , q i , p i , u i ( i = 1 , 2 , … , n ) r_i,q_i, p_i, u_i(\mathrm{i=1,2,\ldots,n}) ri,qi,pi,ui(i=1,2,…,n) 固定不变
- 不考虑在资产交易过程中产生的其他费用,如股票交易印花税等
- 由于投资数额 M 相当大,而题目设定的定额 u i u_i ui 相对 M 很小, p i , u i p_i, u_i pi,ui 更小,因此假设每一笔交易 x i x_i xi 都大于对应定额 u i u_i ui
模型建立:
- 总体风险可用所投资的 s i s_i si 中最大的一个风险来度量,即 m a x { q i x i ∣ i = 1 , 2 , ⋯ , n } max\{q_{i}x_{i}|i=1,2,\cdots,n\} max{qixi∣i=1,2,⋯,n}。
- 购买 s i ( i = 1 , 2 , … , n ) s_i (\mathrm{i=1,2,\ldots,n}) si(i=1,2,…,n) 所付交易费本来是一个分段函数,但假设中已经假设每一笔交易 x i x_i xi 都大于对应定额 u i u_i ui,所以交易费 = p i x i p_ix_i pixi,这样购买 s i s_i si 的净收益可以简化为 ( r i − p i ) x i (r_i - p_i) x_i (ri−pi)xi 。
目标函数为: { m a x ∑ i = 0 n ( r i − p i ) x i , m i n { m a x 1 ≤ i ≤ n { q i x i } } {\begin{cases}max\sum_{i=0}^n(r_i-p_i)x_i,\\[0.em]\\min\{max_{1\leq i\leq n}\{q_ix_i\}\}&\end{cases}} ⎩ ⎨ ⎧max∑i=0n(ri−pi)xi,min{max1≤i≤n{qixi}} 约束条件为: { ∑ i = 0 n ( 1 + p i ) x i = M , x i ≥ 0 , i = 0 , 1 , ⋯ , n . \left.\left\{\begin{matrix}{\sum_{i=0}^{n}(1+p_{i})x_{i}=M,}\\[0.em]\\{x_{i}\geq0,\quad i=0,1,\cdots,n.}\\\end{matrix}\right.\right. ⎩ ⎨ ⎧∑i=0n(1+pi)xi=M,xi≥0,i=0,1,⋯,n.
这是一个多目标规划模型!
模型简化:
- 在实际投资中,投资者承受风险的程度不一样,若给定风险一个界限 a ,使最大的一个风险 q i x i M ≤ a \frac{q_{i}x_{i}}{M}\leq a Mqixi≤a 可找到相应的投资方案。这样把多目标规划变成一个目标的线性规划。
- 这里将目标函数 m i n { m a x 1 ≤ i ≤ n { q i x i } } min\{max_{1\leq i\leq n}\{q_ix_i\}\} min{max1≤i≤n{qixi}} 转化为了约束条件: q i x i M ≤ a \frac{q_{i}x_{i}}{M}\leq a Mqixi≤a (总体风险小于某个常数)
简化后的模型:
m
a
x
∑
i
=
0
n
(
r
i
−
p
i
)
x
i
s
.
t
.
{
q
i
x
i
M
≤
a
,
i
=
1
,
2
,
⋯
,
n
,
∑
i
=
0
n
(
1
+
p
i
)
x
i
=
M
,
x
i
≥
0
,
i
=
0
,
1
,
⋯
,
n
.
max\sum_{i=0}^n(r_i-p_i)x_i\quad\mathrm{s.t.}\begin{cases}\frac{q_ix_i}{M}\leq a,i=1,2,\cdots,n,\\\sum_{i=0}^n(1+p_i)x_i=M,\\x_i\geq0,\quad i=0,1,\cdots,n.\end{cases}
maxi=0∑n(ri−pi)xis.t.⎩
⎨
⎧Mqixi≤a,i=1,2,⋯,n,∑i=0n(1+pi)xi=M,xi≥0,i=0,1,⋯,n.
三、代码实现----Matlab
1.Matlab 的 linprog 函数
标准形式:
[
x
,
f
v
a
l
]
=
l
i
n
p
r
o
g
(
f
,
A
,
b
,
A
e
q
,
b
e
q
,
l
b
,
u
b
)
min
x
f
T
x
,
s
.
t
.
{
A
⋅
x
≤
b
,
A
e
q
⋅
x
=
b
e
q
,
l
b
≤
x
≤
u
b
.
[x,fval]=linprog(f ,A ,b ,Aeq ,beq ,lb ,ub)\\\\[1em]\min\limits_xf^Tx ,\\[1em]\\s.t.\begin{cases}A\cdot x\leq b,\\Aeq\cdot x=beq,\\lb\leq x\leq ub.\end{cases}
[x,fval]=linprog(f,A,b,Aeq,beq,lb,ub)xminfTx,s.t.⎩
⎨
⎧A⋅x≤b,Aeq⋅x=beq,lb≤x≤ub.
- f — — 目标函数的系数向量(必须是求最小值形式下的)
- A,b — — 不等式约束条件的变量系数矩阵和常数项矩阵(必须是 ≤ 形式)
- Aeq,beq — — 等式约束条件的系数矩阵和常数项矩阵
- lb,ub — — 决策变量的最小取值和最大取值
- x 是返回的最优解的变量取值, fval 返回目标函数的最优值
- 注意:
要调用 linprog 函数,变量必须是标准形式,即目标函数是求最小值,约束条件都是小于等于号或等号如果不满足标准形式,我们可以用同乘 “-” 变号来继续求解
由简化后的模型可得:
m
i
n
f
=
[
0.05
,
0.27
,
0.19
,
0.055
,
0.185
]
⋅
[
x
0
,
x
1
,
x
2
,
x
3
,
x
4
]
T
s.t.
{
x
0
+
1.01
x
1
+
1.02
x
2
+
1.045
x
3
+
1.065
x
4
=
M
,
0.025
x
1
≤
a
M
,
0.015
x
2
≤
a
M
,
0.055
x
3
≤
a
M
,
0.026
x
4
≤
a
M
,
x
i
≥
0
(
i
=
0
,
1
,
⋯
,
4
)
.
\begin{aligned}&min\quad f=[0.05,0.27, 0.19, 0.055, 0.185]\cdot[x_0,x_1,x_2,x_3,x_4]^T\\[0.0em]\\&\quad\text{s.t.}\begin{cases}x_0+1.01x_1+1.02x_2+1.045x_3+1.065x_4=M,\\0.025x_1\leq aM,\\0.015x_2\leq aM,\\0.055x_3\leq aM,\\0.026x_4\leq aM,\\x_i\geq0~(i=0,1,\cdots,4).\end{cases}\end{aligned}
minf=[0.05,0.27,0.19,0.055,0.185]⋅[x0,x1,x2,x3,x4]Ts.t.⎩
⎨
⎧x0+1.01x1+1.02x2+1.045x3+1.065x4=M,0.025x1≤aM,0.015x2≤aM,0.055x3≤aM,0.026x4≤aM,xi≥0 (i=0,1,⋯,4).
2.Matlab 代码
clear;clc;
f = [-0.05 -0.27 -0.19 -0.185 -0.185];
A = [zeros(4,1),diag([0.025 0.015 0.055 0.026])]; % 将 4*1 的 0 向量,与对角矩阵拼在一起作为系数矩阵A
% 假设可供投资的资金数额M是一万元
M = 1;
Aeq = [1 1.01 1.02 1.045 1.065];
beq = M;
lb = zeros(5,1);
a = (0:0.001:0.05); % a的范围时0-0.05,步长为0.001
Q = zeros(1,length(a));
for i = 1 : length(a)
b = a(i) * ones(4,1);
[x,y] = linprog(f,A,b,Aeq,beq,lb);
Q(i) = -y;
end
plot(a,Q,'-r')
xlabel('风险率')
ylabel('最大收益')
运行结果:
- 风险 a 与收益 Q 之间的关系见图。从图中可以看出:
1)风险不超过2.5%时,风险大,收益也大
2)在 a=0.006 附近有一个转折点,在这一点左边,风险增加很少时,利润增长很快。在这一点右边,风险增加很大时,利润增长很缓慢,所以对于风险和收益没有特殊偏好的投资者来说,应该选择曲线的转折点作为最优投资组合,大约是a=0.6%,Q=2000,所对应投资方案为:
风险度 a=0.006 ,收益 Q=2019 元; x 0 = 0 x_0=0 x0=0 元, x 1 = 2400 x_1=2400 x1=2400 元, x 2 = 4000 x_2=4000 x2=4000 元, x 3 = 1091 x_3=1091 x3=1091 元, x 4 = 2212 x_4=2212 x4=2212 元
四、代码实现----python
1.python 的 linprog 函数
r
e
s
u
l
t
=
l
i
n
p
r
o
g
(
c
,
A
_
u
b
,
b
_
u
b
,
A
_
e
q
,
b
_
e
q
,
b
o
u
n
d
s
,
m
e
t
h
o
d
)
m
i
n
c
x
,
s
.
t
.
{
A
_
u
b
⋅
x
≤
b
_
u
b
,
A
_
e
q
⋅
x
=
b
_
e
q
,
x
∈
b
o
u
n
d
s
.
result=linprog(c,A\_ub,b\_ub,A\_eq,b\_eq,bounds,method)\\\\[1em]\\min cx , \\\\[1em]\\s.t. \begin{cases}A\_ub\cdot x\le b\_ub,\\A\_eq\cdot x=b\_eq,\\x\in bounds.\end{cases}
result=linprog(c,A_ub,b_ub,A_eq,b_eq,bounds,method)mincx,s.t.⎩
⎨
⎧A_ub⋅x≤b_ub,A_eq⋅x=b_eq,x∈bounds.
linprog
是 SciPy 库中用于解决线性规划问题的函数。线性规划是指在满足一组线性不等式约束条件的前提下,优化(最大化或最小化)一个线性目标函数的问题。
以下是 linprog
函数的主要用法及其参数介绍:
参数说明
c
: 目标函数的决策变量对应的系数向量(行列向量都可以,下同)。A_ub
: 不等式约束条件的变量系数矩阵(必须是 ≤ 形式)。b_ub
: 不等式约束条件的常数项矩阵。A_eq
: 等式约束矩阵的变量系数矩阵。b_eq
: 等式约束条件的常数项矩阵。bounds
:每个变量的上下界,默认情况下每个变量的范围是[0, None]
。可以用(min, max)
或[(min1, max1), (min2, max2), ...]
的形式指定。method
:求解方法。可选值包括'simplex'
,'interior-point'
,'revised simplex'
和'highs'
。默认值为'highs'
。options
: 求解器选项,用于设置求解器的参数。
返回值
返回一个 OptimizeResult
对象,其中包含以下关键属性:
x
: 最优解。success
: 布尔值,指示是否找到最优解。status
: 整数,指示求解器的退出状态。message
: 退出状态的信息。fun
: 目标函数的最优值。
调用时用 result.x
2.python代码
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import linprog
c = np.array([-0.05, -0.27, -0.19, -0.185, -0.185])
# NumPy 提供了 numpy.c_ 接口,它可以方便地将多个数组沿着第二个轴(列)进行拼接,形成一个新的数组
A_ub = np.c_[np.zeros(4), np.diag([0.025, 0.015, 0.055, 0.026])]
M = 1
A_eq = np.array([[1, 1.01, 1.02, 1.045, 1.065]])
b_eq = M
bounds = [(0,None), (0,None), (0,None), (0,None), (0,None)]
a = 0
aa = []
ss = []
while a < 0.05:
b_ub = a * np.ones(4)
# 执行线性规划,得到最优解
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds)
# 提取线性规划的解向量和最优值
x = res.x
Q = -res.fun
aa.append(a)
ss.append(Q)
a = a + 0.001
# 绘制结果
plt.plot(aa,ss,'-r')
plt.xlabel("a")
plt.ylabel("Q")
plt.savefig('figure_6.png',dpi = 500)
plt.show()
在运行过程中出现了保存的运行结果图打开是空白的问题
解决方法:
在jupyter notebook 中,savefig()不能单独一行运行,必须和plt.plot()在一行一起运行。
运行结果:
总结
本文介绍了线性规划模型,通过1998年国赛A题作为例题,分别使用Matlab和python进行代码编写。