00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00013
00014
00015 #ifndef __defined_libdai_dag_h
00016 #define __defined_libdai_dag_h
00017
00018
00019 #include <ostream>
00020 #include <vector>
00021 #include <algorithm>
00022 #include <dai/util.h>
00023 #include <dai/exceptions.h>
00024 #include <dai/smallset.h>
00025 #include <dai/graph.h>
00026
00027
00028 namespace dai {
00029
00030
00032
00043 class DAG {
00045
00047 typedef dai::Neighbor Neighbor;
00048
00050
00052 typedef dai::Neighbors Neighbors;
00053
00055
00057 typedef dai::Edge Edge;
00058
00059 private:
00061 std::vector<Neighbors> _pa;
00062
00064 std::vector<Neighbors> _ch;
00065
00066 public:
00068
00069
00070 DAG() : _pa(), _ch() {}
00071
00073 DAG( size_t nr ) : _pa( nr ), _ch( nr ) {}
00074
00076
00083 template<typename EdgeInputIterator>
00084 DAG( size_t nr, EdgeInputIterator begin, EdgeInputIterator end, bool check=true ) : _pa(), _ch() {
00085 construct( nr, begin, end, check );
00086 }
00088
00090
00091
00092 const Neighbor& pa( size_t n, size_t _p ) const {
00093 DAI_DEBASSERT( n < _pa.size() );
00094 DAI_DEBASSERT( _p < _pa[n].size() );
00095 return _pa[n][_p];
00096 }
00098 Neighbor& pa( size_t n, size_t _p ) {
00099 DAI_DEBASSERT( n < _pa.size() );
00100 DAI_DEBASSERT( _p < _pa[n].size() );
00101 return _pa[n][_p];
00102 }
00103
00105 const Neighbors& pa( size_t n ) const {
00106 DAI_DEBASSERT( n < _pa.size() );
00107 return _pa[n];
00108 }
00110 Neighbors& pa( size_t n ) {
00111 DAI_DEBASSERT( n < _pa.size() );
00112 return _pa[n];
00113 }
00114
00116 const Neighbor& ch( size_t n, size_t _c ) const {
00117 DAI_DEBASSERT( n < _ch.size() );
00118 DAI_DEBASSERT( _c < _ch[n].size() );
00119 return _ch[n][_c];
00120 }
00122 Neighbor& ch( size_t n, size_t _c ) {
00123 DAI_DEBASSERT( n < _ch.size() );
00124 DAI_DEBASSERT( _c < _ch[n].size() );
00125 return _ch[n][_c];
00126 }
00127
00129 const Neighbors& ch( size_t n ) const {
00130 DAI_DEBASSERT( n < _ch.size() );
00131 return _ch[n];
00132 }
00134 Neighbors& ch( size_t n ) {
00135 DAI_DEBASSERT( n < _ch.size() );
00136 return _ch[n];
00137 }
00139
00141
00142
00143
00149 template<typename EdgeInputIterator>
00150 void construct( size_t nr, EdgeInputIterator begin, EdgeInputIterator end, bool check=true );
00151
00153 size_t addNode() {
00154 _pa.push_back( Neighbors() );
00155 _ch.push_back( Neighbors() );
00156 return _pa.size() - 1;
00157 }
00158
00160
00166 template <typename NodeInputIterator>
00167 size_t addNode( NodeInputIterator begin, NodeInputIterator end, size_t sizeHint=0 ) {
00168 Neighbors newparents;
00169 newparents.reserve( sizeHint );
00170 size_t iter = 0;
00171 for( NodeInputIterator it = begin; it != end; ++it ) {
00172 DAI_ASSERT( *it < nrNodes() );
00173 Neighbor newparent( iter, *it, ch(*it).size() );
00174 Neighbor newchild( ch(*it).size(), nrNodes(), iter++ );
00175 newparents.push_back( newparent );
00176 ch( *it ).push_back( newchild );
00177 }
00178 _pa.push_back( newparents );
00179 _ch.push_back( Neighbors() );
00180 return _pa.size() - 1;
00181 }
00182
00184
00186 DAG& addEdge( size_t n1, size_t n2, bool check=true );
00188
00190
00191
00192 void eraseNode( size_t n );
00193
00195 void eraseEdge( size_t n1, size_t n2 );
00197
00199
00200
00201 size_t nrNodes() const {
00202 DAI_DEBASSERT( _pa.size() == _ch.size() );
00203 return _pa.size();
00204 }
00205
00207 size_t nrEdges() const {
00208 size_t sum = 0;
00209 for( size_t i = 0; i < _pa.size(); i++ )
00210 sum += _pa[i].size();
00211 return sum;
00212 }
00213
00215
00217 bool hasEdge( size_t n1, size_t n2 ) const {
00218 if( ch(n1).size() < pa(n2).size() ) {
00219 for( size_t _n2 = 0; _n2 < ch(n1).size(); _n2++ )
00220 if( ch( n1, _n2 ) == n2 )
00221 return true;
00222 } else {
00223 for( size_t _n1 = 0; _n1 < pa(n2).size(); _n1++ )
00224 if( pa( n2, _n1 ) == n1 )
00225 return true;
00226 }
00227 return false;
00228 }
00229
00231
00234 size_t findPa( size_t n, size_t p ) {
00235 for( size_t _p = 0; _p < pa(n).size(); _p++ )
00236 if( pa( n, _p ) == p )
00237 return _p;
00238 DAI_THROW(OBJECT_NOT_FOUND);
00239 return pa(n).size();
00240 }
00241
00243
00246 size_t findCh( size_t n, size_t c ) {
00247 for( size_t _c = 0; _c < ch(n).size(); _c++ )
00248 if( ch( n, _c ) == c )
00249 return _c;
00250 DAI_THROW(OBJECT_NOT_FOUND);
00251 return ch(n).size();
00252 }
00253
00255 SmallSet<size_t> paSet( size_t n ) const;
00256
00258 SmallSet<size_t> chSet( size_t n ) const;
00259
00261 std::set<size_t> ancestors( size_t n ) const;
00262
00264 std::set<size_t> descendants( size_t n ) const;
00265
00267 bool existsDirectedPath( size_t n1, size_t n2 ) const;
00268
00270 bool isConnected() const;
00271
00273 void checkConsistency() const;
00274
00276
00280 bool operator==( const DAG& x ) const {
00281 if( nrNodes() != x.nrNodes() )
00282 return false;
00283 for( size_t n1 = 0; n1 < nrNodes(); n1++ ) {
00284 if( pa(n1).size() != x.pa(n1).size() )
00285 return false;
00286 foreach( const Neighbor &n2, pa(n1) )
00287 if( !x.hasEdge( n2, n1 ) )
00288 return false;
00289 foreach( const Neighbor &n2, x.pa(n1) )
00290 if( !hasEdge( n2, n1 ) )
00291 return false;
00292 }
00293 return true;
00294 }
00296
00298
00299
00300 void printDot( std::ostream& os ) const;
00301
00303 friend std::ostream& operator<<( std::ostream& os, const DAG& g ) {
00304 g.printDot( os );
00305 return os;
00306 }
00308 };
00309
00310
00311 template<typename EdgeInputIterator>
00312 void DAG::construct( size_t nr, EdgeInputIterator begin, EdgeInputIterator end, bool check ) {
00313 _pa.clear();
00314 _pa.resize( nr );
00315 _ch.clear();
00316 _ch.resize( nr );
00317
00318 for( EdgeInputIterator e = begin; e != end; e++ )
00319 addEdge( e->first, e->second, check );
00320 }
00321
00322
00323 }
00324
00325
00326 #endif