Skip to content

island discovery: edge discovery#1101

Open
thowell wants to merge 6 commits intogoogle-deepmind:mainfrom
thowell:edge_discovery
Open

island discovery: edge discovery#1101
thowell wants to merge 6 commits intogoogle-deepmind:mainfrom
thowell:edge_discovery

Conversation

@thowell
Copy link
Collaborator

@thowell thowell commented Jan 31, 2026

implements the host function tree_edges and a collection of kernels to compute tree-tree edge structure in the constraint Jacobian types.Constraint.J ("efc_J")

depends on #1100

Model fields:
- ntree: number of kinematic trees
- tree_dofadr: start address of tree's DOFs (ntree,)
- tree_dofnum: number of DOFs in tree (ntree,)
- tree_bodynum: number of bodies in tree (ntree,)
- body_treeid: id of body's tree; -1 for static (nbody,)
- dof_treeid: id of dof's tree (nv,)

All fields are imported directly from mjModel via the dataclass field
matching pattern in put_model().

Test: test_tree_structure_fields verifies all fields match MuJoCo.
- _find_tree_edges kernel scans Jacobian for tree-tree connections
- On-device deduplication using radix sort and prefix sum compaction
- Helper kernels: _compute_edge_keys, _init_indices, _mark_unique_edges, _compact_edges
- find_tree_edges host function orchestrates the full pipeline
- 5 tests: single edge, self-edge, chain, deduplication, no constraints
@thowell thowell linked an issue Jan 31, 2026 that may be closed by this pull request
@thowell thowell mentioned this pull request Jan 31, 2026
Copy link
Collaborator

@yuvaltassa yuvaltassa left a comment

Choose a reason for hiding this comment

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

I'm not sure this is the right approach on GPU. In the C code and this PR we compute the incidence matrix which is then used to compute the adjacency matrix K. But the sparse adjacency matrix is probably overkill and if K, which is just ntree x ntree is allocated densely then you can compute it directly in parallel quite efficiently IMO.

Imagine that all your threads are just scanning the Jacobian rows in parallel. Every time I see a nonzero in tree i and tree j I set K[i,j] = 1, done.

Let's discuss offline?

# skip continuation rows (same constraint type and id as previous)
# this avoids duplicate edges from multi-row constraints (e.g., 3D contacts)
if efcid > 0:
if efc_type_in[worldid, efcid] == efc_type_in[worldid, efcid - 1]:
Copy link
Collaborator

Choose a reason for hiding this comment

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

are we sure that type + id uniquely identifies the column pattern? I think I made that assumption at some point and discovered it was wrong, but I can't quite remember the counterexample. I might be wrong and this could be correct.

@thowell thowell force-pushed the edge_discovery branch 2 times, most recently from fb62446 to 6b5ce5e Compare February 3, 2026 11:53
@thowell
Copy link
Collaborator Author

thowell commented Feb 4, 2026

previous implementation was incorrect/incomplete and has been refactored with different parallelism

@thowell thowell added this to the Islands milestone Feb 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

constraint islands

2 participants