The SLPA (Speaker-Listener Label Propagation Algorithm) detects overlapping communities, where nodes can belong to multiple communities simultaneously. Unlike standard Label Propagation which assigns each node to exactly one community, SLPA maintains a memory of labels each node has received, allowing it to identify multiple community memberships.
References:
In many real-world networks, nodes naturally belong to multiple communities. For example, a person may belong to a work group, a family group, and a hobby group simultaneously.
Standard community detection algorithms assign each node to exactly one community. SLPA addresses this limitation by allowing nodes to have multiple community memberships.
The algorithm works through an iterative process where nodes exchange labels:
threshold.For example, in this graph:
A=[0], B=[1], C=[2], D=[3]B is selected as the listener. Its neighbors A, C, D each send a random label from their memory. Suppose they send 0, 2, 3. The most frequent label is a tie — say 0 wins. B's memory becomes [1, 0]. Then the algorithm selects another node as the listenser.B's memory might be [1, 0, 0, 2, 0, 2, 0, 2, ...], accumulating different labels from its neighbors over time. If both label 0 and label 2 each appear ≥ 10% of the time (e.g., threshold: 0.1), node B is assigned to both community 0 and community 2 — it is an overlapping node.A lower threshold allows more overlapping memberships; a higher threshold produces fewer, more confident assignments.
GQLINSERT (A:user {_id: "A"}), (B:user {_id: "B"}), (C:user {_id: "C"}), (D:user {_id: "D"}), (E:user {_id: "E"}), (F:user {_id: "F"}), (G:user {_id: "G"}), (H:user {_id: "H"}), (I:user {_id: "I"}), (J:user {_id: "J"}), (K:user {_id: "K"}), (L:user {_id: "L"}), (M:user {_id: "M"}), (N:user {_id: "N"}), (O:user {_id: "O"}), (A)-[:connect]->(B), (A)-[:connect]->(C), (A)-[:connect]->(F), (A)-[:connect]->(K), (B)-[:connect]->(C), (C)-[:connect]->(D), (D)-[:connect]->(A), (D)-[:connect]->(E), (E)-[:connect]->(A), (F)-[:connect]->(G), (F)-[:connect]->(J), (G)-[:connect]->(H), (H)-[:connect]->(F), (I)-[:connect]->(F), (I)-[:connect]->(H), (J)-[:connect]->(I), (K)-[:connect]->(F), (K)-[:connect]->(N), (L)-[:connect]->(M), (L)-[:connect]->(N), (M)-[:connect]->(K), (M)-[:connect]->(N), (N)-[:connect]->(M), (O)-[:connect]->(N)
| Name | Type | Default | Description |
|---|---|---|---|
iterations | INT | 20 | Number of propagation iterations. |
threshold | FLOAT | 0.1 | Label frequency threshold for community membership (0 < threshold ≤ 1). A label is kept only if its proportion in a node's memory is ≥ threshold. |
limit | INT | -1 | Limits the number of results returned (-1 = all). |
order | STRING | / | Sorts the results by communities: asc or desc. |
Returns:
| Column | Type | Description |
|---|---|---|
nodeId | STRING | Node identifier (_id) |
communities | LIST | List of community IDs the node belongs to |
GQLCALL algo.slpa({ iterations: 20, threshold: 0.5 }) YIELD nodeId, communities
Result:
| nodeId | communities |
|---|---|
| A | [4] |
| B | [4] |
| C | [4] |
| D | [4] |
| E | [4] |
| F | [3] |
| G | [2] |
| H | [3] |
| I | [3] |
| J | [3] |
| K | [7] |
| L | [8] |
| M | [8] |
| N | [7] |
| O | [8] |
Returns the same columns as run mode, streamed for memory efficiency.
GQLCALL algo.slpa.stream({ iterations: 30, threshold: 0.7 }) YIELD nodeId, communities RETURN nodeId, communities
Result:
| nodeId | communities |
|---|---|
| A | [4] |
| B | [4] |
| C | [4] |
| D | [4] |
| E | [4] |
| F | [3] |
| G | [2] |
| H | [2] |
| I | [3] |
| J | [3] |
| K | [13] |
| L | [13] |
| M | [13] |
| N | [13] |
| O | [13] |
Returns:
| Column | Type | Description |
|---|---|---|
nodeCount | INT | Total number of nodes |
communityCount | INT | Number of unique communities detected |
GQLCALL algo.slpa.stats({ threshold: 0.5 }) YIELD nodeCount, communityCount
Result:
| nodeCount | communityCount |
|---|---|
| 15 | 4 |
Computes results and writes them back to node properties. The write configuration is passed as a second argument map.
Write parameters:
| Name | Type | Description |
|---|---|---|
db.property | STRING or MAP | Node property to write results to. String: writes the communities column in results to a property. Map: explicit column-to-property mapping (e.g., {communities: 'comm_list'}). |
Writable columns:
| Column | Type | Description |
|---|---|---|
communities | LIST | List of community IDs |
Returns:
| Column | Type | Description |
|---|---|---|
task_id | STRING | Task identifier for tracking via SHOW TASKS |
nodesWritten | INT | Number of nodes with properties written |
computeTimeMs | INT | Time spent computing the algorithm (milliseconds) |
writeTimeMs | INT | Time spent writing properties to storage (milliseconds) |
GQLCALL algo.slpa.write({iterations: 20, threshold: 0.1}, { db: { property: "comm_list" } }) YIELD task_id, nodesWritten, computeTimeMs, writeTimeMs