Skip to content

Fix Zygote gradient through add_edges - #729

Merged
CarloLucibello merged 7 commits into
JuliaGraphs:masterfrom
DHAKED440:fix/add-edges-zygote-segfault
Nov 11, 2026
Merged

CarloLucibello merged 7 commits into
JuliaGraphs:masterfrom
DHAKED440:fix/add-edges-zygote-segfault

Conversation

@DHAKED440

@DHAKED440 DHAKED440 commented Nov 5, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #671

Summary

Fix the sample_neighbors and Zygote-through-add_edges failures found in CI.

Changes

  • Handle nodes with no neighbors when sampling, including with replacement, while preserving normal sampling behavior.
  • Keep reconstruction of empty graph metadata out of Zygote’s differentiated path while preserving gradients through edge weights.
  • Add regression tests for empty and non-empty neighbor sampling, graph edge and weight preservation, and differentiation through add_edges.

Tests

  • Focused sample_neighbors tests: 31 passed.
  • Focused add_edges/Zygote tests: 16 passed.
  • GNNGraphs CPU suite: 1,368 passed, 8 broken.
  • GNNGraphs CI on Julia 1.10 and latest stable: passed.

Before and after

The CI failures involved sampling from an empty neighbor list and Zygote processing empty graph metadata. Both affected GNNGraphs CI checks now pass. The add_edges regression returns the expected gradient: Float32[1.0, 1.0].

@CarloLucibello

Copy link
Copy Markdown
Member

Thanks for this! I checked the branch out and ran it locally (Julia 1.13.3).

Verified

  • On master, differentiating through add_edges fails (map is not defined on sets: Zygote differentiates the keys(x1) comprehension in cat_features(::Dict, ::Dict)). On this branch the Differentiating across add_edges causes Zygote to segfault #671 reproducer returns Float32[1.0, 1.0]. It also works with non-empty edata, which fails on master too.
  • sample_neighbors(...; replace=true) on zero-degree nodes: 3/300 random graphs failed on master, 0/300 here.

Suggestions

  1. The datastore.jl change looks redundant. With only that file reverted, the Differentiating across add_edges causes Zygote to segfault #671 reproducer and my non-empty-edata gradient checks still passed, so the utils.jl change (iterating over a Vector of keys instead of keys(x1)) is what fixes it. The if CRC.ignore_derivatives() do … end also wraps an isempty check, which is not differentiable anyway. If it is needed for the Julia 1.12 segfault from the issue (I could only test 1.13), please keep it but simplify; this passed the same checks for me:
    if isempty(data1) && isempty(data2)
        return CRC.ignore_derivatives(() -> DataStore(n1 + n2, Dict{Symbol, Any}()))
    end
    Could you confirm on 1.12 which of the two is actually needed?
  2. Please add a gradient test through add_edges with non-empty edata. The current test only covers empty metadata, but the utils.jl change is what makes the general case work.
  3. The sample_neighbors fix is independent of Differentiating across add_edges causes Zygote to segfault #671 (the old test was flaky because rand_graph(10, 40) can have zero-degree nodes). Fine to keep here, but worth a line in the PR description.

🧔‍♂️🤖 Assisted by AI

@DHAKED440

DHAKED440 commented Nov 7, 2026 •

Copy link
Copy Markdown
Contributor Author

Summary

  • Fix Zygote differentiation through add_edges when edge metadata is non-empty by iterating over a collected vector of metadata keys.
  • Simplify handling of empty DataStore metadata.
  • Handle zero-degree nodes in sample_neighbors(...; replace=true) without attempting to sample from an empty neighbor list.

Tests

  • Add a gradient regression test for add_edges with non-empty edge metadata.
  • Add coverage for sampling zero-degree nodes with replacement.

@CarloLucibello
CarloLucibello merged commit 0846e87 into JuliaGraphs:master Nov 11, 2026
12 checks passed
@CarloLucibello

Copy link
Copy Markdown
Member

@DHAKED440 I didn't realize it before merging, but this PR contained a lot of AI-generated junk files. Please pay attention to what you commit

CarloLucibello added a commit that referenced this pull request Nov 11, 2026
…735)

* Remove local setup files and notes committed in #729

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Fix changelog inconsistencies

Move #717 and #728 out of the already tagged releases, link the PRs that
introduced each fix, sort the link references and use one date separator.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Keep changelog edits out of PRs in AGENTS.md

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
@DHAKED440

Copy link
Copy Markdown
Contributor Author

Okay, I’ll review future PRs carefully and keep commits focused on the issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Differentiating across add_edges causes Zygote to segfault

2 participants