numerics
Loading...
Searching...
No Matches
connected_components.hpp
Go to the documentation of this file.
1/// @file spatial/connected_components.hpp
2/// @brief Iterative BFS connected-component labelling.
3///
4/// connected_components(n_sites, in_cluster, neighbors)
5///
6/// Template parameters:
7/// InCluster callable: bool(int i) -- true if site i is in the cluster
8/// Neighbors callable: void(int i, F&& f) -- calls f(nb) for each neighbor nb of i
9///
10/// Returns ClusterResult where id[i] is:
11/// -2 = excluded (in_cluster returned false)
12/// >=0 = cluster index
13///
14/// ClusterResult::largest_id and largest_size track the biggest connected component.
15#pragma once
16
17#include <vector>
18
19namespace num {
20
22 std::vector<int> id; ///< Per-site label: -2 excluded, >=0 cluster index
23 std::vector<int> sizes; ///< sizes[c] = number of sites in cluster c
24 int largest_id = -1; ///< Index of largest cluster (-1 if none)
25 int largest_size = 0; ///< Size of largest cluster
26};
27
28/// BFS connected-component labelling with pre-allocated flat queue (no heap per call).
29///
30/// @param n_sites Total number of sites
31/// @param in_cluster bool(int i) -- include site i?
32/// @param neighbors void(int i, auto&& visit) -- call visit(nb) per neighbor of i
33template<typename InCluster, typename Neighbors>
36 Neighbors&& neighbors) {
38 res.id.resize(n_sites);
39 res.sizes.reserve(64);
40
41 for (int i = 0; i < n_sites; ++i)
42 res.id[i] = in_cluster(i) ? -1 : -2; // -1 = unvisited included, -2 = excluded
43
44 std::vector<int> queue(n_sites);
45 int qhead = 0, qtail = 0;
46
47 for (int start = 0; start < n_sites; ++start) {
48 if (res.id[start] != -1) continue;
49
50 const int cid = static_cast<int>(res.sizes.size());
51 res.sizes.push_back(0);
52 res.id[start] = cid;
53 queue[qtail++] = start;
54
55 while (qhead < qtail) {
56 const int i = queue[qhead++];
57 ++res.sizes[cid];
58 neighbors(i, [&](int nb) {
59 if (res.id[nb] == -1) { res.id[nb] = cid; queue[qtail++] = nb; }
60 });
61 }
62
63 if (res.sizes[cid] > res.largest_size) {
64 res.largest_size = res.sizes[cid];
65 res.largest_id = cid;
66 }
67 }
68 return res;
69}
70
71} // namespace num
constexpr T ipow(T x) noexcept
Compute x^N at compile time via repeated squaring.
ClusterResult connected_components(int n_sites, InCluster &&in_cluster, Neighbors &&neighbors)
int largest_id
Index of largest cluster (-1 if none)
std::vector< int > id
Per-site label: -2 excluded, >=0 cluster index.
int largest_size
Size of largest cluster.
std::vector< int > sizes
sizes[c] = number of sites in cluster c