現在位置: ホーム その他 講義関連 FY2009 交通シミュレーション特論 RS_Dijkstra.h

RS_Dijkstra.h

Dijkstra's algorithm の実装

RS_Dijkstra.h — C header, 10 kB (10355 bytes)

ファイルコンテンツ

// This may look like C code, but it is really -*- C++ -*-
// RTSS --- Railway Total System Simulator
// (c) TAKAGI Ryo (at Kogakuin University)
// RS_Dijkstra.h --- class RS_Dijkstra and related classes, solving the
//  shortest paths problem.
// -----
// ChangeLog:
// 2009. 10. 16
//  The "directed graph" version complete.
// -----

// ----
// Dijkstra's algorithm
// ダイクストラ法
// ----

#ifndef RS_DIJKSTRA_H
#define RS_DIJKSTRA_H

#include <map>
#include <iostream>
#include <vector>
#include "RS_FHeap.h"

using std :: cerr ;
using std :: endl ;
using std :: vector ;
using std :: map ;
using std :: ostream ;
using std :: string ;



// ----
// Forward declarations
// ----
template < class KC , class NID >
class RS_DKBranch ;

template < class KC , class NID >
class RS_DKNode ;

template < class KD , class NIX >
std :: ostream & operator<<
( std :: ostream & ostr ,
  const RS_DKNode < KD , NIX > & dkn ) ;

// ----
// Dijkstra's Algorithm: the "node" of the graph
// ダイクストラのアルゴリズム: グラフの「ノード」
// ----
template < class KC , class NID >
class RS_DKNode
{

  template < class KD , class NIX >
  friend std :: ostream & operator<<
  ( std :: ostream & ostr , const RS_DKNode < KD , NIX > & dkn ) ;

private :

  string _name ;
  NID _nid ;
  typename RS_FHeap < KC , RS_DKNode < KC , NID > > :: Entry * _heapent ;
  RS_DKBranch < KC , NID > * _dkb_in ;

  // ----
  // Note: _blist_in contains branches coming into the node. Therefore, they
  // must have this node as "_n_out". Vice versa for _blist_out.
  // 注意: _blist_in はこのノードに「入ってくる」ブランチを保有する。従って,
  // このノードはそのブランチの _n_out となる。_blist_out はその逆。
  // ----
  vector < RS_DKBranch < KC , NID > * > _blist_in ;
  vector < RS_DKBranch < KC , NID > * > _blist_out ;

  mutable typename vector < RS_DKBranch < KC , NID > * > :: size_type _iter ;
  mutable bool _iter_to_start ;

  bool _marked ;
  bool _initial ;

  explicit RS_DKNode ( const RS_DKNode < KC , NID > & ) ;

public :
  explicit RS_DKNode ( const NID & _nid_in , const string & _n_in )
    : _nid ( _nid_in ) , _name ( _n_in ) , _heapent ( 0 ) , _dkb_in ( 0 ) ,
      _blist_in () , _blist_out () , _iter ( 0 ) , _iter_to_start ( true ) ,
      _marked ( false ) , _initial ( false ) {}
  void setHeapEntry
  ( typename RS_FHeap < KC , RS_DKNode < KC , NID > > :: Entry * x )
  { _heapent = x ; }

  // ----
  // Functions setting branches in the graph initialisation process.
  // グラフの初期化プロセスにおいてブランチをセットする関数.
  // ----
  void setIncomingBranch ( RS_DKBranch < KC , NID > * x )
  { _blist_in . push_back ( x ) ; }
  void setOutgoingBranch ( RS_DKBranch < KC , NID > * x )
  { _blist_out . push_back ( x ) ; }

  // ----
  // Setting current incoming path, used to follow the shortest path tree.
  // 現在の最短経路が「入ってくる」ブランチ。最短経路木探索のため用いられる。
  // ----
  void setIncomingPath ( RS_DKBranch < KC , NID > * x ) { _dkb_in = x ; }

  void setAsMarked () { _marked = true ; }

  // ----
  // Set as initial node
  // 始点ノードとセット
  // ----
  void setAsInitial () { _initial = true ; }

  typename RS_FHeap < KC , RS_DKNode < KC , NID > > :: Entry *
  getHeapEntry () const { return _heapent ; }
  RS_DKBranch < KC , NID > * getIncomingPath () const { return _dkb_in ; }

