如何为一种代理类型设置不同的初始状态?

How can I have different initial state for one agent type?

我正在研究流行病模型。在这个模型中,有 2 种易感状态,S1 和 S2。在模型开始时,我希望代理处于 S1 状态和 S2 状态。 比如我一开始总共有1000个代理,我希望S1有200个,S2有800个。

我尝试将 S1 设置为开始状态并创建从 S1 到 S2 的消息转换,然后在 main 中编码为:

for(int i = 0; i < 1000*0.8; i++)
    send("s1 to s2", people.random());

但是会造成同一个agent的重复消息,所以S2状态下不会有800。我也觉得这不是一个好的设计。

您需要一些代码来执行 selection-without-replacement 这样您就不会多次选择同一个代理。 AnyLogic 没有 built-in 可以为你做这件事,所以你需要类似下面的代码(假设你的代理是 Person 类型)。

// Create selection list with all Person agents in
List<Person> selectionList = new ArrayList<Person>();
for (Person p : people) {
   selectionList.add(p);
}

// Select one 800 times (removing them from our selection list as we go)
for (int i = 0; i < 800; i++) {
   int randomIndex = uniform_discr(0, selectionList.size() - 1);
   send ("s1 to s2", selectionList.get(randomIndex));
   selectionList.remove(randomIndex);
}

要记住的关键事情(也是许多 AnyLogic 建模者不理解的事情)是发送到状态图的消息是异步处理的(在您可以看到的隐藏超时 0 事件中在运行时的事件视图上)然而 你发送它们(例如,无论你使用 sendreceive 还是状态图的 fireEvent 函数 ---这些只会影响此类中间事件的 数量 以及是否触发 Connections 元素的“On message received”操作。

因此,代理 永远不会 在向他们发送消息的代码块中更改状态。 (它只会在此代码块 --- 以及触发它的当前事件 --- 完成后这样做。)

P.S。根据您对 Emile(不正确)回答的评论,另一种方法是通过动态事件,以便在处理前一条消息后发送每条消息。但是你必须非常小心,确保 at-the-same-sim-time 事件排序正确(这里有大量细微的细节),你仍然必须在 Emile 的答案中进行过滤,这是非常浪费的;更容易做到这一点概念上更正确的方法,你可以在你进行时减少你从中抽样的代理集。