Pregunta

Le agradecería ayuda depurar un comportamiento extraño por un contenedor conjunto múltiple. De vez en cuando, el contenedor parece que deja de clasificar. Este es un error poco frecuente, sólo evidente en algunas simulaciones después de mucho tiempo, y estoy corto de ideas. (Soy un programador aficionado - sugerencias de todo tipo son bienvenidos.)

Mi contenedor es un std::multiset que mantiene estructuras Event:

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

con las estructuras Event ordenadas según sus miembros double time:

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;
  ...
};

El programa itera a través de períodos de añadir eventos con tiempos no ordenadas a EventPQ currentEvents y luego tirando de eventos en orden. En raras ocasiones, después de que algunos eventos se han añadido (con tiempos perfectamente 'legales'), comienza a recibir eventos ejecutados fuera de orden.

¿Qué podría hacer que los acontecimientos siempre no obtener ordenó correctamente? (O lo que podría estropear el iterador?) He comprobado que todas las horas de los eventos agregados son legítimas (es decir, todos superan el tiempo de simulación actual), y también me han confirmado que el error no se produce debido a que dos eventos ocurre que se programado para la misma hora.

Me encantaría sugerencias sobre la forma de trabajo a través de esto.

El código para la ejecución y la adición de eventos está por debajo de la curiosa:

  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 );
}

Debería añadir que de vez en cuando un evento, cuando se ejecuta, eliminará otros eventos de currentEvents. Esto se hace con

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 );

Incluso si este código se ve bien, me gustaría saber otras maneras en que puede examinar lo que está pasando -. Estoy utilizando actualmente una gran cantidad de afirma () y cout << cheques

¿Fue útil?

Solución 3

En la simulación, donde he comentado

// Add some events to currentEvents

acontecimientos estaban siendo añadido a currentevents. (La esperanza de que estaba claro.) Si un evento se añadió que pasó a pertenecer a la cabeza de la cola, creo que el mal estado apuntando a currentEvents.begin iterador (). I reajustó el iterador inmediatamente antes del bucle while interior, y las cosas parecen funcionar.

Voy a actualizar esta pregunta si esto resultara no ser la solución, o si hay otros problemas en lo que tengo aquí.

Gracias a todos los que comentaron; Me ayuda a aprender cómo debería estar acercándose a estos problemas.

Otros consejos

Su ciclo de procesamiento de eventos no comprueba si la cola está vacía. De lo contrario, todo se ve bien (más o menos).

Pero si se le acaba de eventos en la cola currentEvents, el comportamiento no está definido. Es probablemente podría manifestarse como algo aparece como los eventos que se procesan fuera de orden.

De hecho, algunas implementaciones de contenedores asociativos que los vi representado por las estructuras de datos "prácticamente circulares", en el sentido de que si se ignora el final de la secuencia controlada y continúen iterando, su repetidor va a surgir a principios de la secuencia. Podría ser que algo así está sucediendo en su caso?

Otra pregunta que surge inmediatamente en relación con su código: ¿qué ocurre si el nuevo evento llega a la cola con el valor time que es menor que el tiempo "actual"? No veo ninguna comprobación de que capturaría esta situación en el código. Obviamente, si esto sucede, es decir, si algunos eventos llegan "demasiado tarde", podrían conseguir fácilmente procesada fuera de servicio, independientemente de cómo ponerlo en práctica.

Si es posible, te aconsejo cambiar el double está utilizando como una clave para un cierto tipo entero en su lugar. La clave para una set o multiset requiere un estricto orden débil - y una double hace no (normalmente) cumplir con este requisito (ni tampoco cualquier otro tipo de punto flotante IEEE)

.
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top