Frage

Ich würde schätzen Hilfe Debuggen ein seltsames Verhalten von einem multiset Behälter. Gelegentlich erscheint der Behälter Sortierung zu stoppen. Dies ist ein seltener Fehler, offensichtlich in nur einige Simulationen nach langer Zeit, und ich bin kurz auf Ideen. (Ich bin ein Amateur-Programmierer - Vorschläge aller Art sind willkommen.)

Mein Container ist ein std::multiset der Event structs gilt:

typedef std::multiset< Event, std::less< Event > > EventPQ;

mit dem Event structs sortierte nach ihren double time Mitgliedern:

struct Event {

 public:
explicit Event(double t) : time(t), eventID(), hostID(), s() {}
Event(double t, int eid, int hid, int stype) : time(t), eventID( eid ), hostID( hid ), s(stype) {}

  bool operator < ( const Event & rhs ) const {
    return ( time < rhs.time );
  }

  double time;
  ...
};

Das Programm durchläuft Zeiten der Ereignisse mit ungeordneten Zeiten EventPQ currentEvents Hinzufügen und dann Ereignisse, um das Abziehen. In seltenen Fällen nach einigen Ereignissen (mit perfekt ‚legal‘ mal) hinzugefügt wurden, beginnen Ereignisse immer der Reihenfolge ausgeführt werden.

Was die Ereignisse machen könnte immer nicht richtig bestellt werden? (Oder was könnte Iterator vermasseln?) Ich habe überprüft, dass alle die zugegebenen Ereigniszeiten legitim sind (dh alle die aktuelle Simulationszeit nicht überschreiten), und ich habe auch bestätigt, dass der Fehler nicht, weil zwei Ereignisse auftritt happen erhalten geplant für die gleiche Zeit.

Ich würde gerne Vorschläge, wie Arbeit durch diese.

Der Code für die Ausführung und Veranstaltungen ist das Hinzufügen unten für Neugierige:

  double t = 0.0;
  double nextTimeStep = t + EPID_DELTA_T;
  EventPQ::iterator eventIter = currentEvents.begin();

while ( t < EPID_SIM_LENGTH ) {

     // Add some events to currentEvents

     while ( ( *eventIter ).time < nextTimeStep ) { 

         Event thisEvent = *eventIter;
     t = thisEvent.time;
     executeEvent( thisEvent );
     eventCtr++;
     currentEvents.erase( eventIter );
     eventIter = currentEvents.begin();

  }

  t = nextTimeStep;
  nextTimeStep += EPID_DELTA_T;
}


void Simulation::addEvent( double et, int eid, int hid, int s ) {
  assert( currentEvents.find( Event(et) ) == currentEvents.end() );

  Event thisEvent( et, eid, hid, s ); 
  currentEvents.insert( thisEvent );
}

sollte ich, dass gelegentlich ein Ereignis hinzufügen, wenn sie ausgeführt werden, werden andere Ereignisse aus currentEvents löschen. Dies geschieht mit

double oldRecTime = 10.0; // gets defined legitimately in simulation
EventPQ::iterator epqItr = currentEvents.find( Event(oldRecTime) );
assert( currentEvents.count( Event(oldRecTime) ) == 1 );
currentEvents.erase( epqItr );

Auch wenn dieser Code sieht okay, ich mag andere Möglichkeiten, wissen, ich untersuchen kann, was los ist -. Ich bin zur Zeit viel behauptet, mit () und cout << Kontrollen

War es hilfreich?

Lösung 3

In der Simulation, wo ich bemerkt habe

// Add some events to currentEvents

Veranstaltungen wurden zu Current hinzugefügt. (Ich hoffe, das war klar.) Wenn ein Ereignis wurde hinzugefügt, dass an der Spitze der Warteschlange gehören passiert ist, ich glaube, verwirrte es den Iterator zeigt auf currentEvents.begin nach oben (). I setzen Sie den Iterator unmittelbar vor der inneren while-Schleife, und die Dinge erscheinen zu arbeiten.

Ich werde diese Frage aktualisieren, wenn diese erweist sich als nicht die Lösung sein, oder wenn es andere Probleme in dem, was ich hier habe.

Vielen Dank an alle diejenigen, die kommentiert; es hilft mir lernen, wie ich diese Probleme nähern sollte.

Andere Tipps

Ihr Ereignisverarbeitungszyklus nicht zu prüfen, ob die Warteschlange leer ist. Ansonsten alles sieht gut aus (mehr oder weniger).

Aber wenn Sie laufen von Ereignissen in Ihrer currentEvents Warteschlange wird das Verhalten nicht definiert. Es könnte wahrscheinlich manifestieren sich als etwas das Symbol angezeigt wird als Ereignis wird der Auftrag bearbeitet werden.

In der Tat, einige Implementierungen von assoziativen Containern ich sie dargestellt sah durch „nahezu kreisförmige“ Datenstrukturen, in einem gewissen Sinne, dass, wenn Sie das Ende der kontrollierten Sequenz ignorieren und weiter zu wiederholen, wird Ihr Iterator am Anfang der emerge Reihenfolge. Könnte es sein, dass so etwas sein wird in Ihrem Fall passiert?

Eine andere Frage, die unmittelbar im Zusammenhang mit Ihrem Code entsteht: Was passiert, wenn das neue Ereignis der Warteschlange mit dem time Wert gelangt in die kleiner als die „aktuelle“ Zeit ist? Ich sehe keine Kontrollen, die diese Situation in Ihrem Code erfassen würde. Natürlich, wenn dies der Fall ist, das heißt, wenn einige Ereignisse „zu spät“ kommen, könnten sie leicht von Reihenfolge verarbeitet heraus bekommen, unabhängig davon, wie Sie es umsetzen.

Wenn möglich, rate ich würde die double ändern Sie als Schlüssel zu einem gewissen Integer-Typ anstelle verwenden. Der Schlüssel für eine set oder multiset erfordert eine strenge schwache Ordnung - und ein double tut nicht (normalerweise) erfüllen diese Anforderung (auch nicht andere IEEE-Gleitkomma-Typ)

.
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top