数学建模上机实验报告

按:有待进一步施工,尤其是最后一个问题...

这一届(19级)的数学建模的上机题目是在晚上上机的三个小时(可以适当延时一到两个小时)完成一道题目的建模与求解。可以使用任何方法,如果使用计算机求解,那么需要给出代码。因此,这里在建模之后,当然是选择使用 Python 来求解。而题目本身则是一道经典的运筹学问题。在网上也比较容易找到相关的题目。

问题描述

以下没有排版的文字描述仅供搜索引擎检索时使用。

某医院每天各时间段内需要的值班护士数如表1所示: 该医院护士上班分五个班次,每班8小时,具体上班时间为第一班2:0010:00,第二班6:0014:00,第三班10:0018:00,第四班14:0022:00,第五班18:00~2:00(次日)。每名护士每周上5个班,并被安排在不同的日子,由一名总护士长负责护士的值班安排。值班方案要做到在人员或经济上比较节省,又做到尽可能合情合理。下面是一些正在考虑中的值班方案: 方案1:每名护士连续上班5天,休息2天,并从上班第一天起按从上第一班到第五班顺序安排。 方案2:考虑到方案1中每名护士在周末(周六、周日)两天内休息安排不均匀,于是规定每名护士在周六、周日两天内安排一天、且只安排一天休息,再在周一至周五期间安排4个班,同样上班的5天内分别顺序安排5个不同班次。 在对方案1、2建立线性规划模型并求解后发现,方案2虽然在安排周末休息上比较合理,但所需值班人员要比方案1有较多增加,经济上不太合算,于是又提出了第3方案。 方案3:在方案2的基础上,动员一部分护士放弃周末休息,即每周在周一至周五间由总护士长给安排三天值班,加周六周日共上五个班,同样五个班分别安排不同班次。作为奖励,规定放弃周末休息的护士,其工资和奖金总额比其他护士增加a%。 根据上述方案,帮助总护士长分析研究: (1)对方案1、2建立使值班护士人数为最少的线性规划模型并求解。 (2)对方案3,同样建立使值班护士人数为最少的线性规划模型并求解, 然后回答a的值为多大时,第3方案较第2方案更经济。

(1)对方案 1、2 建立使值班护士人数为最少的线性规划模型并求解。

对方案 1

\(x_i\) 表示星期 \(i\) 上第一班的人数(\(i = 1,2,3,...,7\)),于是我们可以画出护士的值班表,然后我们可以对方案 1 建模

\[ min \; z = x_1 + x_2 + x_3 + x_4 + x_5 + x_6 + x_7 \]

s.t.

\[ \begin{align} & x_1 + x_7 \geq 21 \\ & x_6 + x_7 \geq 21 \\ & x_6 + x_5 \geq 21 \\ & x_5 + x_4 \geq 21 \\ & x_4 + x_3 \geq 21 \\ & x_3 + x_2 \geq 21 \\ & x_2 + x_1 \geq 21 \\ & x_i \geq 11 (i = 1,2...7) \end{align} \]

Python 代码如下:

from scipy.optimize import linprog

# 需要优化的函数对应的参数
c = [1, 1, 1, 1, 1, 1, 1]
# 不等式对应的参数矩阵
A = [[-1, 0, 0, 0, 0, 0, -1],
     [0, 0, 0, 0, 0, -1, -1],
     [0, 0, 0, 0, -1, -1, 0],
     [0, 0, 0, -1, -1, 0, -1],
     [0, 0, -1, -1, 0, 0, 0],
     [0, -1, -1, 0, 0, 0, 0],
     [-1, -1, 0, 0, 0, 0, 0]]
# 不等式对应的上界
b = [-21, 
     -21, 
     -21, 
     -21, 
     -21, 
     -21, 
     -21]

x0_bounds = (11, None)
x1_bounds = (11, None)
x2_bounds = (11, None)
x3_bounds = (11, None)
x4_bounds = (11, None)
x5_bounds = (11, None)
x6_bounds = (11, None)

# 代入参数,利用 Linprog 求解
res = linprog(c, A_ub=A, b_ub=b, bounds=(x0_bounds, x1_bounds, x2_bounds, x3_bounds, x4_bounds, x5_bounds, x6_bounds), options={"disp":True})
print(res)

