# Zygote silently fails on CircularArrays.jl

**URL:** <https://discourse.julialang.org/t/zygote-silently-fails-on-circulararrays-jl/87321>\
**Category:** Numerics\
**Tags:** zygote, autodiff\
**Created:** [September 15, 2022, 3:44pm UTC](https://discourse.julialang.org/t/zygote-silently-fails-on-circulararrays-jl/87321 "2022-09-15T15:44:56Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![trakjohnson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/trakjohnson/32/42717_2.png) [@trakjohnson](https://discourse.julialang.org/u/trakjohnson)\
**Post date:** [September 15, 2022, 3:44pm UTC](https://discourse.julialang.org/t/zygote-silently-fails-on-circulararrays-jl/87321/1 "2022-09-15T15:44:56Z")

</div>

It seems that Zygote silently fails when differentiating a function that takes and outputs [CircularArrays](https://github.com/Vexatos/CircularArrays.jl/blob/master/src/CircularArrays.jl), using a `Zygote.Buffer` to allow mutation. Here’s a comparison with ForwardDiff:

```julia
using Zygote, ForwardDiff, CircularArrays

a = CircularArray([1.0])
function f(x)
    new = Zygote.Buffer(x)
    new[1] = x[1] + x[2]
    return copy(new)
end
display(Zygote.jacobian(f, a)[1])
# 1×1 CircularArray(::Matrix{Float64}):
# 1.0
display(ForwardDiff.jacobian(f, a))
# 1×1 CircularArray(::Matrix{Float64}):
# 2.0

```

```julia
b = [1.0]
function g(x)
    new = Zygote.Buffer(x)
    new[1] = x[1] + x[1]
    return copy(new)
end
display(Zygote.jacobian(g, b)[1])
# 1×1 Matrix{Float64}:
# 2.0
display(ForwardDiff.jacobian(g, b))
# 1×1 Matrix{Float64}:
# 2.0

```

Is this a known limitation of Zygote ? Given the simplicity of the implementation of CircularArrays, I would’ve expected it to work.

Thank you!

---

<div class="post-metadata">

**Author:** ![terasakisatoshi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/terasakisatoshi/32/9187_2.png) [@terasakisatoshi](https://discourse.julialang.org/u/terasakisatoshi)\
**Post date:** [January 19, 2024, 10:45am UTC](https://discourse.julialang.org/t/zygote-silently-fails-on-circulararrays-jl/87321/2 "2024-01-19T10:45:19Z")

</div>

~~I’m not sure why, but this also happens for OffsetArrays~~  
Sorry, I misunderstand my outputs…

```julia
(@v1.10) pkg> st Zygote ForwardDiff OffsetArrays
Status `~/.julia/environments/v1.10/Project.toml`
  [f6369f11] ForwardDiff v0.10.36
  [6fe1bfb0] OffsetArrays v1.13.0
  [e88e6eb3] Zygote v0.6.68

```

```julia
               _
   _ _ _(_)_ | Documentation: https://docs.julialang.org
  (_) | (_) (_) |
   _ _ _| |_ __ _ | Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _` | |
  | | |_| | | | (_| | | Version 1.10.0 (2023-12-25)
 _/ |\ __'_|_|_|\__'_| | Official https://julialang.org/ release
|__/ |

julia> using Zygote, ForwardDiff, OffsetArrays

julia> function f(x)
           new = Zygote.Buffer(x)
           new[1] = x[begin] + x[begin]
           return copy(new)
       end
f (generic function with 1 method)

julia> function f2(x)
           new = Zygote.Buffer(x)
           return [x[begin] + x[begin]]
       end
f2 (generic function with 1 method)

julia> oa1 = OffsetArray([1], 1:1)
1-element OffsetArray(::Vector{Int64}, 1:1) with eltype Int64 with indices 1:1:
 1

julia> display(Zygote.jacobian(f, oa1)[begin])
1×1 Matrix{Int64}:
 2

julia> display(ForwardDiff.jacobian(f, oa1))
1×1 Matrix{Int64}:
 2

julia> display(Zygote.jacobian(f2, oa1)[begin])
1×1 Matrix{Int64}:
 2

julia> display(ForwardDiff.jacobian(f2, oa1))
1×1 Matrix{Int64}:
 2

```

---

<div class="post-metadata">

**Author:** ![terasakisatoshi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/terasakisatoshi/32/9187_2.png) [@terasakisatoshi](https://discourse.julialang.org/u/terasakisatoshi)\
**Post date:** [January 19, 2024, 12:54pm UTC](https://discourse.julialang.org/t/zygote-silently-fails-on-circulararrays-jl/87321/3 "2024-01-19T12:54:15Z")

</div>

@trakjohnson

Adding a method of ∇getindex with `CircularArray` type should solve your issue.

> <https://github.com/JuliaDiff/ChainRules.jl/blob/ae37562ea1f16816a0d8fff24e0aca6cd594a40f/src/rulesets/Base/indexing.jl#L73-L92>

```julia-repl
julia> import ChainRules

julia> using CircularArrays, Zygote, ForwardDiff

julia> function ChainRules.∇getindex(x::CircularArray, dy, i::Int)
               m = eachindex(IndexLinear(), x.data)
               ChainRules.∇getindex(x.data, dy, mod(i, m))
       end

julia> a = CircularArray([1.0])
1-element CircularVector(::Vector{Float64}):
 1.0

julia> function f(x)
           new = Zygote.Buffer(x)
           new[1] = x[1] + x[2]
           return copy(new)
       end
f (generic function with 1 method)

julia> display(Zygote.jacobian(f, a)[1])
1×1 CircularArray(::Matrix{Float64}):
 2.0

julia> display(ForwardDiff.jacobian(f, a))
1×1 CircularArray(::Matrix{Float64}):
 2.0

```
