Plant Simulation 学习笔记(一)

1.问题描述

(声明:本笔记参考《生产系统仿真:Plant Simulation应用教程》这本书)

1.1 二次分配问题描述

      设备布局问题是典型的二次分配问题(Quadratic Assignment Problem,QAP):将n个设备放置到n个位置上,其中每个位置上能且仅能放置一台设备,共有n!个选择。有两种情况:

      (1)已知n个设备(设施规划称为作业单位Activity或设施)两两之间的物料搬运量大小Wij(i=1,2,…,n, j=1,2,…,n),以及n个固定位置(设施规划中称为工作地),并且这n个工作地之间的距离为Dij。布置问题就是如何将n个作业单位分配到n个工作地,使得总的物流量为最小,即
在这里插入图片描述
      (2)已知n个作业单位两两之间的物料搬运量大小Wij及作业单位的形状、面积,合理安排作业单位之间的关系,使全部的物流量为最小或接近最小值。这是典型的设施规划问题,例如,已知一间工厂的总平面图,以及工厂将要生产的产品、工艺等,如何使得车间厂房等作业单位合理布置到总平面中,使工厂物流合理通畅呢?设施规划中的系统布置设计SLP可以帮助我们实现。
      以下面的问题为例:
      某玩具厂有8个车间M1~M8,两两之间的物料搬运量参见下表。
在这里插入图片描述
可提供的工厂如图所示,
在这里插入图片描述
布置设计就是合理的将M1~M8分配到A~H 8个工作地点,使得总物流量尽可能小。
      假设上图的黑色线条为物流通道或路径,8个车间的面积相等。两车间之间的物料搬运不能穿越第三个车间,例如,有物料要从A车间搬到E车间去就不能穿越C车间,只能按这样的路线走:从A的中心出发垂直往下到达中间通道,经过C车间到达E/F车间的中间通道,再垂直向上运动到E的中心。相邻车间之间可以直接搬运,例如,有物料从F搬运到H,则可以直接从F车间的中心搬运到H的中心。以40m为一个标准移动单位,F→H的距离为1个标准移动单位,而A→E的距离为3个标准移动单位,以此类推,得到这8个工作地的距离从至表参见下表。
在这里插入图片描述

2.创建新项目

2.1在模型中添加对象

在这里插入图片描述
添加完成如上图所示。

2.2 添加全局变量

在这里插入图片描述
其中,1)Number_Of_Machine:作业单位数量,本例为8个;2)PartsNo:记录仿真模型在后续仿真过程中搬运的零件数,初始值为零;3)X_pos_init/Y_pos_init:定位M1~M8作业单位位置的初始坐标。Plant Simulation绘图坐标采用像素表达,坐标原点(0,0)位于模型层的左上角,水平往屏幕右方为x方向,垂直向屏幕下方为y方向。

2.3 从至表数据处理

点击W_from_to_Data对象,然后如下设置(点击黄色框设置格式):
在这里插入图片描述
以同样的方法,设置距离从至表,
在这里插入图片描述

2.4 从至表数据校核

      右上角数据不能小于零;对角线数据必须等于零;左下角可以没有数据,如果有数据的可以不与右上角数据相等。例如,工作地1~3的距离为10,工作地3~1的距离为0或者10的话,表示物料在两工作地之间走的是同一条路线,如果工作地3~1的距离不是10而是其他数据,则表示来回搬运物料走的路线不一样,这样是允许的。所有与初始化有关的任务均在方法InitPartsTable中完成,双击InitPartsTable打开,输入如下SimTalk语句:

is
   i, j, Rows, Lines: integer;--整数型局部变量
   MachineName,BufName: string;--字符串型局部变量(机器、暂存区名称)
   Machine,Buf: object; --对象型局部变量
do
   if Number_Of_Machine/=D_From_To_Chart.YDim then
    inspect messageBox("设置数目不对!请假查...,",50,13)
    when 16 then
     print "Yes";
    when 32 then
   print "N0";
       else
         print "Cancel";
    end;
    EventController.stop; -- 终止仿真
end;
PartsTable.delete; -- 清除零件表的内容
   for i:=1 to Number_Of_Machine loop --检查距离从至表的数据是否有错
    for j:=1 to Number_Of_Machine loop
     if j<i then
      if D_From_To_Chart[j,i]<=0 then
       D_From_To_Chart[j,i]:=D_From_To_Chart[i,j];
      end;
     else
      if j=i then
       D_From_To_Chart[j,i]:=0; -- 设施本身距离为0
     else
      if D_From_To_Chart[j,i]<=0 then -- 设施之间距离小于等于0
       messageBox("距离小于等于0..., ",50,13);
       EventController.stop; -- 终止仿真
     end;
    end;
   end;
  next;
   next;
end;

运行之后的距离从至表:
在这里插入图片描述

3. 仿真建模思路

       有了两个从至表及初始数据后,观察模型的构建过程如下:
       1)表MachineSequence机器序列存放的8台机器(题目原意是8个车间,简单起见,一个车间看做8台机器)对应A~H的8个工作地,例如,序列M1,M2,…,M8和8个工作地对应关系参见下表第一行,M3,M1,M5,M8,M2,M7,M4,M6和8个工作地对应关系参见下表第2行。
在这里插入图片描述
       2)一旦确定某设备定位在某工作地,仿真模型就必须在已确定的工作地指派相应的机床,用SingleProc物流对象来表示机床。
       如果模型中原来有机器及其前面的缓冲区,先将这些对象删除,在方法InitPartsTable的最后添加如下SimTalk语句(注意必须加在最后一行程序end之前):

   for i:=1 to Number_Of_Machine loop -- 删除模型中原来的设施
    MachineName := sprint("M",i);
    if existsObject(MachineName) then -- 如果模型中原来有机器
     Machine := str_to_obj(MachineName);
     Machine.deleteObject; -- 删除模型中机器对象
    end;
    BufName := sprint("BF",i);
    if existsObject(BufName) then -- 如果模型中原来有暂存区
     Buf := str_to_obj(BufName);
     Buf.deleteObject; -- 删除模型中暂存区对象
    end;
   next;

4. 建立QAP模型

4.1 定义机器序列

在这里插入图片描述

4.2 定义零件加工顺序表

设置source,如下图
在这里插入图片描述
打开part,添加两个变量如图所示:
在这里插入图片描述

4.3 生成机器及其前置暂存区

打开InitPartsTable方法,在其最后添加如下SimTalk语句:

Lines := 0;
for i:=1 to Number_Of_Machine loop -- 从至表转换成仿真用的零件, 遍历机器序列表
Rows := str_to_num(Omit(MachineSequence[1,i],1,1)); --读取机器序列中的当前机器编号
MachineSequence[2,i] := Rows;
for j:=1 to Number_Of_Machine loop -- 读取搬运量从至表的第Rows行
if W_From_To_Chart[j ,Rows]>0 then -- 如果机器Rows对其他机器有物料搬运
Lines := Lines + 1;
PartsTable[1, Lines] := str_to_obj(sprint(".",location.name,".Parts")); -- 填写PartsTable零件表
PartsTable[2, Lines] := W_From_To_Chart[j ,Rows];
PartsTable[3, Lines] := sprint("Parts");
PartsTable[5, Lines] := Rows; -- Parts将流向的源机器
PartsTable[6, Lines] := j; -- Parts将流向的目的机器
end;
next;
MachineName := sprint("M",Rows); -- 生成机器
Machine:=.MaterialFlow.SingleProc.createObject(current,X_pos_init+D_From_To_Chart[Number_Of_Machine+1,i], Y_pos_init+D_From_To_Chart[Number_Of_Machine+2,i]);
Machine.Name := MachineName;
Machine.ProcTime := 5;
Machine.label := sprint("机器_",Rows);
Machine.ExitCtrl := ref(Leave);
BufName := sprint("BF",Rows); -- 生成Buffer
Buf:=.MaterialFlow.Buffer.createObject(current,X_pos_init+D_From_To_Chart[Number_Of_Machine+1,i]-35, Y_pos_init+D_From_To_Chart[Number_Of_Machine+2,i]);
Buf.Name := BufName;
Buf.Capacity := 5000;
Buf.ProcTime := 0;
.MaterialFlow.Connector.connect(Buf, Machine); -- 机器和暂存区连接起来
next;

这时还不能运行EventController仿真,先在Init方法中添加下面SimTalk语句:

is
i: integer;
do 
HandlingCost :=0;      
PartsNo:=0;
InitPartsTable; -- 调用InitPartsTable初始化零件表
GASequence.delete;
/*For i:=1 to Number_Of_Machine loop
GASequence[1,i]:=i;
next;*/
End;

4.4 调入Load和Leave

load策略如下:

is
i,no,m : integer;
Buf : object;
do
m:=0;
no:=@.getNo;
for i:=1 to PartsTable.YDim loop
if PartsNo=m and no<= PartsNo+PartsTable[2,i] then
@._From:=PartsTable[5,i];
@._to:=PartsTable[6,i];
if no= PartsNo+PartsTable[2,i] then
PartsNo:=PartsNo+PartsTable[2,i];
end;
i:=PartsTable.YDim+1; -- 跳出循环
end;
m:=m+PartsTable[2,i];
next;
-- 先将零件送到From位置
Buf := str_to_obj(sprint("BF", @._From));
@.move(Buf);
end;

然后将load加入source,
在这里插入图片描述Leave的策略如下:

在这里插入图片描述

5. 布置设计的优化

5.1 设置GA

在这里插入图片描述打开编辑,插入以下代码:

:boolean
is
i:integer;
chrom: table;obj:object;
do
chrom := individual[1,1];
result := true;
obj := .LayoutDesign.QAP.MachineSequence;
obj.sort(2,"up");
for i:=1 to obj.YDim loop
obj[3, chrom[1,i]] := i;
next;
obj.sort(3,"up");
end;-- of the method

点击按表,打开:
在这里插入图片描述

5.2 仿真结果

在这里插入图片描述

6. 思考

该方法达到最优解了吗?

  • 3
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值