  const NID & getNodeID () const { return _nid ; }
  const string & getName () const { return _name ; }
  bool isMarked () const { return _marked ; }
  bool isUnreachable () const { return ! ( _initial || _dkb_in ) ; }

  RS_DKBranch < KC , NID > * getNextBranch () const
  {
    while ( true )
    {
      if ( _iter_to_start )
      {
        _iter_to_start = false ;
      }
      else
      {
        ++ _iter ;
      }
      if ( _iter >= _blist_out . size () )
        return 0 ;
      if ( _blist_out [ _iter ] == _dkb_in )
      {
        continue ;
      }
      return _blist_out [ _iter ] ;
    }
  }
} ;


template < class KD , class NIX >
ostream &
operator<<
( ostream & ostr ,
  const RS_DKNode < KD , NIX > & dkn )
{
  ostr << dkn . getName () ;
  return ostr ;
}



// ----
// Declaration of template class RS_DKBranch
// RS_DKBranch テンプレートクラスの宣言
// ----
template < class KC , class NID >
class RS_DKBranch
{

private :
  KC _weight ;

  // ----
  // Direction: in -> out. Node _n_in must have this branch in its
  // _blist_out. Node _n_out must have this branch in its _blist_in.
  // 方向: in -> out. このブランチは _n_in ノードの _blist_out に,そして
  // _n_out ノードの _blist_in に,それぞれ含まれなければならない。
  // ----
  RS_DKNode < KC , NID > * _n_in ;
  RS_DKNode < KC , NID > * _n_out ;

public :

  explicit RS_DKBranch ( RS_DKNode < KC , NID > * _in ,
                         RS_DKNode < KC , NID > * _out , KC x )
    : _weight ( x ) , _n_in ( _in ) , _n_out ( _out )
  { _in -> setOutgoingBranch ( this ) ; _out -> setIncomingBranch ( this ) ; }

  RS_DKNode < KC , NID > * getOpposite
  ( RS_DKNode < KC , NID > * x )
  { if ( _n_in == x ) return _n_out ; if ( _n_out == x ) return _n_in ;
    cerr << "Error: could not find opposite node" << endl ; exit ( 1 ) ; }

  const KC & getWeight () const { return _weight ; }

} ;



// ----
// Declaration of template class RS_Dijkstra
// RS_Dijkstra テンプレートクラスの宣言
// ----
template < class KC , class NID >
class RS_Dijkstra
{

  // "Large number" for initialising a node.
  KC _large ;

  // Heap
  RS_FHeap < KC , RS_DKNode < KC , NID > > _hp ;

  // Vector container of RS_DKNode object instances
  // *** May have to consider using map container instead of vector ***
  map < const NID , RS_DKNode < KC , NID > * > _nlist ;

  // Vector container of RS_DKBranch object instances
  // *** May have to consider using map container instead of vector ***
  vector < RS_DKBranch < KC , NID > * > _blist ;

public :

  explicit RS_Dijkstra ( const KC & _l_in )
    : _large ( _l_in ) , _hp () , _nlist () , _blist ()
  {
  }

  ~RS_Dijkstra ()
  {
    for ( typename vector < RS_DKBranch < KC , NID > * > :: iterator
            ii = _blist . begin () ; ii != _blist . end () ; ++ ii )
    {
      delete ( * ii ) ;
    }
    for ( typename map < const NID , RS_DKNode < KC , NID > * > :: iterator
            ii = _nlist . begin () ; ii != _nlist . end () ; ++ ii )
    {
      typename RS_FHeap < KC , RS_DKNode < KC , NID > > :: Entry *
        iix = ii -> second -> getHeapEntry () ;
      delete iix ;
      delete ii -> second ;
    }
  }

  void setNode ( const NID & _n_in )
  {
    RS_DKNode < KC , NID > *
      _n = new RS_DKNode < KC , NID > ( _n_in , _n_in ) ;
    _nlist [ _n_in ] = _n ;
    typename RS_FHeap < KC , RS_DKNode < KC , NID > > :: Entry * _e
      = new typename RS_FHeap < KC , RS_DKNode < KC , NID > > :: Entry
      ( _large , _n , & _hp ) ;
    _n -> setHeapEntry ( _e ) ;
    _hp . insert ( _e ) ;
  }

