1

マルチセットコンテナによる奇妙な動作のデバッグにご協力いただければ幸いです。場合によっては、コンテナが並べ替えを停止しているように見えます。これはまれなエラーであり、久しぶりの一部のシミュレーションでのみ明らかになり、アイデアが不足しています。(私はアマチュアプログラマーです。あらゆる種類の提案を歓迎します。)

私のコンテナは構造体std::multisetを保持するものですEvent

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

メンバーEventでソートされた構造体を使用して: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;
  ...
};

プログラムは、順序付けられていない時間のイベントを追加しEventPQ currentEvents、次にイベントを順番にプルする期間を繰り返します。まれに、いくつかのイベントが追加された後(完全に「合法的な」時間で)、イベントが順不同で実行され始めます。

イベントが適切に順序付けられない原因は何ですか?(または、イテレータを台無しにする可能性がありますか?)追加されたすべてのイベント時間が正当である(つまり、すべてが現在のシミュレーション時間を超えている)ことを確認しました。また、2つのイベントがスケジュールされているため、エラーが発生しないことも確認しました。同時に。

これをどのように処理するかについての提案が欲しいです。

好奇心旺盛な方のために、イベントを実行および追加するためのコードを以下に示します。

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

イベントが実行されると、から他のイベントが削除される場合があることを追加する必要がありますcurrentEvents。これはで行われます

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

このコードは問題ないように見えますが、何が起こっているのかを調べる他の方法を知りたいです。現在、多くのasserts()とcout<<チェックを使用しています。

4

3 に答える 3

1

イベント処理サイクルは、キューが空であるかどうかのチェックに失敗します。それ以外の場合は、すべてが正常に見えます(多かれ少なかれ)。

currentEventsただし、キュー内のイベントが不足した場合、動作は定義されていません。それはおそらく、イベントが順不同で処理されているように見えるものとして現れる可能性があります。

実際、私が見た連想コンテナの一部の実装は、「実質的に循環」データ構造で表されていました。つまり、制御されたシーケンスの終わりを無視して反復を続けると、シーケンスの最初にイテレータが出現します。あなたの場合、そのようなことが起こっているのでしょうか?

コードに関連してすぐに発生する別の質問:新しいイベントがtime「現在の」時間よりも小さい値でキューに到着した場合はどうなりますか?この状況をコードに取り込むチェックはありません。明らかに、これが発生した場合、つまり、一部のイベントの到着が「遅すぎる」場合、実装方法に関係なく、イベントは簡単に順序が狂って処理される可能性があります。

于 2010-05-17T19:07:20.333 に答える
1

可能であれば、double代わりにキーとして使用している整数型に変更することをお勧めします。setまたはのキーはmultiset厳密な弱順序を必要とします-そしてaは(通常)その要件を満たしてdoubleいません(他のIEEE浮動小数点タイプも満たしていません)。

于 2010-05-17T19:08:30.547 に答える
0

シミュレーションでは、私がコメントしました

// Add some events to currentEvents

イベントはcurrentEventsに追加されていました。(それが明確であることを願っています。)キューの一番上にたまたま属していたイベントが追加された場合、currentEvents.begin()を指すイテレーターを台無しにしたと思います。内側のwhileループの直前でイテレータをリセットすると、動作しているように見えます。

これが解決策ではないことが判明した場合、または私がここに持っているものに他の問題がある場合は、この質問を更新します。

コメントしてくれたすべての人に感謝します。これらの問題にどのように取り組むべきかを学ぶのに役立ちます。

于 2010-05-17T20:42:47.287 に答える