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 {
00044 private:
00046 std::vector<Neighbors> _pa;
00047
00049 std::vector<Neighbors> _ch;
00050
00051 public:
00053
00054
00055 DAG() : _pa(), _ch() {}
00056
00058 DAG( size_t nr ) : _pa( nr ), _ch( nr ) {}
00059
00061
00068 template<typename EdgeInputIterator>
00069 DAG( size_t nr, EdgeInputIterator begin, EdgeInputIterator end, bool check=true ) : _pa(), _ch() {
00070 construct( nr, begin, end, check );
00071 }
00073
00075
00076
00077 const Neighbor& pa( size_t n, size_t _p ) const {
00078 DAI_DEBASSERT( n < _pa.size() );
00079 DAI_DEBASSERT( _p < _pa[n].size() );
00080 return _pa[n][_p];
00081 }
00083 Neighbor& pa( size_t n, size_t _p ) {
00084 DAI_DEBASSERT( n < _pa.size() );
00085 DAI_DEBASSERT( _p < _pa[n].size() );
00086 return _pa[n][_p];
00087 }
00088
00090 const Neighbors& pa( size_t n ) const {
00091 DAI_DEBASSERT( n < _pa.size() );
00092 return _pa[n];
00093 }
00095 Neighbors& pa( size_t n ) {
00096 DAI_DEBASSERT( n < _pa.size() );
00097 return _pa[n];
00098 }
00099
00101 const Neighbor& ch( size_t n, size_t _c ) const {
00102 DAI_DEBASSERT( n < _ch.size() );
00103 DAI_DEBASSERT( _c < _ch[n].size() );
00104 return _ch[n][_c];
00105 }
00107 Neighbor& ch( size_t n, size_t _c ) {
00108 DAI_DEBASSERT( n < _ch.size() );
00109 DAI_DEBASSERT( _c < _ch[n].size() );
00110 return _ch[n][_c];
00111 }
00112
00114 const Neighbors& ch( size_t n ) const {
00115 DAI_DEBASSERT( n < _ch.size() );
00116 return _ch[n];
00117 }
00119 Neighbors& ch( size_t n ) {
00120 DAI_DEBASSERT( n < _ch.size() );
00121 return _ch[n];
00122 }
00124
00126
00127
00128
00134 template<typename EdgeInputIterator>
00135 void construct( size_t nr, EdgeInputIterator begin, EdgeInputIterator end, bool check=true );
00136
00138 size_t addNode() {
00139 _pa.push_back( Neighbors() );
00140 _ch.push_back( Neighbors() );
00141 return _pa.size() - 1;
00142 }
00143
00145
00151 template <typename NodeInputIterator>
00152 size_t addNode( NodeInputIterator begin, NodeInputIterator end, size_t sizeHint=0 ) {
00153 Neighbors newparents;
00154 newparents.reserve( sizeHint );
00155 size_t iter = 0;
00156 for( NodeInputIterator it = begin; it != end; ++it ) {
00157 DAI_ASSERT( *it < nrNodes() );
00158 Neighbor newparent( iter, *it, ch(*it).size() );
00159 Neighbor newchild( ch(*it).size(), nrNodes(), iter++ );
00160 newparents.push_back( newparent );
00161 ch( *it ).push_back( newchild );
00162 }
00163 _pa.push_back( newparents );
00164 _ch.push_back( Neighbors() );
00165 return _pa.size() - 1;
00166 }
00167
00169
00171 DAG& addEdge( size_t n1, size_t n2, bool check=true );
00173
00175
00176
00177 void eraseNode( size_t n );
00178
00180 void eraseEdge( size_t n1, size_t n2 );
00182
00184
00185
00186 size_t nrNodes() const {
00187 DAI_DEBASSERT( _pa.size() == _ch.size() );
00188 return _pa.size();
00189 }
00190
00192 size_t nrEdges() const {
00193 size_t sum = 0;
00194 for( size_t i = 0; i < _pa.size(); i++ )
00195 sum += _pa[i].size();
00196 return sum;
00197 }
00198
00200
00202 bool hasEdge( size_t n1, size_t n2 ) const {
00203 if( ch(n1).size() < pa(n2).size() ) {
00204 for( size_t _n2 = 0; _n2 < ch(n1).size(); _n2++ )
00205 if( ch( n1, _n2 ) == n2 )
00206 return true;
00207 } else {
00208 for( size_t _n1 = 0; _n1 < pa(n2).size(); _n1++ )
00209 if( pa( n2, _n1 ) == n1 )
00210 return true;
00211 }
00212 return false;
00213 }
00214
00216
00219 size_t findPa( size_t n, size_t p ) {
00220 for( size_t _p = 0; _p < pa(n).size(); _p++ )
00221 if( pa( n, _p ) == p )
00222 return _p;
00223 DAI_THROW(OBJECT_NOT_FOUND);
00224 return pa(n).size();
00225 }
00226
00228
00231 size_t findCh( size_t n, size_t c ) {
00232 for( size_t _c = 0; _c < ch(n).size(); _c++ )
00233 if( ch( n, _c ) == c )
00234 return _c;
00235 DAI_THROW(OBJECT_NOT_FOUND);
00236 return ch(n).size();
00237 }
00238
00240 SmallSet<size_t> paSet( size_t n ) const;
00241
00243 SmallSet<size_t> chSet( size_t n ) const;
00244
00246 std::set<size_t> ancestors( size_t n ) const;
00247
00249 std::set<size_t> descendants( size_t n ) const;
00250
00252 bool existsDirectedPath( size_t n1, size_t n2 ) const;
00253
00255 bool isConnected() const;
00256
00258 void checkConsistency() const;
00259
00261
00265 bool operator==( const DAG& x ) const {
00266 if( nrNodes() != x.nrNodes() )
00267 return false;
00268 for( size_t n1 = 0; n1 < nrNodes(); n1++ ) {
00269 if( pa(n1).size() != x.pa(n1).size() )
00270 return false;
00271 foreach( const Neighbor &n2, pa(n1) )
00272 if( !x.hasEdge( n2, n1 ) )
00273 return false;
00274 foreach( const Neighbor &n2, x.pa(n1) )
00275 if( !hasEdge( n2, n1 ) )
00276 return false;
00277 }
00278 return true;
00279 }
00281
00283
00284
00285 void printDot( std::ostream& os ) const;
00286
00288 friend std::ostream& operator<<( std::ostream& os, const DAG& g ) {
00289 g.printDot( os );
00290 return os;
00291 }
00293 };
00294
00295
00296 template<typename EdgeInputIterator>
00297 void DAG::construct( size_t nr, EdgeInputIterator begin, EdgeInputIterator end, bool check ) {
00298 _pa.clear();
00299 _pa.resize( nr );
00300 _ch.clear();
00301 _ch.resize( nr );
00302
00303 for( EdgeInputIterator e = begin; e != end; e++ )
00304 addEdge( e->first, e->second, check );
00305 }
00306
00307
00308 }
00309
00310
00311 #endif