ECG
SQL function: cugraph_ecg
Official cuGraph reference: C API
Stabilize community assignments by combining an ensemble of randomized Louvain partitions into a final consensus clustering.
Signature
cugraph_ecg(table_name [, src_col, dst_col [, weight_col [, options_json]]])
Relation inputs
The first positional argument names a registered edge table or view (the edges role). Parenthesized relation subqueries are not accepted; metadata validation uses the same registered name.
Vertex ID types
The edges relation declares the accepted vertex-ID domains. Numeric calls preserve the existing numeric schema. When logical string support is declared, Utf8, LargeUtf8, and Utf8View endpoint columns share one logical domain; their vertex-identity outputs are canonicalized to Utf8.
| Domain | Accepted endpoint inputs | Output contract |
|---|---|---|
| Numeric edge endpoints | Int32, Int64 | The numeric output schema is used for numeric calls. |
| Logical string edge endpoints | Utf8, LargeUtf8, Utf8View | Vertex identity columns are canonicalized to Utf8; scores, distances, counts, coordinates, and opaque labels remain numeric. |
The native mapping type is Int64. Call-specific output schemas come from gpu_validate_call.
Logical string side-input limitations:
- edge ID columns and edge-ID predicate side inputs are not supported for logical string graphs
Scalar arguments & JSON options
Positional scalar arguments
src_col and dst_col name the edge endpoint columns; both are optional and default to src and dst.
| Argument | Type | Required | Default | Notes |
|---|---|---|---|---|
weight_col | Utf8|null | no | accepted as an edge-column binding; native algorithm execution does not consume weights; semantic effect: none for this algorithm |
JSON options
| Option | Type | Default | Constraints | Description |
|---|---|---|---|---|
ensemble_size | UInt32 | 10 | min 1 | |
max_level | UInt32 | 100 | min 1 | |
min_weight | Float64 | 0.001 | min 0 | |
resolution | Float64 | 1 | > 0 | |
seed | UInt64 | 0 | ||
threshold | Float64 | 1e-7 | min 0 |
Graph construction options
This function builds an undirected graph by default (directed=false); all other graph construction options follow the shared defaults documented in Graph Construction Options.
Output schema
| Column | Type | Nullable | Description |
|---|---|---|---|
vertex | Int64|Utf8 | no | Vertex assigned to an ECG community. |
partition | Int64 | no | Community identifier assigned by ECG. |
These are generic descriptor schemas; validate the call to get the concrete, table-specific output schema.
Examples
This example runs on the citation network demo dataset.
Benchmark the ensemble against single-run algorithms
ECG runs an ensemble of Louvain passes (ensemble_size, default 10), reweights
edges by how often their endpoints co-cluster, and clusters the consensus. Is
that worth it? Because every cugraph_* function returns a plain relation, one
statement can run all three community algorithms on the same subgraph (the
Louvain example's 2010s AI views) and score them against the human-assigned
primary_fos labels — the share of members in a community carrying its
dominant label:
CREATE OR REPLACE VIEW ai_nodes AS
SELECT paper_id FROM papers
WHERE year >= 2010 AND primary_fos IN (
'Deep learning', 'Artificial neural network', 'Convolutional neural network',
'Recurrent neural network', 'Natural language processing',
'Reinforcement learning', 'Image segmentation', 'Feature extraction',
'Object detection', 'Speech recognition');
CREATE OR REPLACE VIEW ai_edges AS
SELECT e.src, e.dst
FROM citation_edges e
JOIN ai_nodes a ON a.paper_id = e.src
JOIN ai_nodes b ON b.paper_id = e.dst;
WITH labeled AS (
SELECT 'louvain' AS algorithm, c."partition" AS community, p.primary_fos
FROM cugraph_louvain('ai_edges', 'src', 'dst') c
JOIN papers p ON p.paper_id = c.vertex
UNION ALL
SELECT 'leiden', c."partition", p.primary_fos
FROM cugraph_leiden('ai_edges', 'src', 'dst') c
JOIN papers p ON p.paper_id = c.vertex
UNION ALL
SELECT 'ecg', c."partition", p.primary_fos
FROM cugraph_ecg('ai_edges', 'src', 'dst') c
JOIN papers p ON p.paper_id = c.vertex),
counts AS (
SELECT algorithm, community, primary_fos, COUNT(*) AS n
FROM labeled GROUP BY 1, 2, 3),
sized AS (
SELECT algorithm, community, SUM(n) AS members, MAX(n) AS top_label
FROM counts GROUP BY 1, 2)
SELECT algorithm,
COUNT(*) AS communities,
COUNT(*) FILTER (WHERE members >= 100) AS ge100,
ROUND(SUM(top_label) FILTER (WHERE members >= 100) * 100.0
/ SUM(members) FILTER (WHERE members >= 100), 1) AS purity_pct
FROM sized
GROUP BY algorithm
ORDER BY purity_pct DESC;
| algorithm | communities | ge100 | purity_pct |
|---|---|---|---|
| leiden | 2,670 | 16 | 44.1 |
| ecg | 5,014 | 41 | 41.7 |
| louvain | 1,960 | 14 | 38.5 |
Three GPU graph builds plus the joins and aggregation return together in about
one second. ECG's consensus is deliberately conservative: it only keeps
vertices together when most ensemble members agree, so it produces the finest
partition (5,014 communities, 41 of them with 100+ papers) and beats a single
Louvain run on label purity. Determinism comes from seed (default 0);
ensemble_size trades run time for consensus stability.
Limitations & lifecycle
No algorithm-specific limitations.
Validate before running
Dry-run validation checks registered relation metadata, column presence, static dtypes, and options only; it does not scan edge data, construct a graph, or prove source-vertex existence:
SELECT * FROM gpu_validate_call(
'cugraph_ecg',
'{"schema_version":1,"relations":{"edges":{"table":"target_edges"}},"options":{"src_col":"src","dst_col":"dst"}}'
);
See GPU Function Catalog API for the full gpu_validate_call contract.