Sorting 事件模拟是否需要优先级队列?

Sorting 事件模拟是否需要优先级队列?,sorting,heap,simulation,priority-queue,heapsort,Sorting,Heap,Simulation,Priority Queue,Heapsort,现在在我的基本事件模拟引擎中,我只是在模拟的每个步骤中根据事件对象的优先级更新事件对象列表。我这样做是因为可以在事件更新期间创建新事件并将其附加到列表中,并且当事件过期时,我只是将其与列表中的最后一个事件“交换并弹出”以提高性能。我应该只使用两个优先级队列吗?似乎对每个步骤进行排序的n log n至少与清除所有事件(n log n?)的成本相同,如果不低于将每个未过期的事件放入另一个列表中的成本,该列表内置于下一个更新步骤的优先级队列中 编辑:我认为更倾向于将“事件”称为“流程”,而将整个事件称

现在在我的基本事件模拟引擎中,我只是在模拟的每个步骤中根据事件对象的优先级更新事件对象列表。我这样做是因为可以在事件更新期间创建新事件并将其附加到列表中,并且当事件过期时,我只是将其与列表中的最后一个事件“交换并弹出”以提高性能。我应该只使用两个优先级队列吗?似乎对每个步骤进行排序的n log n至少与清除所有事件(n log n?)的成本相同,如果不低于将每个未过期的事件放入另一个列表中的成本,该列表内置于下一个更新步骤的优先级队列中


编辑:我认为更倾向于将“事件”称为“流程”,而将整个事件称为流程调度模拟。队列中的每个对象都按优先级顺序更新其状态,然后只有当它已过期(进入某种结论状态)时,才会丢弃它,而不会重新插入队列。这就是为什么只有一个优先级队列会成为一个问题;重新插入对象时,它的优先级仍然最低,只需再次拉出即可。我正在考虑使用第二个队列插入所有新生成的进程对象和未过期的进程对象,不考虑优先级,然后我可以在下一个更新周期开始之前构建堆并将其与活动队列交换。

通常,您应该在一个(顺序)队列中使用一个事件队列离散事件模拟器。我不太清楚“过期”事件的含义,但如果这些事件因不再有效而被忽略,一个简单的解决方案是丢弃它们而不是处理它们,例如,请参见以下伪Java代码:

 while (!terminationConditionMet() && !eventQueue.isEmpty()) {
   Event currentEvent = eventQueue.getNextEvent();
   if(currentEvent.isExpired())
     continue;
   List<Event> newEvents = currentEvent.process();
   eventQueue.addEvents(newEvents); 
 }

当然,这假设您使用的事件队列实现足够通用,允许您指定自己的时间/优先级顺序,例如,通过指定自定义比较器。

因此,如果需要再次处理事件,它本身就是
newEvents
的唯一项?此外,添加优先级低于当前正在处理事件的事件是否会产生任何奇怪的情况?在某种程度上,与在同一更新周期中添加的具有更高优先级的事件相比,它似乎会得到额外的处理。是的,由处理
currentEvent
引起的任何事件都将在
newEvents
中,这可能包括事件本身(虽然这是相当不寻常的,因为它在某种程度上打破了
事件的隐喻,即简单发生[一次]并可能导致新事件的事件)。如果事件的重新插入在应用程序中定期发生,您也可以检索(但不可以出列)当前事件,然后用新的优先级重新查询它。一些专门为模拟而构建的事件队列提供了此操作。这可能比将新事件排入队列便宜得多。无论如何,要小心过早优化:在使事件调度过于复杂之前,请使用探查器查看这是否真的是一种性能e瓶颈。关于添加低优先级事件的“奇怪性”,这在很大程度上取决于您的应用程序。我看到的一个危险是,您可能在某个优先级(时间)上“卡住”,甚至在时间上倒退(这再次打破了隐喻)。相反,您可以考虑将优先级设置为二维,例如元组(时间,事件优先级),并允许在当前时间重新安排优先级较低/较高的事件。啊,是的,协同路由。我基本上是在尝试“伪造”协同路由,就像你在Java的Lua中看到的那样。啊,我明白了。你看过了吗?无论如何,祝你好运!
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()));     
}