# Mutable objects in Enzyme.jl

**URL:** <https://discourse.julialang.org/t/mutable-objects-in-enzyme-jl/99433>\
**Category:** Machine Learning\
**Tags:** autodiff, enzyme\
**Created:** [May 26, 2023, 8:55am UTC](https://discourse.julialang.org/t/mutable-objects-in-enzyme-jl/99433 "2023-05-26T08:55:03Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![Iris\_Allevi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/iris_allevi/32/50206_2.png) [@Iris\_Allevi](https://discourse.julialang.org/u/Iris_Allevi)\
**Post date:** [May 26, 2023, 8:55am UTC](https://discourse.julialang.org/t/mutable-objects-in-enzyme-jl/99433/1 "2023-05-26T08:55:03Z")

</div>

Hi everyone

I am new to automatic differentiation. I decided to use Enzyme since I need to handle mutating objects (even if I am _not_ differentiating with respect to these objects).

I try to write a minimal, self-consistent, example:

```julia
using Enzyme

mutable struct my_struct
    p1::Vector{Float64}
    p2::Float64
end

function edit_str!(str::my_struct, x, i)
    str.p2 = str.p2 + 2x^2
    return nothing
end

function foo(x, str)
    edit_str!(str, x, 1)
    return str.p2
end

str = my_struct([2.0, 3.0], 1.0)

foo(1.0, str), autodiff(Reverse, foo, Active, Active(1.0), str)

```

Here I try to differentiate the function `foo` in `x = 1.0`. Note that the function `edit_str!` inside `foo` changes the object `str`. Yet, I do not need to differentiate with respect to `str`.

I found out that, depending on the mutations on `str`, the code may or may not work. In the above example it gives the right result `4.0`, but if I change it slightly

```julia
function edit_str!(str::my_struct, x, i)
    str.p1 = str.p1 .+ 1.0
    str.p2 = str.p2 + 2x^2
    return nothing
end

```

it does not work anymore and it gives `0.0`. Note that `str.p1` is not needed anywhere. Perhaps even weirder, this works

```julia
function edit_str!(str::my_struct, x, i)
    str.p1 = 2.0 * str.p1
    str.p2 = str.p2 + 2x^2
    return nothing
end

```

I guess it depends on the kind of mutation on the `mutable struct`, but I would like to know if there is a robust way of dealing with this.

Thanks a lot.

---

<div class="post-metadata">

**Author:** ![jbrea](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jbrea/32/3879_2.png) [@jbrea](https://discourse.julialang.org/u/jbrea)\
**Post date:** [May 26, 2023, 10:29am UTC](https://discourse.julialang.org/t/mutable-objects-in-enzyme-jl/99433/2 "2023-05-26T10:29:37Z")

</div>

The following should work

```julia
autodiff(Reverse, foo, Active, Active(1.0), Duplicated(str, my_struct([0., 0.], 0.)))

```

See [caveats](https://enzymead.github.io/Enzyme.jl/stable/#Activity-of-temporary-storage).

---

<div class="post-metadata">

**Author:** ![Iris\_Allevi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/iris_allevi/32/50206_2.png) [@Iris\_Allevi](https://discourse.julialang.org/u/Iris_Allevi)\
**Post date:** [May 26, 2023, 11:34am UTC](https://discourse.julialang.org/t/mutable-objects-in-enzyme-jl/99433/3 "2023-05-26T11:34:26Z")

</div>

Tank you very much for your answer. This works indeed, but how can I generalise? How can I know how to initialise a more complex `mutable struct`?

---

<div class="post-metadata">

**Author:** ![jbrea](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jbrea/32/3879_2.png) [@jbrea](https://discourse.julialang.org/u/jbrea)\
**Post date:** [May 26, 2023, 11:52am UTC](https://discourse.julialang.org/t/mutable-objects-in-enzyme-jl/99433/4 "2023-05-26T11:52:52Z")

</div>

> [@Iris\_Allevi](#):
>
> How can I know how to initialise a more complex `mutable struct`?

In the second argument of `Duplicated`? I would initialize everything that is mutated to zero, but I don’t know if there is an official recommendation by `Enzyme` authors.

---

<div class="post-metadata">

**Author:** ![Iris\_Allevi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/iris_allevi/32/50206_2.png) [@Iris\_Allevi](https://discourse.julialang.org/u/Iris_Allevi)\
**Post date:** [May 28, 2023, 4:37pm UTC](https://discourse.julialang.org/t/mutable-objects-in-enzyme-jl/99433/5 "2023-05-28T16:37:20Z")

</div>

Thank you very much @jbrea

Here is the official answer from the developers:

> Yeah essentially if you store active (e.g. differentiable) data into constant memory (such as the struct here), there’s some additional complications.
> 
> Specifically, since it’s stored into constant data, Enzyme can assume that uses of it in that constant data won’t impact the derivative – since its loading/using a constant!
> 
> If it acts as a buffer/temporary storage of derivative data, you’ll need to mark it as duplicated (see here: [Home · Enzyme.jl](https://enzyme.mit.edu/index.fcgi/julia/stable/#Activity-of-temporary-storage)). The reason for this is because if you build up some arbitrary data structure, we also need to construct the shadow (aka derivative) data structure. Without the shadow data structure, we have no location as memory to use for the temporary storage of the derivative!
> 
> Your first case is actually why I was very careful and said that Enzyme _can_ assume that uses of it won’t impact the derivative, rather than Enzyme _will_ assume. The reason in that case, is that the computation was simple enough that an optimization realized it was returning the input variable x and decided to return that directly rather than actually loading from the constant struct. Therefore it is returning an active value, and has a meaningful derivative. If you want guarantee that all uses of a variable will not have their uses change the derivative, we have a construct for that too. In essence it’s equivalent to making a custom rule that behaves identity-like, but is marked inactive.

---

<div class="post-metadata">

**Author:** ![Iris\_Allevi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/iris_allevi/32/50206_2.png) [@Iris\_Allevi](https://discourse.julialang.org/u/Iris_Allevi)\
**Post date:** [May 28, 2023, 5:00pm UTC](https://discourse.julialang.org/t/mutable-objects-in-enzyme-jl/99433/6 "2023-05-28T17:00:03Z")

</div>

My question on how to initialise the shadow was related to the fact that if I change the operation on the structure, the initial value of 0.0 does not work anymore.

Example:

```julia
using Enzyme

mutable struct my_struct
    p1::Vector{Float64}
    p2::Float64
end

function edit_str!(str::my_struct, x, i)
    str.p1 = str.p1 .+ 1.0
    # Here I changed the operation to a product
    str.p2 = str.p2 * 2x^2
    return nothing
end

function foo(x, str)
    edit_str!(str, x, 1)
    return str.p2
end

str = my_struct([2.0, 3.0], 1.0)

str_copy = my_struct([0.0, 0.0], 0.0)

foo(1.0, str), autodiff(Reverse, foo, Active, Active(1.0), Duplicated(str, str_copy))

```

This gives `8.0` instead of `4.0`. Initialising `str_copy.p2` to other numbers only increases the result.

Do you know any workaround?

---

<div class="post-metadata">

**Author:** ![wsmoses](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wsmoses/32/26497_2.png) [@wsmoses](https://discourse.julialang.org/u/wsmoses)\
**Post date:** [May 28, 2023, 5:26pm UTC](https://discourse.julialang.org/t/mutable-objects-in-enzyme-jl/99433/7 "2023-05-28T17:26:11Z")

</div>

Your call to `foo(1.0, str)` changes the value of str. As a result it gives you a correct derivative for the new input values.

```julia

julia> using Enzyme

julia> mutable struct my_struct
           p1::Vector{Float64}
           p2::Float64
       end

julia> function edit_str!(str::my_struct, x, i)
           str.p1 = str.p1 .+ 1.0
           # Here I changed the operation to a product
           str.p2 = str.p2 * 2x^2
           return nothing
       end
edit_str! (generic function with 1 method)

julia> function foo(x, str)
           edit_str!(str, x, 1)
           return str.p2
       end
foo (generic function with 1 method)

julia> str = my_struct([2.0, 3.0], 1.0)
my_struct([2.0, 3.0], 1.0)

julia> str_copy = my_struct([0.0, 0.0], 0.0)
my_struct([0.0, 0.0], 0.0)

julia> foo(1.0, str)
2.0

julia> str
my_struct([3.0, 4.0], 2.0)

julia> str = my_struct([2.0, 3.0], 1.0)
my_struct([2.0, 3.0], 1.0)

julia> autodiff(Reverse, foo, Active, Active(1.0), Duplicated(str, str_copy))
((4.0, nothing),)

julia> str = my_struct([2.0, 3.0], 2.0)
my_struct([2.0, 3.0], 2.0)

julia> str_copy = my_struct([0.0, 0.0], 0.0)
my_struct([0.0, 0.0], 0.0)

julia> autodiff(Reverse, foo, Active, Active(1.0), Duplicated(str, str_copy))
((8.0, nothing),)

```

The expression here is equivalent to `str.p2 * 2x^2` Its derivative is thus equivalent to `4x^2 str.p2 dx + 2x^2 d(str.p2)`. You set shadow(str.p2) = 0, and using active means dx = 1. Thus you should get ``4x^2 str.p2`. If, however, you did this on an input where p2 = 2 (like after your foo), a derivative of 8 is indeed the correct result.

---

<div class="post-metadata">

**Author:** ![wsmoses](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wsmoses/32/26497_2.png) [@wsmoses](https://discourse.julialang.org/u/wsmoses)\
**Post date:** [May 28, 2023, 5:32pm UTC](https://discourse.julialang.org/t/mutable-objects-in-enzyme-jl/99433/8 "2023-05-28T17:32:51Z")

</div>

Not sure what you’re trying to do. But you may be interested in Enzymes split mode which gives you the result of the original code and a separate pullback function and tape you can use to evaluate the derivatives of the values as they were at the time you called the original code.
