【学习笔记】Matlab和python双语言的学习(线性规划模型)


前言

通过模型算法,熟练对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,,xn0.

  • 简写形式: 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=1ncjxj,s.t.{j=1naijxj(=,)bi,i=1,2,,m,xj0,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,x0.
    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{qixii=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 (ripi)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}} maxi=0n(ripi)xi,min{max1in{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,xi0,i=0,1,,n.

这是一个多目标规划模型

模型简化:

  • 在实际投资中,投资者承受风险的程度不一样,若给定风险一个界限 a ,使最大的一个风险 q i x i M ≤ a \frac{q_{i}x_{i}}{M}\leq a Mqixia 可找到相应的投资方案。这样把多目标规划变成一个目标的线性规划
  • 这里将目标函数 m i n { m a x 1 ≤ i ≤ n { q i x i } } min\{max_{1\leq i\leq n}\{q_ix_i\}\} min{max1in{qixi}} 转化为了约束条件: q i x i M ≤ a \frac{q_{i}x_{i}}{M}\leq a Mqixia (总体风险小于某个常数)

简化后的模型:
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=0n(ripi)xis.t. Mqixia,i=1,2,,n,i=0n(1+pi)xi=M,xi0,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. Axb,Aeqx=beq,lbxub.

  • 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.025x1aM,0.015x2aM,0.055x3aM,0.026x4aM,xi0 (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_ubxb_ub,A_eqx=b_eq,xbounds.
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进行代码编写。

  • 11
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值