没有全局队列的离散事件模拟?

时间:2014-03-09 15:33:44

标签: functional-programming simulation reactive-programming frp

我正在考虑建立物流网络。有一些以一定速度运行的进程,可以溢出或下溢的缓冲区以及它们之间的连接。

我没有看到使用全局事件队列以经典的离散事件模拟(DES)方式对此进行建模时出现任何问题。我尝试在没有队列的情况下对系统建模,但在早期阶段失败了。我仍然不明白为什么需要队列的根本原因,至少不是因为在网络“内部”发生的事件。

无队列DES的想法是将整个网络视为一个函数,它接收来自外部世界的事件流并返回状态变化流。网络中的每个节点只应受与其直接连接的节点的影响。我总体上对Haskell的箭头和功能反应式编程(FRP)寄予了一些希望,但我仍然在学习。

事件队列对我来说太“全球化”了。如果我的网络分成两个子网,它们之间没有连接,我只询问有关一个子网的状态变化的问题,另一个子网根本不应该进行任何计算。在这种情况下,我可以使用两个事件队列。但是,只要连接两个子网,我就必须将所有事件放入一个队列中。我不喜欢这个想法,我需要知道网络的拓扑结构才能设置我的队列。

所以

  • 是否有人知道DES算法不需要全局队列?
  • 有什么理由说这很困难甚至不可能吗?
  • 是FRP在DES的上下文中有用吗?

1 个答案:

答案 0 :(得分:6)

回答第一点,不,我不知道任何不需要全局事件队列的离散事件模拟(DES)算法。可以具有事件队列的层次结构,其中每个事件队列在其父事件队列中表示为事件(对应于其下一事件的时间)。如果将新事件添加到事件队列以使其成为队列的下一个事件,则需要在其父事件中重新调度事件队列以保留事件执行的顺序。但是,您最终仍将归结为单个全局事件队列,该队列是层次结构中所有其他事件的父级,并且会调度每个事件。

或者,您可以省去DES并执行更类似于可编程逻辑控制器(PLC)的操作,它可以每隔一小段时间重新评估整个网络的状态。但是,通常情况下会慢得多(它甚至可能不像实时那样快),因为大部分时间它都没有任何关系。如果选择太大的时间增量,模拟可能会失去准确性。

对第二点的最简单答案是,最终,据我所知,没有全局事件队列是不可能的。每个模拟事件都需要在正确的时间执行,并且 - 由于时间不能倒退 - 事件的调度顺序很重要。当前模拟时间由当前事件执行的时间定义。如果你有单独的事件队列,你也有单独的时钟,至少可以说会让事情变得非常混乱。

在您的情况下,如果子网完全独立,则可以单独模拟每个子网。但是,如果一个子网的状态影响整个网络的状态,并且整个网络的状态影响每个子网的状态,那么 - 由于事件受到其之前的事件的影响,因此只能影响事件跟随,但不能影响它之前的内容 - 你必须用全局事件队列模拟整个网络。

如果是任何安慰,真正的DES模拟不会在事件之间执行任何处理(其他确定下一个事件是什么),因此如果所有操作都发生在另一个子网中,则不应该在一个子网中浪费处理

最后,功能反应式编程(FRP)在DES的上下文中绝对有用。实际上,我现在使用这种方法在Scala中编写了很多我的DES模拟。

我希望这有帮助!

更新:自上述以来,我使用了 Sodium (一个优秀的 FRP 库,其中引用了下面的评论中的OP,并且可以添加一些进一步的解释: Sodium 提供了订阅事件以及在事件发生时执行操作的方法。但是,在这里我使用的术语 event 在一般意义上,例如用户在 GUI 中点击的按钮,或到达的网络包等。换句话说,事件不一定是模拟事件。

您仍然可以使用 Sodium - 或任何其他 FRP 库作为模拟的一部分,订阅模拟事件并在事件发生时执行操作;但是,这些工具通常没有内置的模拟支持,因此您必须将模拟引擎作为模拟事件的来源,就像将 GUI 合并为用户来源一样互动活动。全局事件队列必须驻留在此引擎内。

顺便提一下,如果您尝试执行并行或分布式仿真模型执行,事情会变得相当复杂。在这些情况下,您有多个事件队列,但必须同步它们(给出单个队列的外观)。两种基本方法是保守同步乐观同步