Skip to content

feat(clustering): Leiden community detection (well-connected communities) - #8

Closed
seilat wants to merge 2 commits into
feat/louvain-clusteringfrom
feat/leiden-clustering
Closed

feat(clustering): Leiden community detection (well-connected communities)#8
seilat wants to merge 2 commits into
feat/louvain-clusteringfrom
feat/leiden-clustering

Conversation

@seilat

@seilat seilat commented May 30, 2026

Copy link
Copy Markdown
Owner

Self-review PR (fork only — not upstream; stacked on the Louvain branch, holds for jgrapht-dev).

What (Workstream E2, stacked on #7)

  • E2.0 — extract package-private CommunityAggregation (compact / numberOfCommunities /
    degree-conserving aggregate that compacts labels internally) and refactor LouvainClustering
    onto it. Behaviour-preserving: Louvain's 17 tests stay green. Internal compaction removes the
    implicit "caller passes compact labels" coupling flagged in the Louvain review, so Leiden can
    aggregate its non-compact refined partitions safely.
  • E2.1LeidenClustering implements ClusteringAlgorithm<V>. Multilevel local-moving +
    refinement (sub-communities grow only along edges → each connected) + aggregation over the
    refined partition + a final connected-components split that guarantees every reported community
    is connected
    — the property Louvain lacks (Traag-Waltman-van Eck 2019).
  • E2.2 — 16 tests incl. the headline everyCommunityIsConnected oracle (ConnectivityInspector
    per induced subgraph, structured + 30 random graphs).

Verification

  • 33/33 clustering tests (Leiden 16 + Louvain 17). checkstyle 0 violations, javadoc clean.
  • Connectivity guarantee asserted directly via induced-subgraph ConnectivityInspector.

Honest scope notes

  • Modularity is competitive with Louvain, not strictly ≥ — Leiden trades a sliver of Q for
    guaranteed connectivity (worst observed gap on random graphs: 4×10⁻⁴; test allows 0.02).
  • Simplifications vs the full paper (documented in the class javadoc): local-moving restarts from
    singletons each level rather than seeding from the previous partition; the refinement gate is
    connectivity + positive gain rather than the resolution-parametrised well-connected test. The
    connectivity guarantee is enforced unconditionally by the final connected-components split.
  • resolution constructor parameter deferred.

Review focus

  • refinement correctness (connectivity by construction; stays within a Louvain community)
  • CommunityAggregation.aggregate internal compaction + degree conservation
  • termination safeguard (stop when aggregation can't shrink the graph)

🤖 Generated with Claude Code

seilat and others added 2 commits May 30, 2026 12:30
…unities)

Builds on Louvain (E2):

- E2.0: extract package-private CommunityAggregation (compact /
  numberOfCommunities / degree-conserving aggregate that compacts labels
  internally) and refactor LouvainClustering to use it. Behaviour-preserving:
  Louvain's 17 tests stay green. The internal compaction removes the implicit
  'caller must pass compact labels' coupling flagged in review, so Leiden can
  aggregate its non-compact refined partitions safely.
- E2.1: LeidenClustering implementing ClusteringAlgorithm<V>. Multilevel
  local-moving + a refinement phase whose sub-communities grow only along
  edges (so each is connected), aggregation over the refined partition, and a
  final connected-components split that guarantees every reported community is
  connected -- the property Louvain lacks. Non-negative/zero-weight guards
  mirror Louvain.
- E2.2: 16 tests incl. the headline everyCommunityIsConnected oracle
  (ConnectivityInspector per induced subgraph, structured + 30 random graphs),
  clique/ring/complete/weighted parity, determinism, edge cases, and a
  modularity-vs-Louvain comparison (competitive within 0.02; Leiden trades a
  sliver of modularity for guaranteed connectivity).

33/33 clustering tests pass; checkstyle + javadoc clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Leiden vs Louvain vs LabelPropagation vs GreedyModularity on planted
partitions. Leiden costs ~1.4-1.5x Louvain (refinement + connectivity-split
passes) while staying 7-9x faster than GreedyModularity; scaling parallels
Louvain. Cost (ms/op): 125-node Louvain 0.28 / Leiden 0.42; 500-node
Louvain 3.05 / Leiden 4.17.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@seilat

seilat commented May 30, 2026

Copy link
Copy Markdown
Owner Author

Superseded by #9 — Louvain + Leiden combined into a single clustering PR.

@seilat seilat closed this May 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant