@@ -141,67 +141,39 @@ auto aggregate(
141141 return result_t {std::move (new_g), std::move (new_community_map), std::move (temp_internal_weights), std::move (vertex_to_originals)};
142142}
143143
144- // / @brief Track hierarchy of aggregation levels for unfolding partitions .
145- template <typename VertexDescriptor>
146- struct hierarchy_t
144+ // / @brief Unfold a coarse partition back to the original vertices through hierarchy levels .
145+ template <typename CommunityMap, typename VertexDescriptor>
146+ auto unfold ( const CommunityMap& final_partition, const std::vector<boost::unordered_flat_map<VertexDescriptor, boost::unordered_flat_set<VertexDescriptor>>>& levels)
147147{
148- // Each level maps super-nodes to their constituent vertices from the previous level.
149- using level_t = boost::unordered_flat_map<VertexDescriptor, boost::unordered_flat_set<VertexDescriptor>>;
150- std::vector<level_t > levels;
151-
152- void push_level (const level_t & mapping) {
153- levels.push_back (mapping);
154- }
155-
156- void push_level (level_t && mapping) {
157- levels.push_back (std::move (mapping));
158- }
159-
160- std::size_t size () const {
161- return levels.size ();
162- }
163-
164- bool empty () const {
165- return levels.empty ();
166- }
167-
168- const level_t & operator [](std::size_t i) const {
169- return levels[i];
170- }
171-
172- template <typename CommunityMap>
173- auto unfold (const CommunityMap& final_partition) const
174- {
175- BOOST_ASSERT (!empty ());
148+ BOOST_ASSERT (!levels.empty ());
176149
177- boost::unordered_flat_map<VertexDescriptor, VertexDescriptor> original_partition;
150+ boost::unordered_flat_map<VertexDescriptor, VertexDescriptor> original_partition;
151+
152+ for (const auto & kv : final_partition) {
153+ boost::unordered_flat_set<VertexDescriptor> current_nodes;
154+ current_nodes.insert (kv.first );
178155
179- for ( const auto & kv : final_partition) {
180- boost::unordered_flat_set<VertexDescriptor> current_nodes;
181- current_nodes. insert (kv. first ) ;
156+ // From coarse to fine
157+ for ( auto level = levels. size (); level--; ) {
158+ boost::unordered_flat_set<VertexDescriptor> next_nodes ;
182159
183- // From coarse to fine
184- for (auto level = size (); level--; ) {
185- boost::unordered_flat_set<VertexDescriptor> next_nodes;
186-
187- for (VertexDescriptor node : current_nodes) {
188- auto it = levels[level].find (node);
189- BOOST_ASSERT (it != levels[level].end ());
190- next_nodes.insert (it->second .begin (), it->second .end ());
191- }
192-
193- current_nodes = std::move (next_nodes);
160+ for (VertexDescriptor node : current_nodes) {
161+ auto it = levels[level].find (node);
162+ BOOST_ASSERT (it != levels[level].end ());
163+ next_nodes.insert (it->second .begin (), it->second .end ());
194164 }
195165
196- // Assign all original vertices to community
197- for (VertexDescriptor original_v : current_nodes) {
198- original_partition[original_v] = kv.second ;
199- }
166+ current_nodes = std::move (next_nodes);
200167 }
201168
202- return original_partition;
169+ // Assign all original vertices to community
170+ for (VertexDescriptor original_v : current_nodes) {
171+ original_partition[original_v] = kv.second ;
172+ }
203173 }
204- };
174+
175+ return original_partition;
176+ }
205177
206178// Create vector of all vertices.
207179template <typename Graph>
@@ -580,7 +552,9 @@ louvain_clustering(
580552 partition_vec[get (vertex_index, g0, *vi)] = get (components, *vi);
581553 }
582554
583- louvain_detail::hierarchy_t <vertex_descriptor> hierarchy;
555+ using level_t = boost::unordered_flat_map<vertex_descriptor, boost::unordered_flat_set<vertex_descriptor>>;
556+ std::vector<level_t > levels;
557+
584558 auto partition_map_g0 = make_iterator_property_map (partition_vec.begin (), get (vertex_index, g0));
585559 auto coarse = louvain_detail::aggregate (g0, partition_map_g0, w0);
586560
@@ -601,7 +575,7 @@ louvain_clustering(
601575 break ;
602576 }
603577
604- hierarchy. push_level (std::move (coarse.vertex_mapping ));
578+ levels. push_back (std::move (coarse.vertex_mapping ));
605579 weight_type Q_old = Q;
606580
607581 // Dispatch the local optimization using the incremental or non-incremental variant
@@ -614,7 +588,7 @@ louvain_clustering(
614588 agg_partition_map[*vi_agg] = get (coarse.partition , *vi_agg);
615589 }
616590
617- auto unfolded_map = hierarchy. unfold (agg_partition_map);
591+ auto unfolded_map = louvain_detail:: unfold (agg_partition_map, levels );
618592 vertex_iterator vi_orig, vi_orig_end;
619593 for (boost::tie (vi_orig, vi_orig_end) = vertices (g0); vi_orig != vi_orig_end; ++vi_orig) {
620594 partition_vec[get (vertex_index, g0, *vi_orig)] = unfolded_map[*vi_orig];
0 commit comments