运筹优化中的数学建模——线性规划深度解析
目录
1.线性规划
2.线性规划模型三要素
3.模型特点
4.建模步骤
5.案例演示
1.线性规划
线性规划(LP)是研究线性约束条件下线性目标函数的极值问题的数学理论和方法。可为合理利用有限人力、物力、财力等资源作出最优决策,提供科学依据。
2.线性规划模型三要素
3.模型特点
4.建模步骤
1.根据影响所要达到目的的因素找到决策变量。
2.由决策变量和所在达到目的之间的函数关系确定目标函数。
3. 由决策变量所受的限制条件确定决策变量所要满足的约束条件。
5.案例演示
5.1 游戏升满级
题目:该游戏每天有100点体力,可通过反复通关A、B、C三张地图来获取经验升级,通关A图可获得20点经验,通关B图可获得30点经验,通关C图可获得45点经验,但通关地图会消耗体力,其中通关A图消耗4点体力,通关B图消耗8点体力,通关C图消耗5点体力,同时A、B、C三图每天加在一起最多通关20次,求该怎么组合通关ABC三个地图的次数来使今天获得的经验最大?
解答:由上题可知:
决策变量:三个地图通关次数。设A、B、C三个地图通关的次数分别为,
,
。
目标函数:获得的经验最高。设经验为y,。
约束条件:消耗体力不能超过100(),三个地图最多超过20次(
),隐藏约束条件(
),
用一般形式(代数形式)表现为:
转换为矩阵表现形式为:
其中:
编程实现:
import numpy as np
from scipy.optimize import linprog
# 目标函数系数,这里取负值,因为linprog默认进行最小优化
c=[-20,-30,-45]
# 不等式约束的系数矩阵
A_ub=[
[4,8,15],
[1,1,1]
]
# 不等式约束的右侧向量值b
b_ub=[100,20]
# 定义域
bounds=[[0,None],[0,None],[0,None]]
# 求解线性规划问题
# 注意:由于linprog默认是求解最小化问题,我们通过对目标函数系数取负值来转换为最大化问题
result=linprog(c,A_ub,b_ub,bounds=bounds)
# 输出结果
print('A、B、C三图分别通关的次数为:',result.x) # 解向量
# 目标函数的最大值是最小化问题的相反数
y=-result.fun
print('最终获得的经验为:',y)
输出结果如下,可知通过通关A图15次,B图5次,C图0次即可获得今天经验最大450值:
5.2 投资选择
题目:市场上有n种资产(如股票、债券、……)(i=1,2,…,n)供投资者选择,某公司有数额为M的一笔相当大的资金可用作一个时期的投资。公司财务分析人员对这n种资产进行了评估,估算出在这一时期内购买资产
的平均收益率为
,并预测出购买
的风险损失率为
。考虑到投资越分散,总的风险越小,公司确定,当用这笔资金购买若干种资产时,总体风险可用所投资的
中最大的一个风险来度量。
28 | 2.5 | 1 | 103 | |
21 | 1.5 | 2 | 198 | |
23 | 5.5 | 4.5 | 52 | |
25 | 2.6 | 6.5 | 40 |
问:给上述公司设计投资组合方案,用给定资金M,有选择地购买若干种资产或存银行生息,使净收益尽可能大,总体风险尽可能小。
解答:由上题可知:
决策变量:投资不同项目的为
(i=1,2,…,n)。
目标函数:净收益Q尽可能大、总风险尽可能小。
约束条件:总资金M有限,每一笔投资都是非负数。模型假设:
可供投资的资金数额M相当大。 投资越分散,总的风险越小,总体风险可用所投资的 中最大的一个风险来度量。
可供选择的 n+1 种资产(含银行存款)之间是相互独立的。 每种资产可购买的数量为任意值。 在当前投资周期内, ,
,
,
(i=0,1,…,n)固定不变。
不考虑在资产交易过程中产生的其他费用。 由于投资数额M相当大,而题目设定的定额 相对M很小,
更小,因此假设每一笔交易
都大于对应定额
。
模型建立:
1)总体风险用所投资的中最大的一个风险来衡量,即
.
2)购买(i=1,2,…,n)所付交易费本来是一个分段函数,但假设中已假设每一笔交易
都大于对应定额
,所以交易费=
,这样购买
的净收益可以简化为
.
3)由以上可以得出:
目标函数为:
约束条件为:
可以发现这是一个多目标规划模型,我们可以将其进行简化变成一个目标的线性规划。
模型简化:
在实际投资中,投资者承受风险的程度不一样,这时可以给定风险一个界限a,使最大的一个风险,这样就可以将目标函数中的
转换为约束条件
(总体风险小于某个常数)。至此,模型用一般形式表现为:
将数值代入进去得:
这里 M 我们取1万元,由于 a 是任意给定的风险度,不妨 a 从0开始,以步长=0.001进行循环搜索,搜索至 a=5%(低风险者能够接受的风险)。
编程实现:
import matplotlib.pyplot as plt
from numpy import ones,diag,c_,zeros # 用于创建和操作数组
from scipy.optimize import linprog # 用于执行线性规划
# 设置matplotlib的参数使其支持LaTeX文本和字体大小
plt.rc('text',usetex=True)
plt.rc('font',size=16)
# 线性规划问题的目标函数系数
c=[-0.05,-0.27,-0.19,-0.185,-0.185]
# 线性不等式约束的系数矩阵
# 使用c_来合并数组,zeros创建一个全0的数组作为第1列,diag创建一个对角阵
A=c_[zeros(4),diag([0.025,0.015,0.055,0.026])]
# 线性等式约束的系数矩阵和右侧的值
Aeq=[[1,1.01,1.02,1.045,1.065]]
beq=[1]
# 初始化参数a,以及两个用于存储结果的空列表
a=0
aa=[]
ss=[]
# 循环,a的值从0开始,以0.0001的步长增加,直到0.05
while a<0.05:
# 创建线性不等式约束的右侧值(b)
b=ones(4)*a
# 执行线性规划,得到最优解
res=linprog(c,A,b,Aeq,beq,bounds=[(0,None),(0,None),(0,None),(0,None),(0,None)])
# 提取线性规划的解向量x和最优值Q
x=res.x
Q=-res.fun
# 将当前的a值和对应的最优值Q存入列表
aa.append(a)
ss.append(Q)
# a增加0.001
a=a+0.001
# 绘制结果,a值与最优值Q之间的关系图
plt.plot(aa,ss,'r*') # 使用红色星号标记数据点
# 设置坐标轴标签,其中a和Q将使用LaTeX格式显示
plt.xlabel('$a$')
plt.ylabel('$Q$',rotation=90)
# 显示图形
plt.show()

由上图可以看出:
① 风险不超过2.5%时,风险大,收益也大;
② 在a=0.006 附近有一个转折点,在这一点左边,风险增加很少时,利润增长很快。在这一点右边,风险增加很大时,利润增长很缓慢。所以对于风险和收益没有特殊偏好的投资者来说,应该选择曲线的转折点作为最优投资组合,大约是 a=0.6%,Q=2000,所对应的投资方案为:
风险度a=0.006,收益Q=2019元;=0元,
=2400元,
=4000元,
=1091元,
=2212元。
作者:LotsoD