ForceAtlas2
SQL function: cugraph_force_atlas2
Compute ForceAtlas2 two-dimensional layout coordinates.
Signature
cugraph_force_atlas2(table_name [, src_col, dst_col [, weight_col [, options_json]]])
Allowed argument counts: 1, 3, 4, 5.
Quickstart
SELECT * FROM cugraph_force_atlas2('target_edges')
Positional arguments
| Argument | Type | Required | Default | Notes |
|---|---|---|---|---|
table_name | Utf8 | yes | ||
src_col | Utf8 | no | src | |
dst_col | Utf8 | no | dst | |
weight_col | Utf8|null | no | optional edge weight column for graph construction when supported by the algorithm; semantic effect: edge weights affect algorithm results when provided | |
options_json | Utf8 | no |
JSON options
| Option | Type | Default | Constraints | Description |
|---|---|---|---|---|
barnes_hut_optimize | Boolean | false | ||
barnes_hut_theta | Float64 | 0.5 | min 0; max 1 | |
edge_weight_influence | Float64 | 1 | min 0 | |
gravity | Float64 | 1 | min 0 | |
jitter_tolerance | Float64 | 1 | min 0 | |
lin_log_mode | Boolean | false | ||
max_iter | UInt32 | 500 | min 1; max 2147483647 | |
outbound_attraction_distribution | Boolean | false | ||
overlap_scaling_ratio | Float64 | 2 | > 0 | |
prevent_overlapping | Boolean | false | one of false; valid when unsupported until vertex_radius side inputs are exposed by the SQL API | |
scaling_ratio | Float64 | 2 | > 0 | |
seed | UInt64 | 0 | ||
strong_gravity_mode | Boolean | false | ||
verbose | Boolean | false |
Graph construction options
Shared by all cuGraph functions, shown here with this function's defaults. The construction_policy option controls whether Nexus requests Python cuGraph-compatible edge normalization or bypasses it for raw libcugraph-style construction; see graph construction options for the full policy guide.
| Option | Type | Default | Constraints | Description |
|---|---|---|---|---|
construction_policy | Utf8 | "python_cugraph" | one of "python_cugraph", "raw_libcugraph" | Edge-list construction semantics used before calling libcugraph. |
directed | Boolean | false | Whether graph construction treats edges as directed. | |
renumber | Boolean | true | Whether graph construction may renumber external vertex identifiers internally. |
Output schema
| Column | Type | Nullable | Description |
|---|---|---|---|
vertex | Int64 | no | Vertex receiving ForceAtlas2 layout coordinates. |
x | Float32 | no | X coordinate assigned by ForceAtlas2. |
y | Float32 | no | Y coordinate assigned by ForceAtlas2. |
These are the generic registry schemas. Run cugraph_validate_call for the concrete, table-specific output schema of a particular call.
Examples
This example runs on the citation network demo dataset.
Lay out an ego network on the GPU
Three statements build the one-hop world around Attention Is All You Need
(its ~40 references, its 110 most-cited citers, and every citation among
them), and ForceAtlas2 returns drawable coordinates. A second call —
cugraph_louvain on the same edge view — colors the clusters:
CREATE VIEW attention_ego_nodes AS
SELECT paper_id FROM (
SELECT dst AS paper_id FROM citation_edges WHERE src = 2963403868
UNION ALL
SELECT src AS paper_id FROM (
SELECT e.src, p.n_citation
FROM citation_edges_by_dst e JOIN papers p ON p.paper_id = e.src
WHERE e.dst = 2963403868
ORDER BY p.n_citation DESC LIMIT 110) t
UNION ALL
SELECT 2963403868 AS paper_id
) u GROUP BY paper_id;
CREATE VIEW attention_ego_edges AS
SELECT e.src, e.dst
FROM citation_edges e
JOIN attention_ego_nodes a ON a.paper_id = e.src
JOIN attention_ego_nodes b ON b.paper_id = e.dst;
WITH layout AS (
SELECT vertex, x, y
FROM cugraph_force_atlas2('attention_ego_edges', 'src', 'dst', NULL,
'{"max_iter":500, "seed":42}')),
community AS (
SELECT vertex, "partition"
FROM cugraph_louvain('attention_ego_edges', 'src', 'dst'))
SELECT l.vertex, l.x, l.y, c."partition", p.title, p.year
FROM layout l
JOIN community c ON c.vertex = l.vertex
JOIN papers p ON p.paper_id = l.vertex;
The figure below renders that query's actual output — 133 rows of
(vertex, x, y, partition, title, year) — with no client-side layout at all;
the browser only draws what the SQL returned. Louvain's partitions turn out
to be readable research threads (labels assigned by inspecting each
cluster's members):
seed fixes the initial placement, but the parallel layout itself is not
bit-reproducible — expect slightly different (equally valid) coordinates on
each run. If downstream queries must agree on positions, snapshot into the
mutable datafusion.public workspace with CREATE TABLE … AS; that does not
write back to the Iceberg source catalog.
Limitations & notes
- dry-run validates table resolution, column presence, static dtypes, and options only
- dry-run does not scan edge data, construct a graph, or prove source-vertex existence
- prevent_overlapping=true is rejected until vertex_radius side inputs are exposed
Validate before running
Always dry-run a call before executing it. Validation checks the function, table, columns, dtypes, and options without touching the GPU:
SELECT * FROM cugraph_validate_call(
'cugraph_force_atlas2',
'your_edges_table',
'{"src_col":"src","dst_col":"dst"}'
);
See Discovery & validation for the full cugraph_validate_call contract.