想象一下,你已经为一个复杂的模型工作了几个月,就在它快要准备就绪的时候,客户要求你对它进行重大修改。未来几天的额外工作、结构调整,以及试图加入一些最初并不打算加入的东西。听起来令人生畏,不是吗?
是否有办法避免出现这种情况,或至少使其不那么痛苦?答案就在于建立一个坚实的模型基础,为灵活性留有余地,并让您能够完全控制仿真。
本杰明-舒曼(Benjamin Schumann)博士是一位拥有十多年经验的仿真专家,他在研讨会上重点介绍了如何构建仿真模型,使其在需要实施突然的变更时不会崩溃。该研讨会在AnyLogic的全球会议上发表,现在已在网上分享,它为所有技能水平的人提供了如何建立稳健模型的详细指导。
这篇博客文章概述了最新的“如何构建模型,使其永不崩溃”研讨会,该研讨会以工厂模型为例,帮助初学者、高级和超高级AnyLogic用户深入了解技术细节。
您可能还会对早前的一篇博文感兴趣,这篇博文收录了 Ben 一段更基础的视频,其中他谈到了模型结构的主题,即嵌入智能体、智能体继承和模型重构
目录
基础知识:可视化结构和嵌入式智能体
刚开始使用 AnyLogic 的用户往往只需在画布上拖放元素即可建立模型。这种方法简单快捷,适合小型项目。但是,对于大型复杂模型,Ben 建议采取更安全的方法,虽然时间更长,但首先要打下坚实的基础。
与其在画布上堆积模型元素,您可以将它们归类为五颜六色的矩形,如下图所示,每个智能体都有自己的矩形。您还可以在这些矩形中定义每个智能体类型的功能。例如,您的Main智能体只能保存实际模型和处理数据。

大多数AnyLogic用户下一步会直接在Main智能体中构建模型逻辑。但Ben的建议是,将其放入一个名为Model的单独智能体中,然后将其嵌入Main中。所有这一切都为项目后期带来了透明度和灵活性。
要想获得更高的灵活性和对智能体的控制,您应该始终创建一个初始为空的智能体群,而不是单一智能体类型。

在研讨会的工厂仿真示例中,有两个智能体——产品和机器。Ben 在 Model 中为每个代理创建了一个单独的代理。这里的另一个建议是,在Main中使用智能体状态图绘制一个简单的层次结构方案。这样做将帮助您跟踪模型中智能体之间的关系。

模型正确性检查和更多智能体分层技巧是本节视频的主要内容。
提高技能:流程图和面向对象的编程概念
由于用户倾向于将模型逻辑放在Main中,因此在大型复杂项目中可能会变得杂乱无章,从而容易出错。简化流程建模图的一种方法是为重复的模块序列创建自定义流程图块。另一种解决方案是将流程图拆分,使其不同部分位于各自的智能体中。让我们详细研究一下第二种方法。
回到工厂仿真的例子,假设机器智能体(A_Machine)和产品智能体(A_Product)有自己的流程图。产品逐一访问机器,每个产品都有一个必须访问的机器的待办事项列表。
为了启动这个流程,Ben首先创建了一个函数,该函数允许他控制在模型运行时创建机器或产品的顺序。其次,他设置指定智能体的参数。通过遵循面向对象编程的封装原理,他为每个代理单独设置参数的方式将在未来对他有所帮助——如果情况需要更改模型,他就不用大量重写代码。
如果每个智能体都有自己的流程图,那么作为一个系统,这一切又是如何运作的呢?
产品运抵工厂后,进入第一台机器进行加工:

然后经过一段时间的加工,再转移到下一台机器或离开工厂:

当机器完成产品加工并准备出厂时,它会将产品发送到Main中的Sink模块。

提升您的技能:通用KPI和动画
良好模型的关键原则之一是将逻辑与可视化分离。遵循这一原则,Ben建议创建单独的智能体,这些智能体将探查其相应的智能体(在我们的示例中,它们是A_Machine和A_Product),并以图表的形式告诉您它们的执行情况。这也有助于让您完全控制通用KPI,避免测量智能体活动时出错,并使逻辑智能体计算更加高效。
您可以通过一些Java技巧、创建探查智能体并设置它们的参数和函数来实现这一点。最后,您需要使用更多的Java代码来使Main理解如何显示机器的KPI。

关于动画,可以应用一个简单的规则:如果模型中有应该移动的对象,则直接在逻辑智能体中设置动画。否则,就将其设置为探查。
更进一步:仪表板和数据处理
既然你有不同的探查智能体来显示统计数据,为什么不把它们组合在一个名为Dashboard的新智能体中,这样你就可以灵活地创建你想要的任何仪表板了?例如,您可以选择只显示机器的图表以及在仪表板上放置机器实际动画的确切位置。
如果您想在仪表板上添加更多的智能体类型,比如产品,那么您只需创建另一个参数、智能体群(pop_UI_Product)和一个创建产品的函数。然后按照您希望的方式定位仪表板。
Dashboard智能体本身应嵌入Main中,并且您应创建一个启动动画的函数。

在研讨会的最后,Ben 分享了加载和存储模型数据的技巧。良好建模的共同原则是<将数据与模型分开,而他的建议是更进一步,在中间多加一层--模型输入。为什么他认为这种方法很强大?
真实数据可能是杂乱无章的,而且会随着时间的推移而变化,而模型需要格式化和干净的数据才能继续运行。模型输入层的作用就是将数据转化为模型,使其始终有经过处理的输入可供使用。此设置还有另一个用途——测试。
因此,如果真实的数据结构发生了变化,你只需要对这个模型输入层稍作修改,模型仍然可以正常工作。它不会受到影响。
为此,首先需要将数据添加到Excel电子表格中。然后为每个数据结构(例如机器)创建一个名为POJO(普通Java对象)的Java类,并使用Java代码复制该结构。


下一步是创建一个名为数据输入的Java类,该类一方面从Excel文件加载数据,另一方面创建用于测试的新数据。

现在,您可以通过Model智能体中的输入数据(使用参数)来定义模型。因此,当您需要为工厂机器添加更多特性时,就不必为此创建数十个新参数了。
在Main中,您需要正确设置智能体的行为。启动模型时,Main应该能够首先加载数据,然后创建模型及其智能体,最后启动动画(这是一个可选步骤)。
关键要点和研讨会视频
本研讨会中的技巧和方法看起来可能不容易快速实施,但它们为您提供了灵活性和对模型的完全控制,这在大型复杂项目中至关重要。
概括而言,以下是本次研讨会的四个要点:
- 如果您是初学者,请使用Model作为嵌入Main中的智能体。
- 如果您的水平稍高,请开始封装您的代理和函数。请记住,智能体是通过参数指定的,函数是通过自变量指定的。
- 将动画与模型的逻辑分离。创建能够跟踪其他智能体表现的探查智能体。不需要动态动画属性,您有探查智能体,只需要不时地更新它们。
- 不要将真实数据与模型分离,而是在两者之间设置一个模型输入层。这种方法使您独立于客户的数据,并使您的模型更加稳健。
观看“如何构建模型,使其永不崩溃”研讨会,深入了解更好的仿真建模实践。
订阅我们的月度资讯,以便我们将最新的博客文章直接发送到您的收件箱。