HomeNetworks & Graph TheoryCommunity Detection (Louvain)

🔵 Community Detection (Louvain)

Interactive Louvain method: detect communities in a network by greedily maximizing modularity Q. Animated local-moving and aggregation phases recover planted community structure.

Networks & Graph Theory3DAdvanced60 FPS
louvain ↗ Open standalone

About this simulation

This simulation implements the Louvain method, a greedy algorithm for detecting communities in a network by maximizing modularity Q. The graph is generated from a stochastic block model with planted communities, then the algorithm alternates between two phases: local moving, where each node greedily jumps to whichever neighbouring community gives the largest increase in Q, and aggregation, where the resulting communities are collapsed into super-nodes to form a smaller graph for the next level. Repeating these two phases builds a hierarchical decomposition of the network, and modularity rises monotonically until no single move can improve it further.

🔬 What it shows

A random graph built with a stochastic block model: nodes are assigned to planted groups, edges inside a group appear with probability pin and edges between groups with probability pout. Running Louvain on this graph recovers (or fails to recover, when pin and pout are close) the planted structure. The live readouts track modularity Q, the number of detected communities, and the current pass/level as the algorithm converges.

🎮 How to use

Choose a preset — 3 blocks, 4 blocks, Weak structure, or Random (no structure) — or set Nodes, Planted communities, pin and pout yourself and hit Regenerate graph. Use Step to run one local-moving-plus-aggregation pass at a time, or Auto-run to let it play continuously at the chosen Speed, Pause to stop, and Reset to return to the un-clustered starting state. You can also drag any node with the mouse or touch to rearrange the force-directed layout without affecting the clustering.

💡 Did you know?

The default "3 blocks" preset (60 nodes, 3 planted communities, pin = 0.50, pout = 0.03) is deliberately easy: the within-group connection probability is far higher than the between-group one, so Louvain typically recovers the three planted blocks in just a couple of passes. Switch to "Weak structure" or "Random" to see modularity struggle to rise, or even fail to separate the graph into meaningful groups at all.

Frequently asked questions

What is modularity, and what does the formula mean?

Modularity Q measures how much more densely connected nodes within the same community are compared to what you'd expect from a random graph with the same degree sequence. The formula Q = (1/2m)·Σ[A_ij − k_i k_j/2m]·δ(c_i,c_j) sums, over every pair of nodes in the same community, the actual edge weight A_ij minus the expected weight k_i k_j/2m under random wiring. Q ranges roughly from -0.5 to 1, and higher values indicate a stronger community structure.

How does the local-moving phase decide where a node goes?

For each node, the algorithm temporarily removes it from its current community and considers moving it to any community that one of its neighbours belongs to. It computes the modularity gain for each candidate community and moves the node to whichever gives the largest positive gain, or leaves it in place if no move helps. This repeats for every node, over multiple sweeps, until a full sweep produces no more moves.

What happens during the aggregation phase?

Once local moving stabilizes, every detected community is collapsed into a single super-node. Edges between two communities become a single weighted edge between their super-nodes, and edges within a community become a self-loop on the super-node that stores their combined internal weight. Local moving is then re-run on this smaller graph, effectively looking for communities of communities, which is why the process produces a hierarchy of levels rather than a single flat partition.

Why does the algorithm sometimes fail to find the planted communities?

Louvain is a greedy heuristic, not an exact optimizer, so it can only follow moves that improve modularity immediately and can get stuck in a local optimum. When pin and pout are close together, as in the "Weak structure" or "Random" presets, the planted groups aren't actually much denser than the rest of the graph, so there is little modularity signal for the algorithm to detect, and it may merge, split, or miss the true groups.

Does dragging nodes around affect the detected communities?

No. Dragging only changes the on-screen (x, y) position of a node in the force-directed layout used for drawing; it does not touch the underlying adjacency data that Louvain operates on. The layout step itself just runs a simple repulsion/attraction simulation between all node pairs and edges each frame to keep the picture readable, completely separately from the community-detection logic.

⚙ Under the hood

Detect communities by greedily maximizing modularity with the Louvain method. Watch local node moves recover planted structure as Q rises.

Canvas 2DGraph TheoryCommunity DetectionModularityLouvain

3D · Three.js / WebGL renderer · 60 FPS target · runs fully client-side, no install

What did you find?

Add reproduction steps (optional)