Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .wordlist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -798,4 +798,6 @@ PyG
pyg
NeighborLoader
GraphSAGE

subgraph
maxFlow
modelled
5 changes: 5 additions & 0 deletions algorithms/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ This overview summarizes the available algorithms and links to their individual
- [Pathfinding Algorithms](#pathfinding-algorithms)
- [Centrality Measures](#centrality-measures)
- [Community Detection](#community-detection)
- [Network Flow Algorithms](#network-flow-algorithms)

---

Expand Down Expand Up @@ -55,3 +56,7 @@ For path expressions like `shortestPath()` used directly in Cypher queries, refe
- **[CDLP (Community Detection Label Propagation)](./cdlp.md)**
Detects communities in a network, by propagating labels through the graph structure.

## Network Flow Algorithms

- **[MaxFlow](./maxflow.md)**
Comment thread
swilly22 marked this conversation as resolved.
Computes the maximum amount of flow that can be routed through a directed, weighted graph from one or more **source** nodes to one or more **sink** (target) nodes.
175 changes: 175 additions & 0 deletions algorithms/maxflow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
---
title: "Max Flow"
description: "Max Flow"
parent: "Algorithms"
nav_order: 8
---

# Max Flow

## Overview

The Max Flow algorithm computes the maximum amount of flow that can be routed through a directed, weighted graph from one or more **source** nodes to one or more **sink** (target) nodes. Edge weights represent capacities — the upper bound on how much flow an edge can carry.

Max Flow is commonly applied in scenarios such as:
- Network throughput optimization (bandwidth, pipelines, logistics)
- Traffic routing and congestion analysis
- Supply chain and distribution planning
- Bipartite matching and scheduling problems

## Algorithm Details

The procedure implements a capacity-scaling max-flow algorithm over the subgraph induced by the specified node labels and relationship types. It builds a residual graph from the selected edges (using the configured capacity property), then repeatedly finds augmenting paths from the source super-node to the sink super-node and pushes flow along them until no augmenting path exists.

Multiple source or sink nodes are supported by introducing a virtual super-source connected to every source node, and a virtual super-sink connected from every sink node, each with infinite capacity.

The algorithm returns the set of nodes and edges that carry positive flow, together with the per-edge flow values and the total maximum flow.

### Performance

The algorithm operates with a time complexity of **O(V · E²)**, where:
- **|V|** represents the total number of nodes in the subgraph
- **|E|** represents the total number of edges in the subgraph

Comment thread
swilly22 marked this conversation as resolved.
For sparse graphs this is typically much faster in practice.

## Syntax

```cypher
CALL algo.maxFlow(config)
YIELD nodes, edges, edgeFlows, maxFlow
```

### Parameters

The procedure accepts a required configuration `Map` with the following parameters:

| Name | Type | Default | Description |
|----------------------|--------|---------------|-----------------------------------------------------------------------------|
| `sourceNodes` | Array | *(required)* | One or more node objects that act as flow sources |
| `targetNodes` | Array | *(required)* | One or more node objects that act as flow sinks |
| `relationshipTypes` | Array | *(required)* | Relationship types that define the edges of the flow network |
| `capacityProperty` | String | `'capacity'` | Name of the numeric edge property used as the edge capacity |
| `nodeLabels` | Array | All labels | Array of node labels used to restrict which nodes are included |

### Return Values

The procedure yields a single record with the following fields:

| Name | Type | Description |
|-------------|---------|------------------------------------------------------------------------------------|
| `nodes` | Array | All node entities that participate in the max-flow solution (carry positive flow) |
| `edges` | Array | All edge entities that carry positive flow |
| `edgeFlows` | Array | Numeric flow value for each edge in `edges`, in the same order |
| `maxFlow` | Integer | The total maximum flow from all source nodes to all sink nodes |

## Examples

Consider this pipeline network:

```
(A) --[cap:10]--> (B) --[cap:8]--> (C)
\ ^
\----------[cap:5]---------------/
```
Comment on lines +70 to +74
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add a language tag to the fenced diagram block.

This fence is missing a language identifier, which triggers markdownlint MD040.

Suggested fix
-```
+```text
 (A) --[cap:10]--> (B) --[cap:8]--> (C)
  \                                  ^
   \----------[cap:5]---------------/
</details>

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 markdownlint-cli2 (0.21.0)</summary>

[warning] 70-70: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

</details>

</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @algorithms/maxflow.md around lines 70 - 74, The fenced diagram block
containing "(A) --[cap:10]--> (B) --[cap:8]--> (C)" is missing a language tag
which triggers markdownlint MD040; update that fenced code block (the
triple-backtick fence that wraps the diagram) to include a language identifier
such as "text" (i.e., change totext) so the diagram block is properly
tagged.


</details>

<!-- fingerprinting:phantom:triton:hawk -->

<!-- This is an auto-generated comment by CodeRabbit -->


Node **A** is the source, node **C** is the sink. There are two routes from A to C:
- **A → C** directly, with capacity 5
- **A → B → C**, with a bottleneck of 8 (min of 10 and 8)

The maximum flow is therefore **13**.

### Create the Graph

```cypher
CREATE
(a:Node {name: 'A'}),
(b:Node {name: 'B'}),
(c:Node {name: 'C'}),

(a)-[:PIPE {cap: 10}]->(b),
(a)-[:PIPE {cap: 5}]->(c),
(b)-[:PIPE {cap: 8}]->(c)
```

### Example: Compute the maximum flow between two nodes

```cypher
MATCH (s:Node {name: 'A'}), (t:Node {name: 'C'})
CALL algo.maxFlow({
sourceNodes: [s],
targetNodes: [t],
capacityProperty: 'cap',
relationshipTypes: ['PIPE']
})
YIELD nodes, edges, edgeFlows, maxFlow
RETURN maxFlow
```

#### Expected Results

| maxFlow |
|---------|
| `13` |

### Example: Inspect per-edge flow on the solution

```cypher
MATCH (s:Node {name: 'A'}), (t:Node {name: 'C'})
CALL algo.maxFlow({
sourceNodes: [s],
targetNodes: [t],
capacityProperty: 'cap',
relationshipTypes: ['PIPE']
})
YIELD edges, edgeFlows
UNWIND range(0, size(edges) - 1) AS i
RETURN
startNode(edges[i]).name AS from,
endNode(edges[i]).name AS to,
edgeFlows[i] AS flow
```

#### Expected Results

| from | to | flow |
|------|-----|------|
| `A` | `B` | `8` |
| `A` | `C` | `5` |
| `B` | `C` | `8` |

### Example: Restrict the subgraph by node label

When the graph contains multiple node labels, use `nodeLabels` to limit the algorithm to a specific subset of nodes:

```cypher
MATCH (s:Intersection {name: 'Source'}), (t:Intersection {name: 'Sink'})
CALL algo.maxFlow({
sourceNodes: [s],
targetNodes: [t],
capacityProperty: 'bandwidth',
nodeLabels: ['Intersection'],
relationshipTypes: ['CONNECTS']
})
YIELD nodes, maxFlow
RETURN size(nodes) AS participatingNodes, maxFlow
```

### Example: Multiple sources and multiple sinks

`sourceNodes` and `targetNodes` each accept arrays, allowing multi-commodity-style problems to be modelled with virtual super-nodes:

```cypher
MATCH
(s1:Node {name: 'SourceA'}),
(s2:Node {name: 'SourceB'}),
(t:Node {name: 'Sink'})
CALL algo.maxFlow({
sourceNodes: [s1, s2],
targetNodes: [t],
capacityProperty: 'cap',
relationshipTypes: ['PIPE']
})
YIELD maxFlow
RETURN maxFlow
```
Loading