00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00014
00015
00016 #ifndef __defined_libdai_bipgraph_h
00017 #define __defined_libdai_bipgraph_h
00018
00019
00020 #include <ostream>
00021 #include <vector>
00022 #include <algorithm>
00023 #include <dai/util.h>
00024 #include <dai/smallset.h>
00025 #include <dai/exceptions.h>
00026
00027
00028 namespace dai {
00029
00030
00032
00047 class BipartiteGraph {
00048 public:
00050
00105 struct Neighbor {
00107 size_t iter;
00109 size_t node;
00111 size_t dual;
00112
00114 Neighbor() {}
00116 Neighbor( size_t iter, size_t node, size_t dual ) : iter(iter), node(node), dual(dual) {}
00117
00119 operator size_t () const { return node; }
00120 };
00121
00123 typedef std::vector<Neighbor> Neighbors;
00124
00126 typedef std::pair<size_t,size_t> Edge;
00127
00128 private:
00130 std::vector<Neighbors> _nb1;
00131
00133 std::vector<Neighbors> _nb2;
00134
00136 struct levelType {
00138 std::vector<size_t> ind1;
00140 std::vector<size_t> ind2;
00141 };
00142
00143 public:
00145
00146
00147 BipartiteGraph() : _nb1(), _nb2() {}
00148
00150 BipartiteGraph( size_t nr1, size_t nr2 ) : _nb1(nr1), _nb2(nr2) {}
00151
00153
00160 template<typename EdgeInputIterator>
00161 BipartiteGraph( size_t nrNodes1, size_t nrNodes2, EdgeInputIterator begin, EdgeInputIterator end, bool check=true ) : _nb1(), _nb2() {
00162 construct( nrNodes1, nrNodes2, begin, end, check );
00163 }
00165
00167
00168
00169 const Neighbor & nb1( size_t i1, size_t _i2 ) const {
00170 DAI_DEBASSERT( i1 < _nb1.size() );
00171 DAI_DEBASSERT( _i2 < _nb1[i1].size() );
00172 return _nb1[i1][_i2];
00173 }
00175 Neighbor & nb1( size_t i1, size_t _i2 ) {
00176 DAI_DEBASSERT( i1 < _nb1.size() );
00177 DAI_DEBASSERT( _i2 < _nb1[i1].size() );
00178 return _nb1[i1][_i2];
00179 }
00180
00182 const Neighbor & nb2( size_t i2, size_t _i1 ) const {
00183 DAI_DEBASSERT( i2 < _nb2.size() );
00184 DAI_DEBASSERT( _i1 < _nb2[i2].size() );
00185 return _nb2[i2][_i1];
00186 }
00188 Neighbor & nb2( size_t i2, size_t _i1 ) {
00189 DAI_DEBASSERT( i2 < _nb2.size() );
00190 DAI_DEBASSERT( _i1 < _nb2[i2].size() );
00191 return _nb2[i2][_i1];
00192 }
00193
00195 const Neighbors & nb1( size_t i1 ) const {
00196 DAI_DEBASSERT( i1 < _nb1.size() );
00197 return _nb1[i1];
00198 }
00200 Neighbors & nb1( size_t i1 ) {
00201 DAI_DEBASSERT( i1 < _nb1.size() );
00202 return _nb1[i1];
00203 }
00204
00206 const Neighbors & nb2( size_t i2 ) const {
00207 DAI_DEBASSERT( i2 < _nb2.size() );
00208 return _nb2[i2];
00209 }
00211 Neighbors & nb2( size_t i2 ) {
00212 DAI_DEBASSERT( i2 < _nb2.size() );
00213 return _nb2[i2];
00214 }
00216
00218
00219
00220
00227 template<typename EdgeInputIterator>
00228 void construct( size_t nrNodes1, size_t nrNodes2, EdgeInputIterator begin, EdgeInputIterator end, bool check=true );
00229
00231 size_t addNode1() { _nb1.push_back( Neighbors() ); return _nb1.size() - 1; }
00232
00234 size_t addNode2() { _nb2.push_back( Neighbors() ); return _nb2.size() - 1; }
00235
00236
00238
00244 template <typename NodeInputIterator>
00245 size_t addNode1( NodeInputIterator begin, NodeInputIterator end, size_t sizeHint = 0 ) {
00246 Neighbors nbs1new;
00247 nbs1new.reserve( sizeHint );
00248 size_t iter = 0;
00249 for( NodeInputIterator it = begin; it != end; ++it ) {
00250 DAI_ASSERT( *it < nrNodes2() );
00251 Neighbor nb1new( iter, *it, nb2(*it).size() );
00252 Neighbor nb2new( nb2(*it).size(), nrNodes1(), iter++ );
00253 nbs1new.push_back( nb1new );
00254 nb2( *it ).push_back( nb2new );
00255 }
00256 _nb1.push_back( nbs1new );
00257 return _nb1.size() - 1;
00258 }
00259
00261
00267 template <typename NodeInputIterator>
00268 size_t addNode2( NodeInputIterator begin, NodeInputIterator end, size_t sizeHint = 0 ) {
00269 Neighbors nbs2new;
00270 nbs2new.reserve( sizeHint );
00271 size_t iter = 0;
00272 for( NodeInputIterator it = begin; it != end; ++it ) {
00273 DAI_ASSERT( *it < nrNodes1() );
00274 Neighbor nb2new( iter, *it, nb1(*it).size() );
00275 Neighbor nb1new( nb1(*it).size(), nrNodes2(), iter++ );
00276 nbs2new.push_back( nb2new );
00277 nb1( *it ).push_back( nb1new );
00278 }
00279 _nb2.push_back( nbs2new );
00280 return _nb2.size() - 1;
00281 }
00282
00284
00286 BipartiteGraph& addEdge( size_t n1, size_t n2, bool check = true );
00288
00290
00291
00292 void eraseNode1( size_t n1 );
00293
00295 void eraseNode2( size_t n2 );
00296
00298 void eraseEdge( size_t n1, size_t n2 );
00300
00302
00303
00304 size_t nrNodes1() const { return _nb1.size(); }
00306 size_t nrNodes2() const { return _nb2.size(); }
00307
00309 size_t nrEdges() const {
00310 size_t sum = 0;
00311 for( size_t i1 = 0; i1 < nrNodes1(); i1++ )
00312 sum += nb1(i1).size();
00313 return sum;
00314 }
00315
00317
00319 bool hasEdge( size_t n1, size_t n2 ) const {
00320 if( nb1(n1).size() < nb2(n2).size() ) {
00321 for( size_t _n2 = 0; _n2 < nb1(n1).size(); _n2++ )
00322 if( nb1( n1, _n2 ) == n2 )
00323 return true;
00324 } else {
00325 for( size_t _n1 = 0; _n1 < nb2(n2).size(); _n1++ )
00326 if( nb2( n2, _n1 ) == n1 )
00327 return true;
00328 }
00329 return false;
00330 }
00331
00333
00336 size_t findNb1( size_t n1, size_t n2 ) {
00337 for( size_t _n2 = 0; _n2 < nb1(n1).size(); _n2++ )
00338 if( nb1( n1, _n2 ) == n2 )
00339 return _n2;
00340 DAI_THROW(OBJECT_NOT_FOUND);
00341 return nb1(n1).size();
00342 }
00343
00345
00348 size_t findNb2( size_t n1, size_t n2 ) {
00349 for( size_t _n1 = 0; _n1 < nb2(n2).size(); _n1++ )
00350 if( nb2( n2, _n1 ) == n1 )
00351 return _n1;
00352 DAI_THROW(OBJECT_NOT_FOUND);
00353 return nb2(n2).size();
00354 }
00355
00357 SmallSet<size_t> nb1Set( size_t n1 ) const;
00358
00360 SmallSet<size_t> nb2Set( size_t n2 ) const;
00361
00363
00366 SmallSet<size_t> delta1( size_t n1, bool include = false ) const;
00367
00369
00372 SmallSet<size_t> delta2( size_t n2, bool include = false ) const;
00373
00375 bool isConnected() const;
00376
00378 bool isTree() const;
00379
00381
00385 bool operator==( const BipartiteGraph& x ) const {
00386 if( nrNodes1() != x.nrNodes1() )
00387 return false;
00388 if( nrNodes2() != x.nrNodes2() )
00389 return false;
00390 for( size_t n1 = 0; n1 < nrNodes1(); n1++ ) {
00391 if( nb1(n1).size() != x.nb1(n1).size() )
00392 return false;
00393 foreach( const Neighbor &n2, nb1(n1) )
00394 if( !x.hasEdge( n1, n2 ) )
00395 return false;
00396 foreach( const Neighbor &n2, x.nb1(n1) )
00397 if( !hasEdge( n1, n2 ) )
00398 return false;
00399 }
00400 return true;
00401 }
00402
00404 void checkConsistency() const;
00406
00408
00409
00410 void printDot( std::ostream& os ) const;
00411
00413 friend std::ostream& operator<<( std::ostream& os, const BipartiteGraph& g ) {
00414 g.printDot( os );
00415 return os;
00416 }
00418 };
00419
00420
00421 template<typename EdgeInputIterator>
00422 void BipartiteGraph::construct( size_t nrNodes1, size_t nrNodes2, EdgeInputIterator begin, EdgeInputIterator end, bool check ) {
00423 _nb1.clear();
00424 _nb1.resize( nrNodes1 );
00425 _nb2.clear();
00426 _nb2.resize( nrNodes2 );
00427
00428 for( EdgeInputIterator e = begin; e != end; e++ )
00429 addEdge( e->first, e->second, check );
00430 }
00431
00432
00433 }
00434
00435
00471 #endif