我正在使用基于代理的流行病模型。这个想法是个体代理根据他们在网络中观察到的内容(基于距离)做出决策。我在每个代理中都有几个功能,可以动态更新受感染联系人的计数,显示特定行为的联系人等。
以下代码用于计算代理网络中受感染的联系人。
int infectedConnections = 0;
if (getConnections() != null)
for (Agent a : this.getConnections())
{
Person p = (Person) a;
if (p.IsCurrentlyInfected())
infectedConnections++;
}
return infectedConnections ;
至少还有3个这样的功能可以在代理网络中保留表示其他功能的其他代理的计数。现在,当我有500个代理时,这似乎运行好了,但是当我将代理人数增加到大约1000左右时,模型变得极其缓慢。我希望模拟至少5,000个代理商,此时,该模型甚至不会初始化。
对于较大的人群,是否有更加计算有效的方法来跟踪Anylogic中的网络统计数据?
答案 0 :(得分:2)
模型未初始化,因为5000个代理的默认内存量不足。如果每个代理与所有其他代理连接(每个代理4999个连接),则需要> 1.300 Mb的RAM,而默认模拟实验仅分配512 Mb的RAM。更改实验属性中的内存量。然后,对于所有5000个代理程序,代码大约需要1个实时秒。换句话说,如果我每秒收集统计数据,最大执行速度大约是1个模型秒/ 1真实秒。
如果使用Java Stream API重写代码,则可以增加它:
return (int)getConnections().stream()
.filter( a -> (Person)a).IsCurrentlyInfected())
.count();
然后,以0.5真实秒(x2增益)执行1个模型秒。如果统计信息收集是并行执行的(具有由Java代码创建的多个线程),那么您可以获得相应的增益,具体取决于PC上的核心数量。 无论如何,这是计算复杂性问题,所以你需要改变方法(see @pjs answer),否则性能真的很差。
答案 1 :(得分:1)
你所看到的基于代理的模型的结果是,事情陷入1000到5000之间。这是一个基本的计算复杂性问题。对于N个代理,双向交互的数量是N.choose.2,即O(N ^ 2)。 5000名代理人的工作量大约是1000名代理商的25倍。
你可以通过本地化来吸引一些特技。基本上,根据特定区域中的代理无法与其他区域中的代理交互这一事实,将您的沙箱划分为不同的游戏区域,因此您只需要检查交互的子集。如果可能的话,将N个代理划分为k个独立分组,将在运行时间内产生O(k)倍的改善。
另一种选择可能是摆脱时间步骤框架,为您的问题制定基于事件的设计。您可以在this paper中找到此方法的示例。
答案 2 :(得分:0)
正如其他答案所涵盖的那样,您的问题实际上是两个问题:
内存使用情况和'底层'随着代理数量的增加,网络连接总量增加导致模型速度增加;
您的统计数据收集效率。
我很惊讶没有人提到它,但后者的另一个显而易见的选择是,如果您只是保留当前感染数量的统计数据,为什么不让代理商更新相关计数呢?进入/离开受感染状态(通过AnyLogic状态图以及通过函数表示其他方式的'实际'状态等)?同样,对于其他网络传输状态变化的任何统计数据......