  RS_DKNode < KC , NID > * getNode
  ( const NID & _n_in )
  {
    typename map < const NID , RS_DKNode < KC , NID > * > :: iterator
      _i_x = _nlist . find ( _n_in ) ;
    if ( _i_x == _nlist . end () )
    {
      cerr << "Error: no node with ID \"" << _n_in
           << "\" in class RS_Dijkstra" << endl ;
      exit ( 1 ) ;
    }
    return _i_x -> second ;
  }

  void setBranch
  ( const NID & _nn_f , const NID & _nn_t , const KC & _wt )
  {
    RS_DKNode < KC , NID > * _n_f = getNode ( _nn_f ) ;
    RS_DKNode < KC , NID > * _n_t = getNode ( _nn_t ) ;
    RS_DKBranch < KC , NID > *
      _b = new RS_DKBranch < KC , NID > ( _n_f , _n_t , _wt ) ;
    _blist . push_back ( _b ) ;
  }

  void setBidirectionalBranches
  ( const NID & _nn_f , const NID & _nn_t , const KC & _wt )
  {
    setBranch ( _nn_f , _nn_t , _wt ) ;
    setBranch ( _nn_t , _nn_f , _wt ) ;
  }

  void run ( const NID & _start_nid )
  {
    cerr << "Dijkstra's Algorithm: starting from node \"" << _start_nid
         << "\"" << endl ;
    RS_DKNode < KC , NID > * _n_st = getNode ( _start_nid ) ;
    _n_st -> setAsInitial () ;
    _n_st -> getHeapEntry () -> decreaseKey ( 0 ) ;
    typename RS_FHeap < KC , RS_DKNode < KC , NID > > :: Entry * _min
      = _hp . deleteMinimum () ;
    _min -> getEntryData () -> setAsMarked () ;
    cerr << "delete min, node = " << _min -> getEntryData () -> getName ()
         << ", key = " << _min -> getKey () << endl ;

    while ( _hp . size () )
    {
      while ( RS_DKBranch < KC , NID > * _bx
              = _min -> getEntryData () -> getNextBranch () )
      {
        RS_DKNode < KC , NID > * _op
          = _bx -> getOpposite ( _min -> getEntryData () ) ;
        if ( _op -> isMarked () )
        {
          continue ;
        }
        KC _nkey = _min -> getKey () + _bx -> getWeight () ;
        cerr << "decrease key, node = " << _op -> getName () << ", key "
             << _op -> getHeapEntry () -> getKey () << " -> " << _nkey ;
        if ( _nkey < _op -> getHeapEntry () -> getKey () )
        {
          cerr << ", perform" << endl ;
          _op -> getHeapEntry () -> decreaseKey ( _nkey ) ;
          _op -> setIncomingPath ( _bx ) ;
        }
        else
        {
          cerr << ", not perform" << endl ;
        }
      }
      _min = _hp . deleteMinimum () ;
      _min -> getEntryData () -> setAsMarked () ;
      cerr << "delete min, node = " << _min -> getEntryData () -> getName ()
           << ", key = " << _min -> getKey () << endl ;
    }
    for ( typename map < const NID , RS_DKNode < KC , NID > * >
            :: const_iterator ii = _nlist . begin () ;
          ii != _nlist . end () ; ++ ii )
    {
      RS_DKNode < KC , NID > * _n = ii -> second ;
      cerr << "Node \"" << _n -> getName () << "\": " ;
      if ( _n -> isUnreachable () )
      {
        cerr << "unreachable" << endl ;
        continue ;
      }
      cerr << _n -> getHeapEntry () -> getKey () << ": "
           << _n -> getName () ;
      while ( RS_DKBranch < KC , NID > * _bi = _n -> getIncomingPath () )
      {
        cerr << "(" << _bi -> getWeight () << ")" ;
        _n = _bi -> getOpposite ( _n ) ;
        cerr << _n -> getName () ;
      }
      cerr << endl ;
    }
  }

} ;



#endif // RS_DIJKSTRA_H
2018 年 1月 »
1月
123456
78910111213
14151617181920
21222324252627
28293031