通常,您应该在(连续)离散事件模拟器中使用使用一个事件队列。我不太清楚'过期'事件的含义,但是如果这些事件因为无效而被忽略,一个简单的解决办法就是丢弃它们而不是处理它们,例如,看到这个伪Java代码:
while (!terminationConditionMet() && !eventQueue.isEmpty()) {
Event currentEvent = eventQueue.getNextEvent();
if(currentEvent.isExpired())
continue;
List<Event> newEvents = currentEvent.process();
eventQueue.addEvents(newEvents);
}
通常(对于足够大的事件集),这应该比每个步骤后重新排序事件列表快得多。
顺便说一句,许多事件队列实现在O(1)中实现出队,即使对于某些操作来说它们的性能可能并不比排序更好,但实际实现工作要好得多(即它们具有较小的常量/更好的平均表现)。如果您正在使用Java,则可能需要查看JAMES II,它提供了几个事件队列实现,并且是开源的(免责声明:我是开发人员之一)。
EDIT(寻址重新配制问题):
一般而言,实施过程基于离散事件模拟的一种方便的方法是coroutines,参见例如this report获取详细信息。如果你要坚持你的实现,但是,你仍然可以更改优先级,以一个元组(timeStep,processPriority)
和按如下方式使用上述伪代码的改编版:
while (!terminationConditionMet() && !queue.isEmpty()) {
//Read out event
Tuple minTime = queue.getMinTime();
ProcessEvent currentEvent = queue.dequeue();
//Execute event
List<ProcessEvent> newlySpawnedProcesses = processEvent.process();
//Re- and enqueue new events
int nextTimeStep = minTime.getTime() + 1;
if(!currentEvent.finalStateReached())
queue.requeue(currentEvent, new Tuple(nextTimeStep, currentEvent.getPriority()));
for(ProcessEvent event : newlySpawnedProcesses)
queue.enqueue(event, new Tuple(nextTimeStep, event.getPriority()));
}
当然,这是假定你是使用足够通用的事件队列实现,以允许您指定自己的时间/优先级顺序,例如通过指定自定义比较器。
因此,如果一个事件应该再次处理,它本身是'newEvents'的唯一项目?另外,添加比当前正在处理的优先级更低的事件会产生任何奇怪的现象吗?在某种程度上,它看起来会得到一个额外的处理与在同一更新周期中添加更高优先级的事件。 – abr 2012-07-10 17:04:29
是的,任何由'currentEvent'处理引起的事件都会在'newEvents'中,这可能包括事件本身(尽管这很不寻常,因为它有点打破了“事件”的隐喻,只发生[一次],并可能导致新的事件)。如果事件的重新插入在您的应用程序中经常发生,您还可以检索(但不是出列)当前事件,然后以新的优先级“重新插入”它。一些专门为模拟构建的事件队列提供了此操作。这可能比排队一个新事件便宜得多。 – 2012-07-11 05:52:56
无论如何,谨防_premature optimization_:在你使事件调度过于复杂之前,使用一个分析器来查看这是否真的是性能瓶颈。关于添加低优先级事件的“怪异”,这很大程度上取决于您的应用程序。我看到的一个危险是,你可能会在某个优先级(时间)被“卡住”,或者甚至在时间后退(这又一次打破了隐喻)。相反,您可以考虑将您的优先级设为二维,例如。元组(时间,事件优先级),并允许在当前时间重新调度低优先级事件。 – 2012-07-11 06:00:47