Documentation
¶
Overview ¶
Example 16_centrality_analytics — runs a suite of analytics over one shared, immutable CSR snapshot: exact Brandes betweenness centrality, four complementary whole-graph centralities (closeness and harmonic, distance-based; eigenvector and Katz, spectral/walk-based), and label-propagation community detection — with deterministic tie-breaking, and reports per-analysis evidence. A final pass rebuilds the graph with one bridge removed and runs the distance-based centralities on the resulting DISCONNECTED graph, showing they stay finite (no NaN/Inf) and that the Wasserman-Faust closeness normalisation rewards reaching more of the graph.
The example builds a seeded, scale-parametrised synthetic graph with the mutable adjlist builder, freezes it into an immutable CSR snapshot, then runs both analytics against that one snapshot. It reports the deterministic results (the top-k betweenness node ids, the number of communities found, and that partition's size distribution) as bare fact lines, and the volatile cost of each analysis (wall-clock, transient allocations, live heap) as "# "-prefixed telemetry.
Topology — why this generator ¶
The generator was chosen on the advice of the graph-theory-expert sub-agent, so that BOTH analytics produce a meaningful, dramatically non-uniform result from one graph: betweenness must concentrate on a few obvious cut vertices, and label propagation must recover a sensible partition without collapsing to one giant label or fragmenting.
The graph is a CHAIN of dense clusters joined by single bridge edges:
C0 == C1 == C2 == … == C(K-1)
- Each cluster is a dense Erdős–Rényi-style subgraph laid down on top of
a random spanning tree. The spanning tree GUARANTEES the cluster is one
connected component (no reliance on luck), and the extra edges at
intra-density p-in make it internally dense — dense enough that label
propagation keeps each cluster as a single distinct label rather than
fragmenting it.
- Consecutive clusters are joined by exactly ONE bridge edge, between the
right gateway of cluster c and the left gateway of cluster c+1. A single
edge across the cut keeps the effective inter-cluster density near zero,
which is the most stable regime for label propagation (no dense
inter-coupling for a label to flood across), so the clusters survive as
~K separate communities.
The gateways being the betweenness winners is a theorem here, not a heuristic: each bridge is the UNIQUE edge across its cut, so every shortest path between the two sides must traverse both gateway endpoints. Each gateway therefore carries Θ(n_c^2) pair-dependencies while every interior node carries only O(n_c), so the gateways dominate the betweenness ranking for every seed — the argument depends only on the fixed cut structure, not on the random intra-cluster edges. A CHAIN (rather than a ring) is used on purpose: a ring gives two equal-length arcs between far clusters, which splits the pair-dependency between them and blurs the signal; the chain gives a unique inter-cluster path, so the betweenness winners are maximally unambiguous and test-assertable.
The graph is analysed as UNDIRECTED: each edge is stored once, as one directed relationship, and both analytics read the symmetric projection built by csr.CSR.BuildSymmetric. Brandes betweenness is classically read on undirected graphs, and label propagation is defined on undirected neighbourhoods. Both analytics here are unweighted (Brandes counts shortest-path hops; label propagation counts neighbour labels), so the edges carry no weight — the snapshot is purely structural.
Scale ¶
Run with no flags, the example builds a small deterministic default (6 clusters of 50 nodes at intra-density 0.30 — 300 nodes, roughly 1.5k edges) that the regression test pins and that runs in milliseconds. Exact Brandes is O(V*E), so the default is deliberately small. Every dimension is a flag, so the same binary scales up to a size where the per-analysis cost is actually observable:
go run ./examples/16_centrality_analytics -communities 20 -nodes 200 -intra-density 0.2 -seed 7
That is ~4 000 nodes and tens of thousands of edges; because exact Brandes is O(V*E), pushing the cluster size into the hundreds moves the betweenness pass into seconds. The deterministic facts are reproducible for a fixed -seed; only the telemetry (lines prefixed with "# ") varies between runs and machines.