J'apprécierais l'aide pour déboguer un comportement étrange par un conteneur multiset. Parfois, le conteneur semble arrêter le tri. C'est une erreur peu fréquente, apparente dans seulement quelques simulations après une longue période, et je suis à court d'idées. (Je suis un programmeur amateur - suggestions de toutes sortes sont les bienvenus.)Le conteneur multiset semble arrêter le tri
Mon conteneur est un std::multiset
qui détient Event
struct:
typedef std::multiset< Event, std::less<Event> > EventPQ;
avec les Event
struct triés par double time
membres:
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;
...
};
Le programme parcourt des périodes d'ajout d'événements avec des temps non ordonnés à EventPQ currentEvents
, puis d'extraction des événements dans l'ordre. Rarement, après que certains événements ont été ajoutés (avec des temps parfaitement «légaux»), les événements commencent à être exécutés dans le désordre.
Qu'est-ce qui pourrait rendre les événements jamais correctement ordonnés? (Ou qu'est-ce qui pourrait gâcher l'itérateur?) J'ai vérifié que tous les temps d'événements ajoutés sont légitimes (ie, tous dépassent le temps de simulation actuel), et j'ai également confirmé que l'erreur ne se produisait pas parce que deux événements prévu pour le même temps.
J'aimerais des suggestions sur la façon de travailler à travers cela.
Le code pour l'exécution et l'ajout d'événements ci-dessous pour les curieux:
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);
}
Je dois ajouter que de temps en temps un événement, lorsqu'il est exécuté, effacera d'autres événements de currentEvents
. Cela se fait avec
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);
Même si ce code semble correct, je voudrais savoir d'autres façons d'examiner ce qui se passe - Je utilise actuellement beaucoup d'affirme() et Cout < < vérifications.
Pourquoi oldRecTime n'a-t-il aucune valeur? – AnT
Pourquoi utiliser un multiset lorsque vous vous absentez pour éviter l'ajout de doublons? –
@Andrey: Je ne suis jamais sûr de savoir comment synthétiser le code pour les questions ici. Je définis oldRecTime avant de le chercher dans la simulation. (Il s'agit spécifiquement de l'heure planifiée de récupération d'une infection et elle est stockée dans une classe Host.Si un événement d'infection se produit, je recalcule tous les temps de récupération planifiés précédemment, supprimant leurs événements correspondants de currentEvents et ajoutant les événements mis à jour.) – Sarah