运行结果如下

Primal Feasibility  Dual Feasibility    Duality Gap         Step             Path Parameter      Objective
1.0                 1.0                 1.0                 -                1.0                 84.0
0.2809006503072     0.2809006503072     0.2809006503072     0.7236863182761  0.2809006503072     91.03677956402      
0.08188226522114    0.08188226522115    0.08188226522115    0.7562200719556  0.08188226522115    77.6110644976       
0.003285103873164   0.003285103873165   0.003285103873165   0.9666015052536  0.003285103873165   77.04759485173      
4.141424664791e-07  4.141424663523e-07  4.141424663529e-07  0.9998761933313  4.141424663523e-07  77.00000725134      2.070722078688e-11  2.070712356167e-11  2.070712356152e-11  0.9999499999994  2.070712356154e-11  77.00000000036      
Optimization terminated successfully.
        Current function value: 77.000000   
        Iterations: 5
    con: array([], dtype=float64)
    fun: 77.00000000036258
message: 'Optimization terminated successfully.'
    nit: 5
slack: array([ 1.,  1.,  1., 12.,  1.,  1.,  1.])
status: 0
success: True
    x: array([11., 11., 11., 11., 11., 11., 11.])

所以得到的结果是:

\[ x_1 = 11, x2 = 11, x_3 = 11, x_4 = 11, x_5 = 11, x_6 = 11, x_7 = 11 \]

对方案 2

周一到周五连续安排 4 个班,所以可以先安排周末的护士值班情况:周六、周末两天共 10 个班次,用 \(x_j(j = 1...10)\) 表示周六周末两天 10 个班次的护士人数,其中 \(x_1 ...x_5\) 分别代表周六第 1 个到第 5 个班次的护士人数,\(x_6...x_{10}\) 分别代表周日从第 1 个到第 5 个班次的护士人数。因此,我们可以列出其值班表(这里略)。

对方案 2 建立如下线性规划模型:

\(min \; w = x_1 + \cdots + x_{10}\)

s.t.

\[ \begin{align} x_1 + x_5 + x_9 + x_{10} \geq 21 \\ x_4 + x_5 + x_8 + x_9 \geq 21 \\ x_1 + x_2 + x_6 + x_{10} \geq 21 \\ x_2 + x_3 + x_6 + x_7 \geq 20 \\ x_3 + x_4 + x_7 + x_8 \geq 19 \\ x_1 + x_2 \geq 19 \\ x_6 + x_{10} \geq 19 \\ x_2 + x_3 \geq 21 \\ x_6 + x_7 \geq 21 \\ x_3 + x_4 \geq 21 \\ x_7 + x_8 \geq 21 \\ x_8 + x_9 \geq 20 \\ x_4 + x_5 \geq 20 \\ x_1 + x_5 \geq 18 \\ x_9 + x_{10} \geq 18 \\ x_4 + x_8 \geq 11 \\ x_3 + x_7 \geq 11 \\ x_2 + x_6 \geq 11 \\ x_5 + x_9 \geq 11 \\ x_1, x_2, x_5, x_6, x_9, x_{10} \geq 11 \\ x_j \geq 0 \; (j = 1,2,...,10) \end{align} \]

Python 代码如下:

from scipy.optimize import linprog

# 需要优化的函数对应的参数
c = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
# 不等式对应的参数矩阵
A = [[-1, 0, 0, 0, -1, 0, 0, 0, -1, -1],
     [0, 0, 0, -1, -1, 0, 0, -1, -1, 0],
     [-1, -1, 0, 0, 0, -1, 0, 0, 0, -1],
     [0, -1, -1, 0, 0, -1, -1, 0, 0, 0],
     [0, 0, -1, -1, 0, 0, -1, -1, 0, 0],
     [-1, -1, 0, 0, 0, 0, 0, 0, 0, 0],
     [0, 0, 0, 0, 0, -1, 0, 0, 0, -1],
     [0, -1, -1, 0, 0, 0, 0, 0, 0, 0],
     [0, 0, 0, 0, 0, -1, -1, 0, 0, 0],
     [0, 0, -1, -1, 0, 0, 0, 0, 0, 0],
     [0, 0, 0, 0, 0, 0, -1, -1, 0, 0],
     [0, 0, 0, 0, 0, 0, 0, -1, -1, 0],
     [0, 0, 0, -1, -1, 0, 0, 0, 0, 0],
     [-1, 0, 0, 0, -1, 0, 0, 0, 0, 0],
     [0, 0, 0, 0, 0, 0, 0, 0, -1, -1],
     [0, 0, 0, -1, 0, 0, 0, -1, 0, 0],
     [0, 0, -1, 0, 0, 0, -1, 0, 0, 0],
     [0, -1, 0, 0, 0, -1, 0, 0, 0, 0],
     [0, 0, 0, 0, -1, 0, 0, 0, -1, 0]]
