【问题标题】:Discrete Event Simulation without global Queue?没有全局队列的离散事件模拟?
【发布时间】:2014-04-12 14:42:11
【问题描述】:

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

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

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

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

所以

  • 有人知道不需要全局队列的 DES 算法吗?
  • 这有什么困难甚至不可能的原因吗?
  • FRP 在 DES 环境中有用吗?

【问题讨论】:

    标签: functional-programming simulation reactive-programming frp


    【解决方案1】:

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

    或者,您可以放弃 DES 并执行更类似于 可编程逻辑控制器 (PLC) 的操作,该控制器每隔一小段时间就重新评估整个网络的状态。但是,通常情况下,这会慢很多(它甚至可能没有实时运行那么快),因为大多数时候它什么都不做。如果您选择的时间增量太大,模拟可能会失去准确性。

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

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

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

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

    我希望这会有所帮助!

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

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

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

    【讨论】:

    • 在你的鼓励下,我多看了一点 FRP,根本看不到事件队列。在 FRP 样式的 DES 中,您在哪里看到队列?
    • 我很乐意回答这个问题,但您能否澄清一下“查看队列”的含义?我不确定我是否理解这个问题。
    • 在 Sodium 和 Reactive Banana (Haskell) 中,一切似乎都围绕着行为(又名信号)和事件以及组成其网络的方式。没有明确的队列概念。当您以 FRP 方式进行 DES 时,全局事件队列在那里扮演什么角色?
    • 听上去(我不熟悉 Sodium、Reactive Banana 或 Haskell),似乎事件队列隐藏在 Behaviors/Signals 和 Events 后面。
    • (哎呀!点击返回有点早。)换句话说,仍然有一个全局事件队列,用于调度事件并分派它们执行,但您无法直接访问它。这是很正常的,因为除了调度/取消调度事件之外,最终用户模拟代码不应该能够操纵事件队列。当您指定在一段时间后发生的行为时,您(在后台)创建了一个事件,将该事件添加到事件队列中,并指定当事件被调度时会发生什么(动作)。希望这会有所帮助。
    猜你喜欢
    • 1970-01-01
    • 2021-12-31
    • 2011-04-29
    • 2012-10-22
    • 1970-01-01
    • 2017-09-20
    • 2017-05-31
    • 2017-12-30
    • 2019-09-07
    相关资源
    最近更新 更多