00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00014
00015
00016 #ifndef __defined_libdai_graph_h
00017 #define __defined_libdai_graph_h
00018
00019
00020 #include <ostream>
00021 #include <vector>
00022 #include <algorithm>
00023 #include <dai/util.h>
00024 #include <dai/exceptions.h>
00025 #include <dai/smallset.h>
00026
00027
00028 namespace dai {
00029
00030
00032
00076 struct Neighbor {
00078 size_t iter;
00080 size_t node;
00082 size_t dual;
00083
00085 Neighbor() {}
00087 Neighbor( size_t iter, size_t node, size_t dual ) : iter(iter), node(node), dual(dual) {}
00088
00090 operator size_t () const { return node; }
00091 };
00092
00093
00095 typedef std::vector<Neighbor> Neighbors;
00096
00097
00099
00103 typedef std::pair<size_t,size_t> Edge;
00104
00105
00107
00117 class GraphAL {
00118 public:
00120
00122 typedef dai::Neighbor Neighbor;
00123
00125
00127 typedef dai::Neighbors Neighbors;
00128
00130
00132 typedef dai::Edge Edge;
00133
00134 private:
00136 std::vector<Neighbors> _nb;
00137
00138 public:
00140
00141
00142 GraphAL() : _nb() {}
00143
00145 GraphAL( size_t nr ) : _nb( nr ) {}
00146
00148
00154 template<typename EdgeInputIterator>
00155 GraphAL( size_t nr, EdgeInputIterator begin, EdgeInputIterator end, bool check=true ) : _nb() {
00156 construct( nr, begin, end, check );
00157 }
00159
00161
00162
00163 const Neighbor & nb( size_t n1, size_t _n2 ) const {
00164 DAI_DEBASSERT( n1 < _nb.size() );
00165 DAI_DEBASSERT( _n2 < _nb[n1].size() );
00166 return _nb[n1][_n2];
00167 }
00169 Neighbor & nb( size_t n1, size_t _n2 ) {
00170 DAI_DEBASSERT( n1 < _nb.size() );
00171 DAI_DEBASSERT( _n2 < _nb[n1].size() );
00172 return _nb[n1][_n2];
00173 }
00174
00176 const Neighbors & nb( size_t n ) const {
00177 DAI_DEBASSERT( n < _nb.size() );
00178 return _nb[n];
00179 }
00181 Neighbors & nb( size_t n ) {
00182 DAI_DEBASSERT( n < _nb.size() );
00183 return _nb[n];
00184 }
00186
00188
00189
00190
00196 template<typename EdgeInputIterator>
00197 void construct( size_t nr, EdgeInputIterator begin, EdgeInputIterator end, bool check=true );
00198
00200 size_t addNode() { _nb.push_back( Neighbors() ); return _nb.size() - 1; }
00201
00203
00209 template <typename NodeInputIterator>
00210 size_t addNode( NodeInputIterator begin, NodeInputIterator end, size_t sizeHint = 0 ) {
00211 Neighbors nbsnew;
00212 nbsnew.reserve( sizeHint );
00213 size_t iter = 0;
00214 for( NodeInputIterator it = begin; it != end; ++it ) {
00215 DAI_ASSERT( *it < nrNodes() );
00216 Neighbor nb1new( iter, *it, nb(*it).size() );
00217 Neighbor nb2new( nb(*it).size(), nrNodes(), iter++ );
00218 nbsnew.push_back( nb1new );
00219 nb( *it ).push_back( nb2new );
00220 }
00221 _nb.push_back( nbsnew );
00222 return _nb.size() - 1;
00223 }
00224
00226
00228 GraphAL& addEdge( size_t n1, size_t n2, bool check = true );
00230
00232
00233
00234 void eraseNode( size_t n );
00235
00237 void eraseEdge( size_t n1, size_t n2 );
00239
00241
00242
00243 size_t nrNodes() const { return _nb.size(); }
00244
00246 size_t nrEdges() const {
00247 size_t sum = 0;
00248 for( size_t i = 0; i < nrNodes(); i++ )
00249 sum += nb(i).size();
00250 return sum / 2;
00251 }
00252
00254
00256 bool hasEdge( size_t n1, size_t n2 ) const {
00257 if( nb(n1).size() < nb(n2).size() ) {
00258 for( size_t _n2 = 0; _n2 < nb(n1).size(); _n2++ )
00259 if( nb( n1, _n2 ) == n2 )
00260 return true;
00261 } else {
00262 for( size_t _n1 = 0; _n1 < nb(n2).size(); _n1++ )
00263 if( nb( n2, _n1 ) == n1 )
00264 return true;
00265 }
00266 return false;
00267 }
00268
00270
00273 size_t findNb( size_t n1, size_t n2 ) {
00274 for( size_t _n2 = 0; _n2 < nb(n1).size(); _n2++ )
00275 if( nb( n1, _n2 ) == n2 )
00276 return _n2;
00277 DAI_THROW(OBJECT_NOT_FOUND);
00278 return nb(n1).size();
00279 }
00280
00282 SmallSet<size_t> nbSet( size_t n ) const;
00283
00285 bool isConnected() const;
00286
00288 bool isTree() const;
00289
00291 void checkConsistency() const;
00292
00294
00298 bool operator==( const GraphAL& x ) const {
00299 if( nrNodes() != x.nrNodes() )
00300 return false;
00301 for( size_t n1 = 0; n1 < nrNodes(); n1++ ) {
00302 if( nb(n1).size() != x.nb(n1).size() )
00303 return false;
00304 foreach( const Neighbor &n2, nb(n1) )
00305 if( !x.hasEdge( n1, n2 ) )
00306 return false;
00307 foreach( const Neighbor &n2, x.nb(n1) )
00308 if( !hasEdge( n1, n2 ) )
00309 return false;
00310 }
00311 return true;
00312 }
00314
00316
00317
00318 void printDot( std::ostream& os ) const;
00319
00321 friend std::ostream& operator<<( std::ostream& os, const GraphAL& g ) {
00322 g.printDot( os );
00323 return os;
00324 }
00326 };
00327
00328
00329 template<typename EdgeInputIterator>
00330 void GraphAL::construct( size_t nr, EdgeInputIterator begin, EdgeInputIterator end, bool check ) {
00331 _nb.clear();
00332 _nb.resize( nr );
00333
00334 for( EdgeInputIterator e = begin; e != end; e++ )
00335 addEdge( e->first, e->second, check );
00336 }
00337
00338
00340 GraphAL createGraphFull( size_t N );
00342 GraphAL createGraphGrid( size_t N1, size_t N2, bool periodic );
00344 GraphAL createGraphGrid3D( size_t N1, size_t N2, size_t N3, bool periodic );
00346 GraphAL createGraphLoop( size_t N );
00348 GraphAL createGraphTree( size_t N );
00350
00356 GraphAL createGraphRegular( size_t N, size_t d );
00357
00358
00359 }
00360
00361
00362 #endif