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 #include <dai/graph.h>
00027
00028
00029 namespace dai {
00030
00031
00033
00048 class BipartiteGraph {
00050
00052 typedef dai::Neighbor Neighbor;
00053
00055
00057 typedef dai::Neighbors Neighbors;
00058
00060
00062 typedef dai::Edge Edge;
00063
00064 private:
00066 std::vector<Neighbors> _nb1;
00067
00069 std::vector<Neighbors> _nb2;
00070
00072 struct levelType {
00074 std::vector<size_t> ind1;
00076 std::vector<size_t> ind2;
00077 };
00078
00079 public:
00081
00082
00083 BipartiteGraph() : _nb1(), _nb2() {}
00084
00086 BipartiteGraph( size_t nr1, size_t nr2 ) : _nb1(nr1), _nb2(nr2) {}
00087
00089
00096 template<typename EdgeInputIterator>
00097 BipartiteGraph( size_t nrNodes1, size_t nrNodes2, EdgeInputIterator begin, EdgeInputIterator end, bool check=true ) : _nb1(), _nb2() {
00098 construct( nrNodes1, nrNodes2, begin, end, check );
00099 }
00101
00103
00104
00105 const Neighbor & nb1( size_t i1, size_t _i2 ) const {
00106 DAI_DEBASSERT( i1 < _nb1.size() );
00107 DAI_DEBASSERT( _i2 < _nb1[i1].size() );
00108 return _nb1[i1][_i2];
00109 }
00111 Neighbor & nb1( size_t i1, size_t _i2 ) {
00112 DAI_DEBASSERT( i1 < _nb1.size() );
00113 DAI_DEBASSERT( _i2 < _nb1[i1].size() );
00114 return _nb1[i1][_i2];
00115 }
00116
00118 const Neighbor & nb2( size_t i2, size_t _i1 ) const {
00119 DAI_DEBASSERT( i2 < _nb2.size() );
00120 DAI_DEBASSERT( _i1 < _nb2[i2].size() );
00121 return _nb2[i2][_i1];
00122 }
00124 Neighbor & nb2( size_t i2, size_t _i1 ) {
00125 DAI_DEBASSERT( i2 < _nb2.size() );
00126 DAI_DEBASSERT( _i1 < _nb2[i2].size() );
00127 return _nb2[i2][_i1];
00128 }
00129
00131 const Neighbors & nb1( size_t i1 ) const {
00132 DAI_DEBASSERT( i1 < _nb1.size() );
00133 return _nb1[i1];
00134 }
00136 Neighbors & nb1( size_t i1 ) {
00137 DAI_DEBASSERT( i1 < _nb1.size() );
00138 return _nb1[i1];
00139 }
00140
00142 const Neighbors & nb2( size_t i2 ) const {
00143 DAI_DEBASSERT( i2 < _nb2.size() );
00144 return _nb2[i2];
00145 }
00147 Neighbors & nb2( size_t i2 ) {
00148 DAI_DEBASSERT( i2 < _nb2.size() );
00149 return _nb2[i2];
00150 }
00152
00154
00155
00156
00163 template<typename EdgeInputIterator>
00164 void construct( size_t nrNodes1, size_t nrNodes2, EdgeInputIterator begin, EdgeInputIterator end, bool check=true );
00165
00167 size_t addNode1() { _nb1.push_back( Neighbors() ); return _nb1.size() - 1; }
00168
00170 size_t addNode2() { _nb2.push_back( Neighbors() ); return _nb2.size() - 1; }
00171
00172
00174
00180 template <typename NodeInputIterator>
00181 size_t addNode1( NodeInputIterator begin, NodeInputIterator end, size_t sizeHint = 0 ) {
00182 Neighbors nbs1new;
00183 nbs1new.reserve( sizeHint );
00184 size_t iter = 0;
00185 for( NodeInputIterator it = begin; it != end; ++it ) {
00186 DAI_ASSERT( *it < nrNodes2() );
00187 Neighbor nb1new( iter, *it, nb2(*it).size() );
00188 Neighbor nb2new( nb2(*it).size(), nrNodes1(), iter++ );
00189 nbs1new.push_back( nb1new );
00190 nb2( *it ).push_back( nb2new );
00191 }
00192 _nb1.push_back( nbs1new );
00193 return _nb1.size() - 1;
00194 }
00195
00197
00203 template <typename NodeInputIterator>
00204 size_t addNode2( NodeInputIterator begin, NodeInputIterator end, size_t sizeHint = 0 ) {
00205 Neighbors nbs2new;
00206 nbs2new.reserve( sizeHint );
00207 size_t iter = 0;
00208 for( NodeInputIterator it = begin; it != end; ++it ) {
00209 DAI_ASSERT( *it < nrNodes1() );
00210 Neighbor nb2new( iter, *it, nb1(*it).size() );
00211 Neighbor nb1new( nb1(*it).size(), nrNodes2(), iter++ );
00212 nbs2new.push_back( nb2new );
00213 nb1( *it ).push_back( nb1new );
00214 }
00215 _nb2.push_back( nbs2new );
00216 return _nb2.size() - 1;
00217 }
00218
00220
00222 BipartiteGraph& addEdge( size_t n1, size_t n2, bool check = true );
00224
00226
00227
00228 void eraseNode1( size_t n1 );
00229
00231 void eraseNode2( size_t n2 );
00232
00234 void eraseEdge( size_t n1, size_t n2 );
00236
00238
00239
00240 size_t nrNodes1() const { return _nb1.size(); }
00242 size_t nrNodes2() const { return _nb2.size(); }
00243
00245 size_t nrEdges() const {
00246 size_t sum = 0;
00247 for( size_t i1 = 0; i1 < nrNodes1(); i1++ )
00248 sum += nb1(i1).size();
00249 return sum;
00250 }
00251
00253
00255 bool hasEdge( size_t n1, size_t n2 ) const {
00256 if( nb1(n1).size() < nb2(n2).size() ) {
00257 for( size_t _n2 = 0; _n2 < nb1(n1).size(); _n2++ )
00258 if( nb1( n1, _n2 ) == n2 )
00259 return true;
00260 } else {
00261 for( size_t _n1 = 0; _n1 < nb2(n2).size(); _n1++ )
00262 if( nb2( n2, _n1 ) == n1 )
00263 return true;
00264 }
00265 return false;
00266 }
00267
00269
00272 size_t findNb1( size_t n1, size_t n2 ) {
00273 for( size_t _n2 = 0; _n2 < nb1(n1).size(); _n2++ )
00274 if( nb1( n1, _n2 ) == n2 )
00275 return _n2;
00276 DAI_THROW(OBJECT_NOT_FOUND);
00277 return nb1(n1).size();
00278 }
00279
00281
00284 size_t findNb2( size_t n1, size_t n2 ) {
00285 for( size_t _n1 = 0; _n1 < nb2(n2).size(); _n1++ )
00286 if( nb2( n2, _n1 ) == n1 )
00287 return _n1;
00288 DAI_THROW(OBJECT_NOT_FOUND);
00289 return nb2(n2).size();
00290 }
00291
00293 SmallSet<size_t> nb1Set( size_t n1 ) const;
00294
00296 SmallSet<size_t> nb2Set( size_t n2 ) const;
00297
00299
00302 SmallSet<size_t> delta1( size_t n1, bool include = false ) const;
00303
00305
00308 SmallSet<size_t> delta2( size_t n2, bool include = false ) const;
00309
00311 bool isConnected() const;
00312
00314 bool isTree() const;
00315
00317
00321 bool operator==( const BipartiteGraph& x ) const {
00322 if( nrNodes1() != x.nrNodes1() )
00323 return false;
00324 if( nrNodes2() != x.nrNodes2() )
00325 return false;
00326 for( size_t n1 = 0; n1 < nrNodes1(); n1++ ) {
00327 if( nb1(n1).size() != x.nb1(n1).size() )
00328 return false;
00329 foreach( const Neighbor &n2, nb1(n1) )
00330 if( !x.hasEdge( n1, n2 ) )
00331 return false;
00332 foreach( const Neighbor &n2, x.nb1(n1) )
00333 if( !hasEdge( n1, n2 ) )
00334 return false;
00335 }
00336 return true;
00337 }
00338
00340 void checkConsistency() const;
00342
00344
00345
00346 void printDot( std::ostream& os ) const;
00347
00349 friend std::ostream& operator<<( std::ostream& os, const BipartiteGraph& g ) {
00350 g.printDot( os );
00351 return os;
00352 }
00354 };
00355
00356
00357 template<typename EdgeInputIterator>
00358 void BipartiteGraph::construct( size_t nrNodes1, size_t nrNodes2, EdgeInputIterator begin, EdgeInputIterator end, bool check ) {
00359 _nb1.clear();
00360 _nb1.resize( nrNodes1 );
00361 _nb2.clear();
00362 _nb2.resize( nrNodes2 );
00363
00364 for( EdgeInputIterator e = begin; e != end; e++ )
00365 addEdge( e->first, e->second, check );
00366 }
00367
00368
00369 }
00370
00371
00407 #endif