Skip to content

[Feature] Extend Leiden/Louvain community detection: multi-label graphs and stable incremental updates #709

Description

@BingqingLyu

Is your feature request related to a problem? Please describe.

The current Leiden/Louvain community detection only handles a single vertex label and a single edge label (simple graphs), and re-running on updated data produces a completely fresh, unrelated community labeling. This blocks two real-world needs:

  1. Heterogeneous (multi-label) graphs. A projected graph may contain multiple vertex labels and multiple edge triplets that should be treated as one graph for community detection. For example, both temp_person and person vertices, connected by both temp_knows and knows edges, need to be clustered together in a single run.

  2. Incremental / stable community updates. When the underlying data changes and the algorithm is re-run, community IDs are reassigned from scratch. Downstream consumers cannot tell which communities are "the same" across runs. We need the community results to be incremental and stable: unchanged parts of the graph should keep their original community IDs, so only genuinely changed regions get new/updated assignments.

Describe the solution you'd like

Extend leiden and louvain (keeping the existing public interface unchanged) to support:

  1. Multi-label / multi-triplet input.

    • Accept a projected graph with multiple vertex labels and multiple edge triplets, e.g.:
      CALL project_graph('g', ['temp_person', 'person'],
        {'[temp_person, temp_knows, person]': '',
         '[person, knows, person]': ''});
      CALL leiden('g', {concurrency: 4}) YIELD node, community RETURN node, community;
      
    • All labels/triplets are treated as one unified graph; a global vertex indexing scheme handles overlapping local vertex IDs across labels.
    • Single-label + single-triplet graphs must retain the current performance (zero overhead vs. the original simple-graph path).
  2. Incremental warm-start with stable community IDs.

    • Add an initial_community_property option so a previously written-back community property can seed the next run:
      CALL leiden('g', {initial_community_property: 'comm'}) YIELD node, community ...;
      
    • When the data is unchanged, results must be identical to the seeding run (fully stable).
    • When the data changes, unchanged communities should inherit their original IDs (e.g., majority-vote mapping from new clusters back to old IDs), so only changed regions receive new IDs.

Acceptance criteria

  • leiden / louvain run correctly on a graph with two vertex labels and two edge triplets (e.g., temp_person/person + temp_knows/knows).
  • With initial_community_property set and data unchanged, re-running yields identical community assignments.
  • Public Cypher interface (CALL leiden(...) / CALL louvain(...), YIELD node, community) stays backward compatible; existing queries need no changes.
  • Simple-graph performance is not regressed.

Describe alternatives you've considered

  • Introducing separate multi_label_leiden / multi_label_louvain functions instead of extending the existing ones. Rejected to avoid interface fragmentation and duplicate maintenance; the existing names should transparently gain the new capabilities.

Additional context
Example incremental workflow: run once to get communities, write them back to a vertex property (via ALTER TABLE ... ADD + SET), re-project the graph, then re-run with initial_community_property pointing at that property to obtain stable, incremental results.

Metadata

Metadata

Assignees

Labels

Projects

Status
In progress

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions