第 10 章 Arena 的集成和定制
本章我们将介绍 Arena 和其他应用程序的集成问题以及如何构建定制的 Arena 模块。我
们将通过一个非常简单的呼叫中心的模型来阐述这些概念。
第一节介绍第一个主题,在这里我们设计了一个模型,从一个外部文件中将预定的到达
时间读入模型,然后将性能测度数据写入一个文件中。这说明可以采用多种不同方法从外部
数据源(如文本文件)将数据集成到 Arena 模型中来;第二节我们将介绍两种微软的 Windows
操作系统技术,即 ActiveX 自动化技术和 VBA(Visual Basic for Applications)技术。Arena
利用这些技术直接和其它程序集成。在这一节中我们还将介绍 Arena 是如何与 VBA 集成的。
我们假定读者已经熟悉 VBA 编程,或者读者会通过学习其它有关资料来达到这一要求,本
节的重点只是阐明在 Arena 中如何使用 VBA;第三节介绍怎样使用这些技术来创建一个定
制的用户界面;第四节继续讨论 VBA,并对呼叫中心模型进行了扩充,使其能够纪录有关
呼叫数据并且在微软的 Excel 中将呼叫周期信息用图像表示出来;最后一节即第五节我们将
从整体上介绍如何设计读者自己的模块,从而增加 Arena 的标准建模结构。通过这一章的学
习,读者将对 Arena 的核心特点有一个初步的了解,并且能够将 Arena 和其它桌面应用程序
相集成,以及采取多种方式创建定制的 Arena 界面。
10.1 模型 10-1:读写数据文件
我们先从一个非常简单的呼叫中心模型开始,然后在多个我们感兴趣的方面逐步对它进
行扩展。我们的呼叫中心有一个随机产生的呼叫到达流和一个处理呼叫的事务中心,呼叫在
经过事务中心处理之后即离开系统。呼叫中心经理估计,呼叫的到达服从均值为 1.1 的指数
分布,呼叫的处理时间服从均值为 0.75、最小值为 0.3、最大值为 1.1 的三角分布。如图 10-1
所示,建立本系统的仿真模型,我们使用了一个 Create 模块、一个 Process 模块和一个 Dispose
模块。
原书 P401
图 10-1. 简单的呼叫中心模型
这三个模块的数据如图 10-2 所示,仿真实验的参数通过菜单 Run>Setup>Replication
Parameters 设置成图 10-3 所示。建好模型之后,我们就可以运行并察看仿真结果了。
原书 P402
图 10-2. Create、 Process 和 Dispose 模块
原书 P402
图 10-3. 仿真实验参数
尽管这个呼叫中心模型很简单,我们依然可以使其更加符合实际。呼叫中心经理正好告
知我们,他有某天呼叫到达时间的历史数据。那就让我们使用收到的这一段时间的实际呼叫
记录来产生模型实体,而不是使用概率分布的抽样数据,这样可以更好地确认我们所构建的
模型。通过这些实际数据驱动模型进行仿真运行,如果其仿真结果和那段时间系统的实际性
能非常贴近,我们就可以更加相信该仿真模型的逻辑的正确性了。或者我们也可以使用同样
的方法对具有特定到达模式的系统进行仿真运行,例如,卡车按照一个固定的但是不规则的
日程时间安排到达一个分销中心的装载码头运送货物。
我们在 10.1.1 小节开始一个简单的实例,即从文本文件中读取实体到达数据;在 10.1.2
小节我们将介绍从其它数据源读取类似数据的方法。
10.1.1 模型 10-2:从文本文件中读取实体的到达数据
为了对呼叫中心模型作这样的修改,我们需要一个包含所要研究时间段的到达时间数据
的文件,用它来替换产生实体的模型逻辑。方便起见,假定仿真运行从第 0 分钟开始,我们
构造了一个包含相应仿真时间值的 ASCII 类型的文本文件,该文件(Model 10-02 Input.txt)
的前几个数值如图 10-4 所示。在这里我们不详细介绍这个 ASCII 文本文件是如何产生的。
实际上,读者很可能会发现,读者所能获取的信息很难如此方便地存储起来,但是通过电子
数据表格或者数据库软件的有效使用,通常读者还是能够将原始数据转化成可以直接用于仿
真的值并导出到文本文件中。
原书 P403
图 10-4. 修改后的呼叫中心模型的呼叫时间数据
我们需要决定如何使用存储在文本文件中的历史数据,这涉及到两个方面的问题:一是
将数据从文件传至模型的机制;二是如何使这些数据在适当的时间产生实体。我们先看看在
适当的时间产生实体的逻辑,这包括当到达模型逻辑的相应部分时读取数据的细节问题。
到目前为止,我们都是用 Create 模块来产生实体,在仿真运行的整个过程都是基于间
隔时间来产生新的实体。我们知道,手工仿真的(还记得第二章的有关内容吗?)每一个实
体到达的时候,当前到达的实体都被送至模型中,而下一个到达的实体则被放入未来事件表
以便在将来的某个适当时间到达,对话框中 Time Between Arrivals 项的数据决定了下一个实
体到达的时刻,更一般的,这和概率分布的抽样结果有关。
然而,我们不能通过构造一个简单的 Time Between Arrivals 项的表达式来从我们的数据
文件中建立呼叫的到达信息,相反的,如图 10-5 所示,我们将直接在模型中使用一个控制
实体(control entity)来模仿当前到达和下一个到达的实体逻辑。
原书 P404
图 10-5. 从文件产生实体的逻辑图
如图 10-6 所示,Create 模块只产生一个实体。对于这个 Create 模块,Arena 只会在每次
仿真实验开始时产生一个实体,然后就停止实体产生的流程,因为这已经达到了在 Max
Arrivals 项设置的产生实体的最大数量(即 1)。
产生的实体进入 ReadWrite 模块,如图 10-7 所示,从数据文件中读取下一个值并将它
赋给实体属性 Call Start Time。ReadWrite 模块可以在高等运送面板中找到,它能从外部数据
源读取一个或多个数值到 Arena 中,并且将这些值赋给模型变量。Arena 的文件名 Arrivals File
用作文件的模型标识符,这个名称千万别和存储在硬盘上(或者任何其它地方)的实际文件
名混淆了,我们后面将介绍在 File 数据模块中定义这个实际的文件名称。
原书 P404
图 10-6. 修改后的 Create 模块
原书 P405
图 10-7. ReadWrite 模块
实体从数据文件读取数值之后到达 Delay 模块(图 10-8)等待 Call Start Time 长的时间,
以使代表呼叫的实际实体能在适当的时间到达逻辑模型。由于数据文件中的数值代表从仿真
运行开始后每一个呼叫的绝对时间而不是间隔时间,所以 Delay Time 项被赋值为 Call Start
Time - TNOW,这样实体将被延迟到存储在 Call Start Time 属性里的时间值。
原书 P405
图 10-8. Delay 模块
当控制实体完成必要的延迟之后,即可产生实际的呼叫实体进入逻辑系统,基本操作面
板中的 Separate 模块可以很好地满足这个需要,如图 10-9 所示。Separate 模块一方面将控制
实体(标有 Original 的模块退出点)传送回 ReadWrite 模块,再从数据文件中获取下一个呼
叫时间;另一方面,Separate 模块产生控制实体的一个副本,并通过标有 Duplicate 的退出
点(如图 10-5 所示)将其传送至逻辑模型,这个复制实体代表一个新的呼叫,它将完成所
有剩余的模型逻辑。
原书 P406
图 10-9. Separate 模块
修改模型的最后工作就是要指定数据文件的必要信息,如图 10-10 所示,编辑高等操作
面板中的 File 数据模块。当我们在 ReadWrite 模块的 Arena File Name 项中敲入 Arrivals File
时,Arena 将自动在 File 数据模块中产生一个相应的输入栏,我们在该输入栏的 Operating
System File Name 项中输入 Model 10-02 Input.txt,不管模型文件保存在什么地方,也不管
ReadWrite 模块什么时候引用 Arena 的 Arrivals File,Arena 都会去访问 Model 10-02 Input.txt。
读者也可以给出文件的完整路径,如 C:\My Documents\Cool Stuff\Model 10-02 Input.txt,但是
如果读者决定把这个模型和数据文件发给其他人,他们也必须有同样的文件夹结构,才能保
证正确读取数据。File 数据模块的其它选项都保留默认值,包括文件类型 Free Format(表
示 Model 10-02 Input.txt 文件包含文本值),以及 end-of-file action 选项也保留 Dispose 值,这
样控制实体读完文件的最后一个值后就会离开系统,从而有效地终止模型的实体到达。
原书 P407
图 10-10. File 数据模块
让我们使用图 10-4 的数据值来描述前两个呼叫的仿真逻辑,在仿真时刻 0(即仿真实
验开始的时刻),控制实体先读取一个值 1.038 并将其赋给 Call Start Time 属性,然后延迟
(1.038-0)时间单位。在 1.038 时刻控制实体离开 Delay 模块,并产生一个副本进入 Queue
模块开始呼叫的实际处理过程。控制实体返回 ReadWrite 模块,从数据文件中读取下一个值
2.374 并将其赋给 Call Start Time 属性,然后进入 Delay 模块,延迟(2.374-1.038=1.336)时
间单位,Arena 将在未来事件表中产生一个与控制实体有关的新的事件,该事件在未来的
1.336 个时间单位发生,即在实际的未来时刻 2.374 发生,该事件发生之后控制实体将到达
Separate 模块,在那里产生一个呼叫实体,该实体的 Call Start Time 属性值 2.374 表示第二个
呼叫进入系统的时刻。当控制实体将 Model 10-02 Input.txt 文件的全部数据读取完成之后,
这个过程即告结束。
有两个条件可以终止仿真的运行。第一,数据文件中列出的呼叫还没有发生完,如果仿
真已经达到了 Run Setup 对话框中所设定的运行终止时间,Arena 将在该时刻终止仿真运行,
因为任何一个模型的运行时间都不可能超过事先设定好的仿真终止时间;第二,还没有达到
事先设定好的仿真终止时刻,但是数据文件中列出的呼叫都已经产生,并且处理完成离开系
统,未来事件表变空,此时 Arena 就会在事先设定好的终止时刻之前停止仿真运行(还记得
控制实体读取完数据文件的最后一个数据之后就离开系统吗?),因为在未来事件表中没有
实体并且没有额外的基于时间的控制需要处理的时候,Arena 将在最后一个实体离开模型之
后终止仿真运行。
10.1.2 模型 10-3 和 10-4:读和写 Access 和 Excel 文件
如果保存呼叫到达数据的不是文本文件,而是微软的 Access 数据库或者 Excel 电子表
格,那该怎么办呢?下面的介绍将使读者认识到,在 Arena 中处理这些问题是很简单的。
首先假定保存呼叫到达信息的是 Access 数据库文件,并且相关数据存储在名叫 Arrival
Times 的表中,图 10-11 显示了该文件(Model 10-03 Input.mdb)的前面一些数据值。
原书 P408
图 10-11. Access 表中的呼叫时间数据
从上节我们建立的模型 Model 10-02.doe 开始,只需做少量的改动即可完成读取数据库
的功能。读取和使用数据来控制实体产生过程的模型逻辑依然有用,我们只需改变获取数据
的一些细节。
这次从描述新的数据文件开始。编辑高等操作面板中已经存在的 File 数据模块,如图
10-12 所示。保留 Name 项为 Arrivals File,回顾一下,这项内容是在模型逻辑(本例中为
ReadWrite 模块)里用来标识文件的,没有必要改变它,但是我们必须将 Operating System File
Name 项改为 Model 10-03 Input.mdb1,而其它大多数选项都保留默认值,包括 End of File
Action 的值 Dispose,这就像以前一样,控制实体读完文件的最后一个值就离开仿真系统。
读者将注意到 Access Type 项有一个可供选择的下拉列表,在这里选择 Microsoft Access
(*.mdb),有关字段(列)和以前不一样了,这是因为读取数据库文件需要和文本文件不同
的信息。特别是出现了一个标有初始值为 0 rows 的按钮,在该按钮上方有一个新的列,标
1 使用扩展名为.mdb(Access 文件的默认格式)的文件时请注意,不要和 Arena 模型重名。Arena 自动将其
输出信息保存在文件 ModelName.mdb 中(其中 ModelName 为 Arena 模型文件名称),任何同名的文件都将
被其覆盖。
记为 Recordsets,单击按钮打开如图 10-13 所示的记录集编辑器。
原书 P409
图 10-12. File 数据模块
读取数据库的时候,其实是从表或行和列中读取记录的集合。一个数据库可能有多个不
同的记录集,Arena 通过定义 Recordset Name 来区分每一个记录集,每个 Recordset Name
必须和数据库的一个表建立联系。读者可以选取任何合法的标识名称作为 Recordset Name
的值,方便起见,我们在这里输入表名 ArrivalTimes。单击 Add/Update 完成记录集的定义。
单击 Table Name 下面的下拉列表框的箭头将显示数据库中当前定义好的所有表,本例中选
择唯一的表 ArrivalTimes,如图 10-13 所示。如果读者想浏览某个记录集的一些数据,请先
在左栏中选定该记录集,然后单击 View 按钮,浏览之后单击 Close 按钮关闭浏览窗体。最
后单击 OK 按钮退出记录集编辑器。
原书 P409
图 10-13. 记录集编辑器
读者可能想知道我们为什么要先改变文件属性,而不是先修改 ReadWrite 模块。如果现
在打开 ReadWrite 模块(如图 10-14 所示),可以看到它有些不一样了,事实上,ReadWrite
模块将自动获取所读文件类型的有关信息,本例中,它判断出要读取数据库并且需要确定记
录集。我们从下拉列表中选取 ArrivalTimes,如果读者想控制每次循环要读取的记录,请在
Record Number 项输入一个任意的表达式,但我们在此保留其默认值,即不填写任何数据,
这 样系 统 将 从第 一 条 记录 开 始顺 序 读 取。 还 记 得我 们 不必 改 变 Arena 的 File Name 和
Assignments 项吧,所以单击 OK 按钮完成设置。
原书 P410
图 10-14. ReadWrite 模块
就这样简单,一切就绪,保存读者最新创建的模型,或者在读者的 CD 上查找文件 Model
10-03.doe,现在可以运行模型,从 Access 文件而不是文本文件中读取数据了。
如果读者从第一节开始一直跟着我们学习,现在应该就已经知道了读取 Excel 电子表格
文件要做的大多数工作了。读者可能已经注意到 Excel 电子表格的行和列与数据库表的行和
列非常相似,Excel 不是关系数据库管理系统,但是很多地方我们都可以像处理 Access 数据
库文件一样处理它。
在 Excel 里,一个矩形区域即单元格或行和列的集合等价于一个 Access 数据库表的行
和列,如果我们想将其看作一个数据库(事实上我们在这里的确是这样处理的),命名的区
域 就 必 须 包 含 至 少 两 个 单 元 格 。 读 者 可 以 通 过 选 定 单 元 格 集 合 , 然 后 选 择 菜 单
Insert->Name->Define,输入一个名字,来创建 Excel 的命名区域。例如,如果选定单元格
A3 到 C9 并且按照上述步骤进行,将工作簿选定区域命名为 MyRange,读者将得到非常类
似 Access 表的三行和七列,如图 10-15 所示。如果查看名称下拉列表(一般都在菜单工具
栏的左上角处),可以看到已经定义好的所有单元格区域的名称,同样的,这些区域和 Access
数据库表也是等价的。
原书 P411
图 10-15. Excel 电子表格的呼叫数据
让我们重新开始刚刚在上面建立起来的模型 Model 10-03.doe,把它修改成从 Excel 而不
是 Access 中读取数据。提供的例子数据文件 Model 10-03 Input.xls 如图 10-15 所示,可以看
到区域 ArrivalTimes 在名称框和工作簿里都被突出显示。如图 10-16,我们仍然从描述现有
的 File 数据模块中的新数据文件开始,除了更改 File Name 和 Access Type 两项以外,其余
设置都可以保留和读取 Access 数据库文件一样,将 Operating System File Name 项改为 Model
10-03 Input.xls,在 Access Type 下拉列表中选择 Microsoft Excel (*.xls)。