Pergunta

Eu gostaria de ajudar a depurar alguns comportamentos estranhos por um multiset recipiente.Ocasionalmente, o recipiente aparece para interromper a classificação.Este é um erro frequente, aparente em algumas simulações, depois de um longo tempo, e eu sou curto em idéias.(Eu sou um amador programador--sugestões de todos os tipos são bem-vindas.)

O meu é um recipiente std::multiset que detém Event estruturas:

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

com o Event estruturas ordenadas pelo seu double time membros:

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

O programa repete-se através de períodos de adicionar eventos com desordenada vezes para EventPQ currentEvents e, em seguida, puxando eventos em ordem.Raramente, depois de alguns eventos foram adicionados (perfeitamente legal " vezes), os eventos começam a ficar executadas fora de ordem.

O que poderia fazer os eventos já não conseguir ordenar corretamente?(Ou o que poderia atrapalhar o iterador?) Tenho verificado que todas as adicionado evento vezes são legítimas (por exemplo, todos exceder o tempo de simulação atual), e eu também confirmou que o erro não ocorrer devido a dois eventos acontecem para obter agendadas para o mesmo horário.

Gostaria de sugestões sobre como trabalhar com isso.

O código para a execução e a adição de eventos é abaixo para os curiosos:

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

Devo acrescentar que, ocasionalmente, um evento, quando executado, irá excluir outros eventos de currentEvents.Isso é feito com

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

Mesmo se esse código parece bem, eu gostaria de saber outras maneiras que eu posso examinar o que está acontecendo--eu estou usando atualmente um monte de declarações() e cout << verifica.

Foi útil?

Solução 3

Na simulação, onde eu comentei

// Add some events to currentEvents

Os eventos estavam sendo adicionados ao CurrentEvents. (Espero que estivesse claro.) Se foi adicionado um evento que pertencia ao topo da fila, acredito que isso atrapalhou o iterador apontando para o currentEvents.Begin (). Eu redefini o iterador imediatamente antes do interior enquanto o loop e as coisas parecem funcionar.

Atualizarei essa pergunta se isso não for a solução ou se houver outros problemas no que tenho aqui.

Obrigado a todos aqueles que comentaram; Isso me ajuda a aprender como eu deveria estar abordando esses problemas.

Outras dicas

O evento ciclo de processamento de falha para verificar se a fila está vazia.Caso contrário, tudo parece bem (mais ou menos).

Mas se você correr para fora de eventos em sua currentEvents fila, o comportamento é indefinido.Ele provavelmente poderia se manifestar como algo que aparece como evento a ser processado fora de ordem.

Na verdade, algumas implementações do associativa recipientes eu vi representou-os por "praticamente circular" estruturas de dados, no sentido de que se você ignorar o fim da sequência controlado e continuar a repetir, o iterador que vai surgir no início da sequência.Pode ser que algo como o que está acontecendo no seu caso?

Outra pergunta que imediatamente surge em conexão com o seu código:o que acontece se o novo evento chega na fila com o time valor que é menor do que o "atual" tempo?Eu não vejo qualquer verifica que iria capturar esta situação em seu código.Obviamente, se isso acontece, por exemplo,se alguns eventos chegar "tarde demais", eles podem facilmente obter processadas fora de ordem independentemente de como implementá-lo.

Se possível, eu aconselho a mudar o double Você está usando como chave para algum tipo inteiro. A chave para um set ou multiset requer uma ordem fraca estrita - e um double faz não (Normalmente) atenda a esse requisito (nem qualquer outro tipo de ponto flutuante IEEE).

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top