D题 储药柜的设计
储药柜的结构类似于书橱,通常由若干个横向隔板和竖向隔板将储药柜分割成若干个储药槽(如图1所示)。为保证药品分拣的准确率,防止发药错误,一个储药槽内只能摆放同一种药品。药品在储药槽中的排列方式如图2所示。药品从后端放入,从前端取出。一个实际储药柜中药品的摆放情况如图3所示。
为保证药品在储药槽内顺利出入,要求药盒与两侧竖向隔板之间、与上下两层横向隔板之间应留2mm的间隙,同时还要求药盒在储药槽内推送过程中不会出现并排重叠、侧翻或水平旋转。在忽略横向和竖向隔板厚度的情况下,建立数学模型,给出下面几个问题的解决方案。
1. 药房内的盒装药品种类繁多,药盒尺寸规格差异较大,附件1中给出了一些药盒的规格。请利用附件1的数据,给出竖向隔板间距类型最少的储药柜设计方案,包括类型的数量和每种类型所对应的药盒规格。
2. 药盒与两侧竖向隔板之间的间隙超出2mm的部分可视为宽度冗余。增加竖向隔板的间距类型数量可以有效地减少宽度冗余,但会增加储药柜的加工成本,同时降低了储药槽的适应能力。设计时希望总宽度冗余尽可能小,同时也希望间距的类型数量尽可能少。仍利用附件1的数据,给出合理的竖向隔板间距类型的数量以及每种类型对应的药品编号。
3. 考虑补药的便利性,储药柜的宽度不超过2.5m、高度不超过2m,传送装置占用的高度为0.5m,即储药柜的最大允许有效高度为1.5m。药盒与两层横向隔板之间的间隙超出2mm的部分可视为高度冗余,平面冗余=高度冗余×宽度冗余。在问题2计算结果的基础上,确定储药柜横向隔板间距的类型数量,使得储药柜的总平面冗余量尽可能地小,且横向隔板间距的类型数量也尽可能地少。
4. 附件2给出了每一种药品编号对应的最大日需求量。在储药槽的长度为1.5m、每天仅集中补药一次的情况下,请计算每一种药品需要的储药槽个数。为保证药房储药满足需求,根据问题3中单个储药柜的规格,计算最少需要多少个储药柜。
就是用最少数量宽度类型的药槽装下所有的药盒,即每种药槽所能容纳的药盒宽度范围不能重合。
下面是对应的matlab程序:
clear;clc;
data = xlsread("附件1-药盒型号.xls",1,'B2:D1920');d1 = ceil(sqrt(data(:,1).^2+data(:,2).^2));
data = [data,d1];w = 2;K_min = min(data(:,2));
K_max = max(data(:,2));N = size(data);H_min = K_min;
H_K = 2*H_min - 1;
H_max = H_K - w;H = [];while(H_max <= K_max)index = find(data(:,2)>=H_min & data(:,2)<=H_max);temp = data(index,:);d_min = min(temp(:,4));if(H_K < d_min)H_minH_maxH = [H;[H_K, H_min,H_max]];H_min = H_max + 1;H_K = 2*H_min - 1;H_max = H_K - w;if(H_K > K_max + 2)H_K = K_max + 2;H_max = H_K - w;index = find(data(:,2)>=H_min & data(:,2)<=H_max);temp = data(index,:);d_min = min(temp(:,4));if(H_K < d_min)H_minH_maxH = [H;[H_K, H_min,H_max]];H_min = H_max + 1;H_K = 2*H_min - 1;H_max = H_K - w;elseH_K = d_min - 1;H_max = H_K - w;endendelseH_K = d_min - 1;H_max = H_K - w;end
end
也可以用规划的方法来做,可以用linggo敲,代码如下:
model:Sets:
Box/1..1919/:L,W,H,Wmin,Wmax;
Tank/1..58/:X,SumX;
link(Box,Tank):Y;
EndsetsData:
L,H,W,Wmin,Wmax=@OLE("C:Users86183Desktop2021数学建模暑期训练第一轮B题部分代码附件1-药盒型号.xls","L","H","W","Wmin","Wmax");
@TEXT() = @WRITEFOR( Tank(J) | X(J) #GT# 0: @NAME(X), ' ', X(J), @NEWLINE(1));
@TEXT() = @WRITEFOR( Tank(J) | SumX(J) #GT# 0: @NAME(SumX), ' ', SumX(J), @NEWLINE(1));
@TEXT() = @WRITEFOR( link(I, J) | Y(I,J)#GT#0: @NAME(Y), ' ', J, @NEWLINE(1));
Enddata!Z=@sum(Tank:X);
!Z=4;min=@sum(Tank:X); ! 开放的槽位类型最少;
!决策变量 X=0表示不开放该规格槽位,X=1表示开放该规格槽位;!@for(Box(I):@sum(Tank(J)| J#GE#Wmin(I) #AND# J#LE#Wmax(I): Y(I,J))=1);
!有一个槽位容纳第i种药盒;
@for(Box(I):@sum(Tank(J): Y(I,J))=1);
!不能重叠翻转等(药盒宽度max+2mm);
@for(Box(I):@sum(Tank(J)| J#GT#Wmax(I): Y(I,J))=0);
!留2mm间隙;
@for(Box(I):@sum(Tank(J)| J#LT#Wmin(I): Y(I,J))=0); !只有开放的槽位才摆放药盒;
@for(Box(I): @for(Tank(J): Y(I,J)<=X(J)));!统计适用数量;
@for(Tank(J): SumX(J)=@sum(Box(I): Y(I,J)));@for(link:@bin(y));
@for(Tank:@bin(x));
@for(Tank:@gin(SumX));end! 竖向隔板间距: 18, 33, 44, 58 ;
! 适用药盒种类: 217, 718, 445, 539;! 竖向隔板间距: 19, 33, 44, 58 ;
! 适用药盒种类: 286, 1073, 308, 252;
就是在第一题的基础上加入宽度冗余的限制,同时让宽度类型数量尽可能少。
可以相对简单的把第一题lingo代码中的目标函数换成最小化宽度冗余,每次对药槽宽度类型设定一个定值,最后将结果归一化消除量纲的影响,画个图,取一个可以接受的值。
lingo代码如下:
model:Sets:
Box/1..1919/:L,W,H,Wmin,Wmax;
Tank/1..58/:X,SumX;
link(Box,Tank):Y;
EndsetsData:
L,H,W,Wmin,Wmax=@OLE("附件1-药盒型号.xls","L","H","W","Wmin","Wmax");
@TEXT() = @WRITEFOR( Tank(J) | X(J) #GT# 0: @NAME(X), ' ', X(J), @NEWLINE(1));
@TEXT() = @WRITEFOR( Tank(J) | SumX(J) #GT# 0: @NAME(SumX), ' ', SumX(J), @NEWLINE(1));
@TEXT() = @WRITEFOR( link(I, J) | Y(I,J)#GT#0: @NAME(Y), ' ', J, @NEWLINE(1));
Enddata!决策变量X=0表示不开放该规格槽位,X=1表示开放该规格槽位;
!开放的槽位类型数量;
Z=@sum(Tank:X);
Z=4;min=@sum(Box(I): @sum(Tank(J): Y(I,J)*(J-Wmin(I)))); !@for(Box(I):@sum(Tank(J)| J#GE#Wmin(I) #AND# J#LE#Wmax(I): Y(I,J))=1);
!有一个槽位容纳第i种药盒;
@for(Box(I):@sum(Tank(J): Y(I,J))=1);
!不能重叠翻转等(药盒宽度max+2mm);
@for(Box(I):@sum(Tank(J)| J#GT#Wmax(I): Y(I,J))=0);
!留2mm间隙;
@for(Box(I):@sum(Tank(J)| J#LT#Wmin(I): Y(I,J))=0); !只有开放的槽位才摆放药盒;
@for(Box(I): @for(Tank(J): Y(I,J)<=X(J)));!统计适用数量;
@for(Tank(J): SumX(J)=@sum(Box(I): Y(I,J)));@for(link:@bin(y));
@for(Tank:@bin(x));
@for(Tank:@gin(SumX));
@gin(Z);end! 适用药盒种类: 4, 5, 6, 7, 8, 9, 10;
! 竖向冗余合计: 12989, 7337, 5025, 4105, 3457, 2947, 2535;! 4 ; ! 122.11 second;
! 竖向隔板间距: 19, 33, 45, 58 ;
! 适用药盒种类: 286, 1073, 343, 217;! 5 ; ! 109.09 second;
! 竖向隔板间距: 19, 25, 35, 47, 58 ;
! 适用药盒种类: 286, 670, 482, 340, 141;! 6 ; ! 86.36 second;
! 竖向隔板间距: 19, 23, 29, 37, 47, 58 ;
! 适用药盒种类: 286, 556, 359, 303, 274, 141;! 7 ; ! 52.62 second;
! 竖向隔板间距: 19, 23, 29, 35, 42, 49, 58 ;
! 适用药盒种类: 286, 556, 359, 237, 187, 206, 88;! 8 ; ! 123.13 second;
! 竖向隔板间距: 19, 23, 27, 32, 37, 43, 49, 58 ;
! 适用药盒种类: 286, 556, 247, 233, 182, 146, 181, 88;! 9 ; ! 101.53 second;
! 竖向隔板间距: 18, 22, 25, 28, 32, 37, 43, 49, 58 ;
! 适用药盒种类: 217, 496, 243, 192, 174, 182, 146, 181, 88;! 10 ; ! 64.59 second;
! 竖向隔板间距: 18, 22, 25, 28, 32, 37, 42, 47, 52, 58 ;
! 适用药盒种类: 217, 496, 243, 192, 174, 182, 121, 153, 102, 39;
通过每次设定不同值可做出以下图:
从图中可看出取12种宽度类型较为合适。
加入了药柜高度的限制,不能超过1500mm,但又要尽可能增加药柜空间利用率,又是对药槽进行竖向切割。
可先求出药槽高度类型数量的最大值和最小值,对应lingo代码如下:
model:Sets:
Box/1..1919/:L,W,H,Hmin,Hmax;
Tank/1..127/:X,SumX;
link(Box,Tank):Y;
EndsetsData:
L,H,W,Hmin,Hmax=@OLE("附件1-药盒型号.xls","L","H","W","Hmin","Hmax");
@TEXT() = @WRITEFOR( Tank(J) | X(J) #GT# 0: @NAME(X), ' ', X(J), @NEWLINE(1));
@TEXT() = @WRITEFOR( Tank(J) | SumX(J) #GT# 0: @NAME(SumX), ' ', SumX(J), @NEWLINE(1));
@TEXT() = @WRITEFOR( link(I, J) | Y(I,J)#GT#0: @NAME(Y), ' ', J, @NEWLINE(1));
Enddata!Z=@sum(Tank:X);
!Z=4;min=@sum(Tank:X); ! 开放的槽位类型最少;
!决策变量 X=0表示不开放该规格槽位,X=1表示开放该规格槽位;!@for(Box(I):@sum(Tank(J)| J#GE#Hmin(I) #AND# J#LE#Hmax(I): Y(I,J))=1);
!有一个槽位容纳第i种药盒;
@for(Box(I):@sum(Tank(J): Y(I,J))=1);
!不能重叠翻转等(药盒宽度max+2mm);
@for(Box(I):@sum(Tank(J)| J#GT#Hmax(I): Y(I,J))=0);
!留2mm间隙;
@for(Box(I):@sum(Tank(J)| J#LT#Hmin(I): Y(I,J))=0); !只有开放的槽位才摆放药盒;
@for(Box(I): @for(Tank(J): Y(I,J)<=X(J)));!统计适用数量;
@for(Tank(J): SumX(J)=@sum(Box(I): Y(I,J)));@for(link:@bin(y));
@for(Tank:@bin(x));
@for(Tank:@gin(SumX));end! 竖向隔板间距: 53, 73, 87, 127;
! 适用药盒种类: 532, 485, 25, 877;
! Elapsed runtime seconds: 157.67
和第一问一样,在没有高度限制时,求得最少需要4种高度类型
model:
sets:
box/1..1919/:L,W,H,Hmin,Hmax;
tank/1..127/:x,sumX;
links(box,tank):Y;
endsetsData:
L,H,W,Hmin,Hmax=@OLE("附件1-药盒型号.xls","L","H","W","Hmin","Hmax");
@TEXT() = @WRITEFOR( Tank(J) | X(J) #GT# 0: @NAME(X), ' ', X(J), @NEWLINE(1));
@TEXT() = @WRITEFOR( Tank(J) | SumX(J) #GT# 0: @NAME(SumX), ' ', SumX(J), @NEWLINE(1));
@TEXT() = @WRITEFOR( links(I, J) | Y(I,J)#GT#0: @NAME(Y), ' ', J, @NEWLINE(1));
Enddataz = @sum(tank(J):x(J)*J);
z<=1500;
z >= 1500-27;min = @sum(tank:x);@for(box(I): @sum(tank(J):y(I,J))=1);@for(box(I): @sum(tank(J)|J#GT#Hmax(I):y(I,J))=0);@for(box(I): @sum(tank(J)|J#LT#Hmin(I):y(I,J))=0);@for(tank(J): @for(box(I): Y(I,J)<=x(J)));@for(tank(J): sumX(J) = @sum(box(I):y(I,J)));@for(tank:@bin(x));
@for(tank:@gin(sumx));
@for(links:@bin(y));end
加入高度限制后求得高度类型的范围为14-51。
本文发布于:2024-02-04 10:36:34,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170705238654821.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |