Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
DisjointSets.cc
Go to the documentation of this file.
1 // (c) Copyright Rosetta Commons Member Institutions.
2 // (c) This file is part of the Rosetta software suite and is made available under license.
3 // (c) The Rosetta software is developed by the contributing members of the Rosetta Commons.
4 // (c) For more information, see http://www.rosettacommons.org. Questions about this can be
5 // (c) addressed to University of Washington UW TechTransfer, email: license@u.washington.edu.
6 
7 /// @file core/graph/Graph.hh
8 /// @brief generic graph class header
9 /// @author Andrew Leaver-Fay (aleaverfay@gmail.com)
10 
11 
12 // Unit Headers
14 
15 namespace core {
16 namespace graph {
17 
18 ///
19 /// @begin DisjointSets::DisjointSets()
20 ///
21 /// @brief
22 /// default constructor, for when number of nodes is not known
23 ///
25 
26 
27 ///
28 /// @begin DisjointSets::DisjointSets()
29 ///
30 /// @brief
31 /// constructor for when number of nodes is known up front. fastest.
32 ///
34  nodes_( n_nodes )
35 {
36  for ( platform::Size ii = 1; ii <= n_nodes; ++ii ) {
37  nodes_[ ii ].parent = ii;
38  nodes_[ ii ].rank = 0;
39  }
40 }
41 
42 ///
43 /// @begin DisjointSets::n_nodes()
44 ///
45 /// @brief
46 /// returns the total number of nodes
47 ///
49  return nodes_.size();
50 }
51 
52 
53 ///
54 /// @begin DisjointSets::ds_make_set()
55 ///
56 /// @brief
57 /// creates a new set
58 ///
59 /// @details This implementation uses indices to objects in arrays instead of pointers and so it relies on vector
60 /// push-back methods (O(N)) instead of list push-back methods (O(1)). If enough people clamour, I'll go back and make
61 /// this faster...(apl)
62 ///
64  nodes_.resize( n_nodes() + 1 );
65  nodes_[ n_nodes() ].parent = n_nodes();
66  nodes_[ n_nodes() ].rank = 0;
67 }
68 
69 
70 ///
71 /// @begin DisjointSets::ds_find()
72 ///
73 /// @brief
74 /// given a node_id, return the representative for that node
75 ///
78 
79  if ( nodes_[ node_id ].parent != node_id ) {
80  nodes_[ node_id ].parent = ds_find( nodes_[ node_id ].parent );
81  }
82  return nodes_[ node_id ].parent;
83 }
84 
85 
86 ///
87 /// @begin DisjointSets::ds_union()
88 ///
89 /// @brief
90 /// combine two sets; make it so that two nodes end up in the same set
91 ///
92 void
94 
95  platform::Size parent_node1 = ds_find( node1 );
96  platform::Size parent_node2 = ds_find( node2 );
97 
98  if ( nodes_[ parent_node1 ].rank < nodes_[ parent_node2 ].rank ) {
99  nodes_[ parent_node1 ].parent = parent_node2;
100  ++nodes_[ parent_node2 ].rank;
101 
102  } else if ( nodes_[ parent_node1 ].rank > nodes_[ parent_node2 ].rank ) {
103  nodes_[ parent_node2 ].parent = parent_node1;
104  ++nodes_[ parent_node1 ].rank;
105 
106  } else if ( parent_node1 != parent_node2 ) {
107  nodes_[ parent_node1 ].parent = parent_node2;
108  ++nodes_[ parent_node2 ].rank;
109  }
110 }
111 
112 
113 ///
114 /// @begin DisjointSets::n_disjoint_sets()
115 ///
116 /// @brief
117 /// count the number of disjoint sets. O(N)
118 ///
120 
121  platform::Size n_disjoint( 0 );
122  for ( platform::Size ii = 1; ii <= n_nodes(); ++ii ) {
123  if ( nodes_[ ii ].parent == ii )
124  ++n_disjoint;
125  }
126  return n_disjoint;
127 }
128 
129 
130 ///
131 /// @begin DisjointSets::disjoint_set_sizes()
132 ///
133 /// @brief
134 /// returns a vector1 containing the size of each disjoint set. O(N)
135 ///
138 
139  utility::vector1< platform::Size > index_2_ds( n_nodes(), 0 );
140  platform::Size n_disjoint( 0 );
141  for ( platform::Size ii = 1; ii <= n_nodes(); ++ii ) {
142  if ( nodes_[ ii ].parent == ii )
143  index_2_ds[ ii ] = ++n_disjoint;
144  }
145 
146  utility::vector1< platform::Size > ds_set_sizes( n_disjoint, 0 );
147  for ( platform::Size ii = 1; ii <= n_nodes(); ++ii ) {
148  ++ds_set_sizes[ index_2_ds[ ds_find( ii ) ] ];
149  }
150 
151  return ds_set_sizes;
152 }
153 
154 
155 ///
156 /// @begin DisjointSets::nodes_in_set()
157 ///
158 /// @brief
159 /// returns a vector1 of the nodes in the set containing the specified node.
160 ///
163 
165 
166  platform::Size const root = ds_find( node_id );
167 
168  for ( platform::Size i = 1, ie = n_nodes(); i <= ie; ++i ) {
169  if ( root == ds_find( i ) ) {
170  nis.push_back( i );
171  }
172  }
173 
174  return nis;
175 }
176 
177 
178 ///
179 /// @begin DisjointSets::sets()
180 ///
181 /// @brief
182 /// return a map from the representative node of each set to the list of nodes in their sets
183 ///
184 std::map< platform::Size, utility::vector1< platform::Size > >
186 
187  std::map< platform::Size, utility::vector1< platform::Size > > r2s;
188 
189  for ( platform::Size i = 1, ie = n_nodes(); i <= ie; ++i ) {
190  // operator[] safe here
191  r2s[ ds_find( i ) ].push_back( i );
192  }
193 
194  return r2s;
195 }
196 
197 
198 }
199 }
200