# Custom rule for an implicit function in Enzyme

**URL:** https://discourse.julialang.org/t/custom-rule-for-an-implicit-function-in-enzyme/136259
**Category:** Numerics
**Tags:** ad, enzyme
**Created:** [March 18, 2026, 4:16pm UTC](https://discourse.julialang.org/t/custom-rule-for-an-implicit-function-in-enzyme/136259 "2026-03-18T16:16:54Z")
**Posts on this page:** 4
**Page:** 1

<div class="post-metadata">

### Author: ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)
#### Post date: [March 18, 2026, 4:16pm UTC](https://discourse.julialang.org/t/custom-rule-for-an-implicit-function-in-enzyme/136259/1 "2026-03-18T16:16:55Z")

</div>

Consider an implicit function y = f(x) defined via

g(x, y)

where x, y \in \mathbb{R}^n. The user supplies `f!(y, x)` and `g!(r, x, y)` as callables, which are wrapped in a

```julia
struct SquareImplicitFunction{F,G}
    f!::F
    g!::G
end

function (ℐ::SquareImplicitFunction)(y, x)
    ℐ.f!(y, x)
    nothing
end

```

The user should be able to AD through `ℐ(y, x)` calls in Enzyme, using forward and reverse mode.

I have **coded up an MWE package [here](https://github.com/tpapp/EnzymeImplicitAD.jl/blob/master/src/EnzymeImplicitAD.jl)**, which kind of works (simple tests run), but I have some open questions about it. Note that the questions all pertain to the code, which I am not copy-pasting here, as it is \>100 LOC (with plenty of docstrings), **so if you want to help please look at it**.

**Q1** I figured out AD while making the callable `Const(g!)`, but I am wondering if there is a way to have AD work if it was somehow parameterized. Eg for the trivial example

```julia
struct G!{T<:Real}
    p::T
end
(g!::G!)(x, y) = x .+ g!.p .- y
make_f!(g!::G!) = y .= g!.p .+ x

```

it would be nice to be able to perturb `p` and have AD work. But, frankly, I am conceptually lost on how to do this.

**Q2** I wonder if there is a way to cache the Jacobian (for the same `x` and `y`), in forward and reverse mode. Should I just save it on the tape in reverse mode, would that be reused for various cotangents? What about forward mode?

**Q3** With the function signatures above, I am not sure what combinations of `Const` and `Duplicated` I should plan for. Can it ever happen that, of `x` and `y`, one is `Const` and the other is `Duplicated`?

Any other comments are welcome too. As it may be apparent from the code I have a limited understanding of AD and Enzyme.jl. And yes, I am aware of [ImplicitDifferentiation.jl](https://github.com/JuliaDecisionFocusedLearning/ImplicitDifferentiation.jl), and plan to contribute to it, but I want to understand things first in a simplified context.

---

<div class="post-metadata">

### Author: ![vchuravy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vchuravy/32/8_2.png) [@vchuravy](https://discourse.julialang.org/u/vchuravy)
#### Post date: [March 25, 2026, 9:14am UTC](https://discourse.julialang.org/t/custom-rule-for-an-implicit-function-in-enzyme/136259/2 "2026-03-25T09:14:03Z")

</div>

> Should I just save it on the tape in reverse mode

Yeah you can do that, but it’s always the question if it is worth to calculate the entire Jacobian or if JvP are sufficient. You can’t cache in forward mode (except for batch evaluation)

> But, frankly, I am conceptually lost on how to do this.

On the Enzyme, level this just means that you need to pass `Duplicated(g)`, this providing a storage location for the tangent/shadow value.

> Can it ever happen that, of x and y, one is Const and the other is Duplicated?

I think you could have `Const(y)` and `Duplicated(x)` (perhaps even vice-versa) that just means that y has been marked inactive and x is active.

At some point I did try to add rules to ImplicitDifferentiation [Support Enzyme through EnzymeRules by vchuravy · Pull Request #186 · JuliaDecisionFocusedLearning/ImplicitDifferentiation.jl · GitHub](https://github.com/JuliaDecisionFocusedLearning/ImplicitDifferentiation.jl/pull/186/changes) but I forgotten how far I got.

---

<div class="post-metadata">

### Author: ![gdalle](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gdalle/32/27854_2.png) [@gdalle](https://discourse.julialang.org/u/gdalle)
#### Post date: [March 25, 2026, 11:47am UTC](https://discourse.julialang.org/t/custom-rule-for-an-implicit-function-in-enzyme/136259/3 "2026-03-25T11:47:53Z")

</div>

I’d love for you or someone else to pick up that PR! The most urgent thing would be to add tests, and then we can see what works and what doesn’t 🙂

---

<div class="post-metadata">

### Author: ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)
#### Post date: [March 25, 2026, 12:01pm UTC](https://discourse.julialang.org/t/custom-rule-for-an-implicit-function-in-enzyme/136259/4 "2026-03-25T12:01:04Z")

</div>

I would be happy to do it but I need to learn a lot about AD in general and Enzyme specifically before. I am doing that in my own repo for now.
