Skip to content

Commit 7180cd6

Browse files
committed
fix: no hierarchy_t, free unfold function
1 parent e8760cf commit 7180cd6

File tree

2 files changed

+29
-55
lines changed

2 files changed

+29
-55
lines changed

include/boost/graph/louvain_clustering.hpp

Lines changed: 29 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -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.
207179
template <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];

test/louvain_clustering_test

-223 KB
Binary file not shown.

0 commit comments

Comments
 (0)