Skip to main content

ForceAtlas2

SQL function: cugraph_force_atlas2

Official cuGraph reference: Python API

Place vertices in two dimensions with a force-directed simulation that attracts connected vertices and repels vertices from one another.

Signature

cugraph_force_atlas2(table_name [, src_col, dst_col [, weight_col [, options_json]]])

Quickstart

The call below expects a registered edge table or view target_edges with endpoint columns src and dst. Substitute your own registered relations.

SELECT * FROM cugraph_force_atlas2('target_edges');

Inputs

table_name must be a registered edge table or view (the edges role); optional relations are named by their side-input table options. Parenthesized subqueries are not accepted, and metadata validation resolves the same registered names.

RoleRequiredContract
edgesyesRequired edge-list table or view for graph construction.
vertex_attributesnoOptional complete per-vertex radius, mobility, and mass relation.
initial_positionsnoOptional complete per-vertex Float32 x/y warm-start relation.

Endpoint columns accept numeric Int32, Int64 vertex IDs or logical string Utf8, LargeUtf8, Utf8View vertex IDs; string vertex-identity outputs are canonicalized to Utf8 (native mapping Int64) while scores, distances, counts, coordinates, and opaque labels stay numeric. The shared vertex-ID contract is summarized in Vertex ID support; the concrete call-specific schema comes 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

Arguments and options

Positional scalar arguments

src_col and dst_col name the edge endpoint columns; both are optional and default to src and dst.

ArgumentTypeRequiredDefaultNotes
weight_colUtf8|nullnooptional edge weight column for graph construction when supported by the algorithm; semantic effect: edge weights affect algorithm results when provided

JSON options

OptionTypeDefaultConstraintsDescription
barnes_hut_optimizeBooleanfalseUses the Barnes-Hut approximation for repulsion instead of the slower exact computation.
barnes_hut_thetaFloat640.5min 0; max 1Barnes-Hut trade-off in [0, 1]: 1 favors speed, 0 favors accuracy. Used only when barnes_hut_optimize is true.
edge_weight_influenceFloat641min 0How much edge weights influence attraction: 0 ignores weights, 1 is the normal weighting, and larger values amplify heavy edges.
gravityFloat641min 0Strength of the pull toward the center, which keeps disconnected islands from drifting away.
initial_positions_tableUtf8|nullnullside input (initial_positions, cols: initial_positions_vertex_col, initial_x_col, initial_y_col)Optional relation with exactly one warm-start x/y position per graph vertex; when omitted, initial positions are random.
initial_positions_vertex_colUtf8|nullnullcolumn of initial_positions_table; type ref vertex_domainVertex identifier column in initial_positions_table; must match the edge endpoint domain.
initial_x_colUtf8|nullnullcolumn of initial_positions_table; type ref Float32Starting x-axis position per vertex.
initial_y_colUtf8|nullnullcolumn of initial_positions_table; type ref Float32Starting y-axis position per vertex.
jitter_toleranceFloat641min 0How much swinging is tolerated when adapting speed; lower values give less speed and more precision, and values above 1 are discouraged.
lin_log_modeBooleanfalseSwitches the attraction model from lin-lin to lin-log, which makes clusters tighter; scaling_ratio usually needs readjusting.
max_iterUInt32500min 1; max 2147483647Number of layout iterations to run; the layout stops after this many without error. cuGraph suggests 50-100 iterations for quick results and discourages more than 1000.
outbound_attraction_distributionBooleanfalseDistributes attraction along outbound edges so hubs attract less and are pushed toward the borders.
overlap_scaling_ratioFloat642> 0Scales the repulsion force between two overlapping vertices when prevent_overlapping is true.
prevent_overlappingBooleanfalsevalid when true requires vertex_attributes_table and vertex_radius_colPrevents vertices from overlapping, using the per-vertex radius side input.
scaling_ratioFloat642> 0Repulsion strength; larger values spread the layout out. Readjust it when switching lin_log_mode.
seedUInt640Seed for the random initial positions used when initial_positions_table is not supplied. It does not make layouts reproducible; reruns may place individual vertices far apart.
strong_gravity_modeBooleanfalseUses a stronger gravity law that pulls distant vertices toward the center harder; it can dominate the other forces.
verboseBooleanfalseMakes cuGraph print convergence information at each iteration.
vertex_attributes_tableUtf8|nullnullside input (vertex_attributes, cols: vertex_attributes_vertex_col, vertex_radius_col, vertex_mobility_col, vertex_mass_col)Optional relation with exactly one row per graph vertex carrying radius, mobility, and/or mass attributes.
vertex_attributes_vertex_colUtf8|nullnullcolumn of vertex_attributes_table; type ref vertex_domainVertex identifier column in vertex_attributes_table; must match the edge endpoint domain.
vertex_mass_colUtf8|nullnullcolumn of vertex_attributes_table; type ref Float32Per-vertex mass, which controls attraction to other vertices; when omitted, each vertex's mass is its degree plus one.
vertex_mobility_colUtf8|nullnullcolumn of vertex_attributes_table; type ref Float32Per-vertex mobility: a scaling factor on the vertex's displacement at each iteration.
vertex_radius_colUtf8|nullnullcolumn of vertex_attributes_table; type ref Float32Per-vertex radius, used when prevent_overlapping is true.

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

ColumnTypeNullableDescription
vertexInt64|Utf8noVertex receiving ForceAtlas2 layout coordinates.
xFloat32noX coordinate assigned by ForceAtlas2.
yFloat32noY coordinate assigned by ForceAtlas2.

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.

Lay out an ego network on the GPU

Three statements build the one-hop neighborhood 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; the browser draws only what the SQL returned. Louvain's partitions correspond to distinct 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 different (equally valid) coordinates on each run; on larger graphs individual vertices may land far apart. 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.

Refine a saved layout with radius and mass

The optional relations are complete vertex-domain tables. This second pass uses the first pass as its warm start and supplies one radius and mass value for every vertex:

CREATE VIEW initial_layout AS
SELECT vertex, x, y
FROM cugraph_force_atlas2(
'attention_ego_edges', 'src', 'dst', NULL,
'{"max_iter":250,"seed":42}');

CREATE VIEW layout_attributes AS
SELECT vertex,
CAST(0.75 AS REAL) AS radius,
CAST(1.0 AS REAL) AS mass
FROM initial_layout;

SELECT vertex, x, y
FROM cugraph_force_atlas2(
'attention_ego_edges', 'src', 'dst', NULL,
'{
"max_iter":250,
"seed":42,
"prevent_overlapping":true,
"vertex_attributes_table":"layout_attributes",
"vertex_attributes_vertex_col":"vertex",
"vertex_radius_col":"radius",
"vertex_mass_col":"mass",
"initial_positions_table":"initial_layout",
"initial_positions_vertex_col":"vertex",
"initial_x_col":"x",
"initial_y_col":"y"
}');

Both side inputs reject null, duplicate, missing, or extra vertices. Radius, mass, mobility, and coordinates are Float32; their vertex column must match the edge endpoint domain.

Limits

  • vertex_attributes and initial_positions must contain exactly one non-null row for every graph vertex
  • duplicate, missing, and extra ForceAtlas2 side-input vertices are rejected at execution
  • radius, mobility, mass, x, and y side-input columns must be Float32
  • prevent_overlapping=true requires a radius binding

Validate the call

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_force_atlas2',
'{"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.