Skip to content

[WIP] D* AD algorithm - #1888

Draft
LordOfFrogs wants to merge 44 commits into
JuliaSymbolics:masterfrom
LordOfFrogs:ToriDell/IRStructure-AD
Draft

[WIP] D* AD algorithm#1888
LordOfFrogs wants to merge 44 commits into
JuliaSymbolics:masterfrom
LordOfFrogs:ToriDell/IRStructure-AD

Conversation

@LordOfFrogs

@LordOfFrogs LordOfFrogs commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Implements the D* AD algorithm based on this paper. Similar to FastDifferentiation.jl. Still a work-in-progress.

To be fixed/implemented:

  • New DerivativeGraph representation of expressions
  • Finding subgraphs
  • Factoring subgraphs
  • Evaluating derivatives based on fully factored graph
  • Rn->Rn final evaluation (mostly there, just the final step needs implementing)
  • Support for variables part of symbolic arrays
  • Support for ifelse
  • Proper support for nested differentials
  • Support for matrix operations (dot, norm, etc.)
  • All tests pass (yes, need to make more though)
  • Register multiple Jacobian entries with @register_derivative

Based on some initial benchmarking, this alorithm appears to be at least 2x faster than the existing one for relatively small expressions. In theory, this should improve even more for larger expressions and Rn-Rn functions. (after implementing fixes for large graphs, performance needs more work)

@LordOfFrogs
LordOfFrogs marked this pull request as draft June 8, 2026 20:43
@codecov-commenter

codecov-commenter commented Jun 8, 2026

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

❌ Patch coverage is 0% with 510 lines in your changes missing coverage. Please review.
✅ Project coverage is 17.78%. Comparing base (c736678) to head (42d4f05).
⚠️ Report is 285 commits behind head on master.

Files with missing lines Patch % Lines
src/derivativegraph.jl 0.00% 510 Missing ⚠️
❗ Your organization needs to install the Codecov GitHub app to enable full functionality.

❗ There is a different number of reports uploaded between BASE (c736678) and HEAD (42d4f05). Click for more details.

HEAD has 2 uploads less than BASE
Flag BASE (c736678) HEAD (42d4f05)
6 4
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1888      +/-   ##
==========================================
- Coverage   26.12%   17.78%   -8.35%     
==========================================
  Files          56       62       +6     
  Lines        5356     6496    +1140     
==========================================
- Hits         1399     1155     -244     
- Misses       3957     5341    +1384     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@LordOfFrogs LordOfFrogs changed the title [WIP] New AD algorithm using IRStructure [WIP] D* AD algorithm Jul 23, 2026
@LordOfFrogs
LordOfFrogs deleted the ToriDell/IRStructure-AD branch July 23, 2026 14:25
@LordOfFrogs
LordOfFrogs restored the ToriDell/IRStructure-AD branch July 23, 2026 14:26
@LordOfFrogs LordOfFrogs reopened this Jul 23, 2026

@AayushSabharwal AayushSabharwal left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think the progress looks amazing! My comments are mainly around possible performance pitfalls. You did mention on slack that you're aware of some such cases but I thought it prudent to make sure we're on the same page about some of these pieces.

Comment thread src/derivativegraph.jl Outdated
Comment thread src/derivativegraph.jl
Comment thread src/derivativegraph.jl Outdated
Comment thread src/derivativegraph.jl
Comment thread src/derivativegraph.jl Outdated
Comment thread src/derivativegraph.jl Outdated
end

# evaluate the product of single linear path of edges (this represents applying the chain rule)
function evaluate_path(dg::DerivativeGraph{T}, edge::Edge{T}, goal::T) where T

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can we end up calling evaluate_path with the same edge and goal twice? Is this something that we can then cache or otherwise optimize?

@LordOfFrogs LordOfFrogs Aug 3, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

There is actually a section of the D* paper that covers a solution to this problem of common subproducts, which I am currently working on implementing. The current evaluate_path function was just to verify that R1->R1 derivatives were working correctly.

Comment thread src/derivativegraph.jl Outdated
vars::Vector{SymbolicT} # variable index -> variable symbolic expression
varset::Set{SymbolicT} # for fast checking if an expression is a variable
var_idx_to_postorder::Vector{T}
var_idx_to_postorder::IdDict{Int,T}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'm curious - why a map over an array? And why IdDict?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I switched from an array to a map because in cases where a root has no children or a variable has no parents, it makes more sense to omit it from the postorder numbering because of how the code is structured, and using a map proved the easiest way to do that (I tried using nothings in the array, but that generated a bunch of new problems, and trying to give them postorder numbers also led to problems).

IdDict was just me following the pattern for the existing maps, but I realize now that the only reason I had them as IdDict's in the first place was because I was basing the struct off of FastDifferentiation.jl, which uses a Node struct instead of integers. They have been changed to Dict's now, which should be more performant.

Comment thread src/derivativegraph.jl Outdated
Comment thread src/derivativegraph.jl
Comment thread src/derivativegraph.jl Outdated
IdDict -> Dict, removing erroneous collect calls, only -> first
Subgraphs now only focus on a specific set of roots/vars (its dominance) so subgraphs dont have to have dom/pdom relationships for every root+var; 
Includes many other more minor fixes with it that cropped up
subgraph edge exploration termination cases reordered
add_edge! protection from duplicate edges
corrected is_dominator/is_postdominator edge filtering
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.

3 participants