libDAI
bipgraph.h
Go to the documentation of this file.
1 /* This file is part of libDAI - http://www.libdai.org/
2  *
3  * Copyright (c) 2006-2011, The libDAI authors. All rights reserved.
4  *
5  * Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
6  */
7 
8 
11 
12 
13 #ifndef __defined_libdai_bipgraph_h
14 #define __defined_libdai_bipgraph_h
15 
16 
17 #include <ostream>
18 #include <vector>
19 #include <algorithm>
20 #include <dai/util.h>
21 #include <dai/smallset.h>
22 #include <dai/exceptions.h>
23 #include <dai/graph.h>
24 
25 
26 namespace dai {
27 
28 
30 
46  private:
48  std::vector<Neighbors> _nb1;
49 
51  std::vector<Neighbors> _nb2;
52 
54  struct levelType {
56  std::vector<size_t> ind1;
58  std::vector<size_t> ind2;
59  };
60 
61  public:
63 
64 
65  BipartiteGraph() : _nb1(), _nb2() {}
66 
68  BipartiteGraph( size_t nr1, size_t nr2 ) : _nb1(nr1), _nb2(nr2) {}
69 
71 
78  template<typename EdgeInputIterator>
79  BipartiteGraph( size_t nrNodes1, size_t nrNodes2, EdgeInputIterator begin, EdgeInputIterator end, bool check=true ) : _nb1(), _nb2() {
80  construct( nrNodes1, nrNodes2, begin, end, check );
81  }
83 
85 
86 
87  const Neighbor & nb1( size_t i1, size_t _i2 ) const {
88  DAI_DEBASSERT( i1 < _nb1.size() );
89  DAI_DEBASSERT( _i2 < _nb1[i1].size() );
90  return _nb1[i1][_i2];
91  }
93  Neighbor & nb1( size_t i1, size_t _i2 ) {
94  DAI_DEBASSERT( i1 < _nb1.size() );
95  DAI_DEBASSERT( _i2 < _nb1[i1].size() );
96  return _nb1[i1][_i2];
97  }
98 
100  const Neighbor & nb2( size_t i2, size_t _i1 ) const {
101  DAI_DEBASSERT( i2 < _nb2.size() );
102  DAI_DEBASSERT( _i1 < _nb2[i2].size() );
103  return _nb2[i2][_i1];
104  }
106  Neighbor & nb2( size_t i2, size_t _i1 ) {
107  DAI_DEBASSERT( i2 < _nb2.size() );
108  DAI_DEBASSERT( _i1 < _nb2[i2].size() );
109  return _nb2[i2][_i1];
110  }
111 
113  const Neighbors & nb1( size_t i1 ) const {
114  DAI_DEBASSERT( i1 < _nb1.size() );
115  return _nb1[i1];
116  }
118  Neighbors & nb1( size_t i1 ) {
119  DAI_DEBASSERT( i1 < _nb1.size() );
120  return _nb1[i1];
121  }
122 
124  const Neighbors & nb2( size_t i2 ) const {
125  DAI_DEBASSERT( i2 < _nb2.size() );
126  return _nb2[i2];
127  }
129  Neighbors & nb2( size_t i2 ) {
130  DAI_DEBASSERT( i2 < _nb2.size() );
131  return _nb2[i2];
132  }
134 
136 
137 
138 
145  template<typename EdgeInputIterator>
146  void construct( size_t nrNodes1, size_t nrNodes2, EdgeInputIterator begin, EdgeInputIterator end, bool check=true );
147 
149  size_t addNode1() { _nb1.push_back( Neighbors() ); return _nb1.size() - 1; }
150 
152  size_t addNode2() { _nb2.push_back( Neighbors() ); return _nb2.size() - 1; }
153 
154 
156 
162  template <typename NodeInputIterator>
163  size_t addNode1( NodeInputIterator begin, NodeInputIterator end, size_t sizeHint = 0 ) {
164  Neighbors nbs1new;
165  nbs1new.reserve( sizeHint );
166  size_t iter = 0;
167  for( NodeInputIterator it = begin; it != end; ++it ) {
168  DAI_ASSERT( *it < nrNodes2() );
169  Neighbor nb1new( iter, *it, nb2(*it).size() );
170  Neighbor nb2new( nb2(*it).size(), nrNodes1(), iter++ );
171  nbs1new.push_back( nb1new );
172  nb2( *it ).push_back( nb2new );
173  }
174  _nb1.push_back( nbs1new );
175  return _nb1.size() - 1;
176  }
177 
179 
185  template <typename NodeInputIterator>
186  size_t addNode2( NodeInputIterator begin, NodeInputIterator end, size_t sizeHint = 0 ) {
187  Neighbors nbs2new;
188  nbs2new.reserve( sizeHint );
189  size_t iter = 0;
190  for( NodeInputIterator it = begin; it != end; ++it ) {
191  DAI_ASSERT( *it < nrNodes1() );
192  Neighbor nb2new( iter, *it, nb1(*it).size() );
193  Neighbor nb1new( nb1(*it).size(), nrNodes2(), iter++ );
194  nbs2new.push_back( nb2new );
195  nb1( *it ).push_back( nb1new );
196  }
197  _nb2.push_back( nbs2new );
198  return _nb2.size() - 1;
199  }
200 
202 
204  BipartiteGraph& addEdge( size_t n1, size_t n2, bool check = true );
206 
208 
209 
210  void eraseNode1( size_t n1 );
211 
213  void eraseNode2( size_t n2 );
214 
216  void eraseEdge( size_t n1, size_t n2 );
218 
220 
221 
222  size_t nrNodes1() const { return _nb1.size(); }
224  size_t nrNodes2() const { return _nb2.size(); }
225 
227  size_t nrEdges() const {
228  size_t sum = 0;
229  for( size_t i1 = 0; i1 < nrNodes1(); i1++ )
230  sum += nb1(i1).size();
231  return sum;
232  }
233 
235 
237  bool hasEdge( size_t n1, size_t n2 ) const {
238  if( nb1(n1).size() < nb2(n2).size() ) {
239  for( size_t _n2 = 0; _n2 < nb1(n1).size(); _n2++ )
240  if( nb1( n1, _n2 ) == n2 )
241  return true;
242  } else {
243  for( size_t _n1 = 0; _n1 < nb2(n2).size(); _n1++ )
244  if( nb2( n2, _n1 ) == n1 )
245  return true;
246  }
247  return false;
248  }
249 
251 
254  size_t findNb1( size_t n1, size_t n2 ) {
255  for( size_t _n2 = 0; _n2 < nb1(n1).size(); _n2++ )
256  if( nb1( n1, _n2 ) == n2 )
257  return _n2;
258  DAI_THROW(OBJECT_NOT_FOUND);
259  return nb1(n1).size();
260  }
261 
263 
266  size_t findNb2( size_t n1, size_t n2 ) {
267  for( size_t _n1 = 0; _n1 < nb2(n2).size(); _n1++ )
268  if( nb2( n2, _n1 ) == n1 )
269  return _n1;
270  DAI_THROW(OBJECT_NOT_FOUND);
271  return nb2(n2).size();
272  }
273 
275  SmallSet<size_t> nb1Set( size_t n1 ) const;
276 
278  SmallSet<size_t> nb2Set( size_t n2 ) const;
279 
281 
284  SmallSet<size_t> delta1( size_t n1, bool include = false ) const;
285 
287 
290  SmallSet<size_t> delta2( size_t n2, bool include = false ) const;
291 
293  bool isConnected() const;
294 
296  bool isTree() const;
297 
299 
303  bool operator==( const BipartiteGraph& x ) const {
304  if( nrNodes1() != x.nrNodes1() )
305  return false;
306  if( nrNodes2() != x.nrNodes2() )
307  return false;
308  for( size_t n1 = 0; n1 < nrNodes1(); n1++ ) {
309  if( nb1(n1).size() != x.nb1(n1).size() )
310  return false;
311  bforeach( const Neighbor &n2, nb1(n1) )
312  if( !x.hasEdge( n1, n2 ) )
313  return false;
314  bforeach( const Neighbor &n2, x.nb1(n1) )
315  if( !hasEdge( n1, n2 ) )
316  return false;
317  }
318  return true;
319  }
320 
322  void checkConsistency() const;
324 
326 
327 
328  void printDot( std::ostream& os ) const;
329 
331  friend std::ostream& operator<<( std::ostream& os, const BipartiteGraph& g ) {
332  g.printDot( os );
333  return os;
334  }
336 };
337 
338 
339 template<typename EdgeInputIterator>
340 void BipartiteGraph::construct( size_t nrNodes1, size_t nrNodes2, EdgeInputIterator begin, EdgeInputIterator end, bool check ) {
341  _nb1.clear();
342  _nb1.resize( nrNodes1 );
343  _nb2.clear();
344  _nb2.resize( nrNodes2 );
345 
346  for( EdgeInputIterator e = begin; e != end; e++ )
347  addEdge( e->first, e->second, check );
348 }
349 
350 
351 } // end of namespace dai
352 
353 
389 #endif