# 不等式对应的上界
b = [-21,
     -21,
     -21,
     -20,
     -19,
     -19,
     -19,
     -21,
     -21,
     -21,
     -21,
     -20,
     -20,
     -18,
     -18,
     -11,
     -11,
     -11,
     -11]

x0_bounds = (11, None)
x1_bounds = (11, None)
x2_bounds = (0, None)
x3_bounds = (0, None)
x4_bounds = (11, None)
x5_bounds = (11, None)
x6_bounds = (0, None)
x7_bounds = (0, None)
x8_bounds = (11, None)
x9_bounds = (11, None)

# 代入参数,利用 Linprog 求解
res = linprog(c, A_ub=A, b_ub=b, bounds=(x0_bounds, x1_bounds, x2_bounds, x3_bounds, x4_bounds, x5_bounds, x6_bounds,x7_bounds, x8_bounds, x9_bounds), options={"disp":True})
print(res)

运行结果如下:

Primal Feasibility  Dual Feasibility    Duality Gap         Step             Path Parameter      Objective
1.0                 1.0                 1.0                 -                1.0                 76.0
0.1665271036098     0.1665271036098     0.1665271036098     0.8426664003083  0.1665271036098     99.77035462588      
0.02577816616616    0.02577816616617    0.02577816616617    0.8554761926722  0.02577816616617    141.9514028382      
0.004990687117403   0.004990687117402   0.004990687117402   0.8274173331906  0.004990687117403   107.7426696988      
0.0002950591091504  0.0002950591091505  0.0002950591091506  0.9487415264061  0.0002950591091506  107.9482724078      
5.696569995622e-08  5.696569991676e-08  5.696569979366e-08  0.9998223879716  5.696569998307e-08  108.00000478        
2.848279017625e-12  2.84830035367e-12   2.848388191978e-12  0.9999499996825  2.848288065828e-12  108.0000000002      
Optimization terminated successfully.
        Current function value: 108.000000  
        Iterations: 6
    con: array([], dtype=float64)
    fun: 108.000000000239
message: 'Optimization terminated successfully.'
    nit: 6
slack: array([ 2.30000000e+01,  2.07164358e+01,  2.30000000e+01,  2.42835642e+01,
        2.30000000e+01,  3.00000000e+00,  3.00000000e+00,  1.14178209e+00,
        1.14178209e+00, -4.13713508e-10, -4.13720613e-10,  8.58217912e-01,
        8.58217913e-01,  4.00000000e+00,  4.00000000e+00,  8.71643582e+00,
        1.12835642e+01,  1.10000000e+01,  1.10000000e+01])
status: 0
success: True
    x: array([11.        , 11.        , 11.14178209,  9.85821791, 11.        ,
    11.        , 11.14178209,  9.85821791, 11.        , 11.        ])

所以得到的结果是:

\[ x_1 = 11 \\ x_2 = 11 \\ x_3 = 12 \\ x_4 = 10 \\ x_5 = 11 \\ x_6 = 11 \\ x_7 = 12 \\ x_8 = 10 \\ x_9 = 11 \\ x_{10} = 11 \]

对方案 3,同样建立使值班护士人数为最少的线性规划模型并求解,然后回答 a 的值为多大时,第 3 方案较第 2 方案更经济。

Python 代码如下:

from scipy.optimize import linprog
import numpy as np

# 需要优化的函数对应的参数

# 不等式对应的参数矩阵
from scipy.optimize import linprog
import numpy as np

# 需要优化的函数对应的参数

# 不等式对应的参数矩阵
A = np.array([[0, 0, 0, -1, -1, 0, 0, 0, 0, 0, -1, 0, 0, 0, -1],
     [0, 0, 0, 0, 0, 0, 0, -1, -1, 0, 0, -1, -1, 0, 0],
     [0, 0, 0, 0, 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0],
     [-1, -1, 0, 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0],
     [-1, 0, 0, 0, -1, 0, 0, 0, 0, 0, -1, -1, 0, 0, 0],
     [0, 0, 0, -1, -1, -1, -1, 0, 0, 0, -1, 0, 0, 0, -1],
     [0, 0, -1, -1, 0, -1, 0, 0, 0, -1, 0, 0, 0, -1, -1],
     [0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, 0, -1, -1, 0],
     [0, 0, 0, 0, 0, 0, 0, -1, -1, 0, 0, 0, 0, 0, 0],
     [0, -1, -1, 0, 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0],
     [-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, 0],
     [0, 0, 0, 0, -1, 0, -1, -1, 0, 0, -1, -1, 0, 0, 0],
     [0, 0, 0, 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, -1, -1],
     [0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, 0, 0, 0, 0],
     [0, 0, 0, -1, -1, 0, 0, 0, -1, -1, 0, 0, 0, 0, 0],
     [0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0],
     [0, 0, 0, 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, 0, 0],
     [0, 0, 0, 0, 0, -1, -1, 0, 0, 0, -1, 0, 0, 0, -1],
     [0, 0, 0, -1, -1, 0, 0, 0, -1, -1, 0, 0, 0, 0, 0],
     [0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1],
     [0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, -1, 0, 0, 0],
     [0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0],
     [0, 0, 0, 0, -1, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0],
     [0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0],
     [0, -1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, -1, 0, 0],
     [0, 0, 0, 0, 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, 0],
     [0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
     [0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0],
     [0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1]])

# 不等式对应的上界
b = np.array(
    [-19, -19, -19, -19, -21, -21, -21, -21, -21, -21, -21, -20, -20, -20, -20, -20, -18, -18, -18, -18, -11, -11, -11,
     -11, -11, -11, -11, -11, -11])
c = np.array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1])

# 代入参数,利用 Linprog 求解
res = linprog(c, A_ub=A, b_ub=b, options={"disp": True})
print(res.x)

结果如下:

Primal Feasibility  Dual Feasibility    Duality Gap         Step             Path Parameter      Objective
1.0                 1.0                 1.0                 -                1.0                 37.0
0.2426475349467     0.2426475349467     0.2426475349467     0.7716251234008  0.2426475349467     55.01818412195      
0.04252842427154    0.04252842427153    0.04252842427153    0.8355997887823  0.04252842427153    104.247705703       
0.009356747800954   0.009356747800955   0.009356747800955   0.7953997093281  0.009356747800955   103.5089480738      
0.0005030671623338  0.000503067162334   0.0005030671623341  0.949055846188   0.000503067162334   104.012914924       
7.859317598419e-08  7.859317820896e-08  7.859317829872e-08  0.9998545163766  7.859317721648e-08  103.9999952247      
3.929662644848e-12  3.929721186398e-12  3.929745417963e-12  0.9999499992073  3.929678577412e-12  103.9999999998      
Optimization terminated successfully.
        Current function value: 104.000000  
        Iterations: 6
[ 7.14875174  2.83528395  6.35115075  7.24511069  6.60703322 11.
11.          8.         13.          7.          4.39296678  6.76594071
4.2500236   4.64884925  3.75488931]

由于放弃周末休息的护士其工资和奖金总额比其他护士增加a%,假设未放 弃周末休息的护士的工资为A 园,若使方案三比方案2更经济,可列一下方程: 66A + 38 A (1+a%) < 108 *A 解以上方程可得: a% < 10.5263% 即a<10.5263时,方案三比方案二更经济。


数学建模上机实验报告
http://fanyfull.github.io/2021/12/31/数学建模上机实验报告/
作者
Fany Full
发布于
2021年12月31日
许可协议