julia> using Diffractor: gradient, frule_via_ad, unthunk, DiffractorRuleConfig
julia> gradient(x -> sum(abs2.(x)), [1,2,3.])
([2.0, 4.0, 6.0],)
julia> gradient(x -> sum(x .^ 2), [1,2,3.])
ERROR: MethodError: no method matching (::Diffractor.∂⃖recurse{1})(::typeof(Core._apply_iterate), ::typeof(iterate), ::typeof(Core.apply_type), ::Tuple{DataType, DataType}, ::Core.SimpleVector)
Closest candidates are:
(::Diffractor.∂⃖recurse)(::Any...) at /Users/me/.julia/dev/Diffractor/src/stage1/generated.jl:408
Stacktrace:
[1] macro expansion
@ ~/.julia/dev/Diffractor/src/stage1/generated.jl:0 [inlined]
[2] (::Diffractor.∂⃖recurse{1})(::typeof(Core._apply_iterate), ::typeof(iterate), ::typeof(Core.apply_type), ::Tuple{DataType, DataType}, ::Core.SimpleVector)
@ Diffractor ~/.julia/dev/Diffractor/src/stage1/generated.jl:417
[3] (::∂⃖{1})(::typeof(Core._apply_iterate), ::Function, ::Vararg{Any})
@ Diffractor ~/.julia/dev/Diffractor/src/stage1/generated.jl:215
[4] eltypes
@ ./broadcast.jl:714 [inlined]
[5] (::Diffractor.∂⃖recurse{1})(::typeof(Base.Broadcast.eltypes), ::Tuple{Base.RefValue{typeof(^)}, Vector{Float64}, Base.RefValue{Val{2}}})
@ Diffractor ~/.julia/dev/Diffractor/src/stage1/generated.jl:0
[6] (::∂⃖{1})(f::typeof(Base.Broadcast.eltypes), args::Tuple{Base.RefValue{typeof(^)}, Vector{Float64}, Base.RefValue{Val{2}}})
@ Diffractor ~/.julia/dev/Diffractor/src/stage1/generated.jl:215
[7] combine_eltypes
@ ./broadcast.jl:717 [inlined]
[8] (::Diffractor.∂⃖recurse{1})(::typeof(Base.Broadcast.combine_eltypes), ::typeof(Base.literal_pow), ::Tuple{Base.RefValue{typeof(^)}, Vector{Float64}, Base.RefValue{Val{2}}})
@ Diffractor ~/.julia/dev/Diffractor/src/stage1/generated.jl:0
[9] (::∂⃖{1})(::typeof(Base.Broadcast.combine_eltypes), ::Function, ::Vararg{Any})
@ Diffractor ~/.julia/dev/Diffractor/src/stage1/generated.jl:215
[10] copy
@ ./broadcast.jl:882 [inlined]
[11] (::∂⃖{1})(f::typeof(copy), args::Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1}, Tuple{Base.OneTo{Int64}}, typeof(Base.literal_pow), Tuple{Base.RefValue{typeof(^)}, Vector{Float64}, Base.RefValue{Val{2}}}})
@ Diffractor ~/.julia/dev/Diffractor/src/stage1/generated.jl:215
[12] materialize
@ ./broadcast.jl:860 [inlined]
[13] (::∂⃖{1})(f::typeof(Base.Broadcast.materialize), args::Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1}, Nothing, typeof(Base.literal_pow), Tuple{Base.RefValue{typeof(^)}, Vector{Float64}, Base.RefValue{Val{2}}}})
@ Diffractor ~/.julia/dev/Diffractor/src/stage1/generated.jl:215
[14] #126
@ ./REPL[100]:1 [inlined]
[15] (::Diffractor.∂⃖recurse{1})(::var"#126#127", ::Vector{Float64})
@ Diffractor ~/.julia/dev/Diffractor/src/stage1/generated.jl:0
[16] (::∂⃖{1})(f::var"#126#127", args::Vector{Float64})
@ Diffractor ~/.julia/dev/Diffractor/src/stage1/generated.jl:215
[17] ∂⃖(::Function, ::Vararg{Any})
@ Diffractor ~/.julia/dev/Diffractor/src/interface.jl:25
[18] (::Diffractor.∇{var"#126#127"})(args::Vector{Float64})
@ Diffractor ~/.julia/dev/Diffractor/src/interface.jl:121
[19] Diffractor.∇(::Function, ::Vector{Float64})
@ Diffractor ~/.julia/dev/Diffractor/src/interface.jl:128
[20] top-level scope
@ REPL[100]:1
julia> gradient(x -> sum(x .* x'), [1,2,3.])
([12.0, 12.0, 12.0],)
julia> gradient(x -> sum(x ./ x'), [1,2,3.])
ERROR: Rewrite reached intrinsic function bitcast. Missing rule?
Stacktrace:
[1] error(s::String)
@ Base ./error.jl:33
[2] (::∂⃖{1})(::Core.IntrinsicFunction, ::Type, ::Vararg{Any})
@ Diffractor ~/.julia/dev/Diffractor/src/stage1/generated.jl:205
[3] UInt64
@ ./boot.jl:768 [inlined]
[4] (::Diffractor.∂⃖recurse{1})(::Type{UInt64}, ::Ptr{Float64})
@ Diffractor ~/.julia/dev/Diffractor/src/stage1/generated.jl:0
[5] (::∂⃖{1})(f::Type{UInt64}, args::Ptr{Float64})
@ Diffractor ~/.julia/dev/Diffractor/src/stage1/generated.jl:215
[6] dataids
@ ./abstractarray.jl:1457 [inlined]
[7] (::Diffractor.∂⃖recurse{1})(::typeof(Base.dataids), ::Matrix{Float64})
@ Diffractor ~/.julia/dev/Diffractor/src/stage1/generated.jl:0
[8] (::∂⃖{1})(f::typeof(Base.dataids), args::Matrix{Float64})
@ Diffractor ~/.julia/dev/Diffractor/src/stage1/generated.jl:215
[9] mightalias
@ ./abstractarray.jl:1433 [inlined]
[10] ∂⃖
@ ~/.julia/dev/Diffractor/src/stage1/generated.jl:215 [inlined]
[11] unalias
@ ./abstractarray.jl:1398 [inlined]
[12] ∂⃖
@ ~/.julia/dev/Diffractor/src/stage1/generated.jl:215 [inlined]
[13] broadcast_unalias
@ ./broadcast.jl:934 [inlined]
[14] ∂⃖
@ ~/.julia/dev/Diffractor/src/stage1/generated.jl:215 [inlined]
[15] preprocess
@ ./broadcast.jl:941 [inlined]
[16] ∂⃖
@ ~/.julia/dev/Diffractor/src/stage1/generated.jl:215 [inlined]
[17] preprocess_args
@ ./broadcast.jl:943 [inlined]
[18] ∂⃖
@ ~/.julia/dev/Diffractor/src/stage1/generated.jl:215 [inlined]
[19] preprocess
@ ./broadcast.jl:940 [inlined]
[20] ∂⃖
@ ~/.julia/dev/Diffractor/src/stage1/generated.jl:215 [inlined]
[21] copyto!
@ ./broadcast.jl:957 [inlined]
[22] (::Diffractor.∂⃖recurse{1})(::typeof(copyto!), ::Matrix{Float64}, ::Base.Broadcast.Broadcasted{Nothing, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}, typeof(/), Tuple{Vector{Float64}, Adjoint{Float64, Vector{Float64}}}})
@ Diffractor ~/.julia/dev/Diffractor/src/stage1/generated.jl:0
[23] (::∂⃖{1})(::typeof(copyto!), ::Matrix{Float64}, ::Vararg{Any})
@ Diffractor ~/.julia/dev/Diffractor/src/stage1/generated.jl:215
[24] copyto!
@ ./broadcast.jl:913 [inlined]
[25] ∂⃖
@ ~/.julia/dev/Diffractor/src/stage1/generated.jl:215 [inlined]
[26] copy
@ ./broadcast.jl:885 [inlined]
[27] ∂⃖
@ ~/.julia/dev/Diffractor/src/stage1/generated.jl:215 [inlined]
[28] materialize
@ ./broadcast.jl:860 [inlined]
[29] (::∂⃖{1})(f::typeof(Base.Broadcast.materialize), args::Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{2}, Nothing, typeof(/), Tuple{Vector{Float64}, Adjoint{Float64, Vector{Float64}}}})
@ Diffractor ~/.julia/dev/Diffractor/src/stage1/generated.jl:215
[30] #130
@ ./REPL[102]:1 [inlined]
[31] ∂⃖
@ ~/.julia/dev/Diffractor/src/stage1/generated.jl:215 [inlined]
[32] ∂⃖
@ ~/.julia/dev/Diffractor/src/interface.jl:25 [inlined]
[33] (::Diffractor.∇{var"#130#131"})(args::Vector{Float64})
@ Diffractor ~/.julia/dev/Diffractor/src/interface.jl:121
[34] Diffractor.∇(::Function, ::Vector{Float64})
@ Diffractor ~/.julia/dev/Diffractor/src/interface.jl:128
[35] top-level scope
@ REPL[102]:1
julia> using LinearAlgebra
julia> function fjac(f, x)
delta = Matrix(I, length(x), length(x))
slice(k) = vec(frule_via_ad(DiffractorRuleConfig(), (0, reshape(delta[:,k], axes(x))), f, x)[2])
reduce(hcat, [slice(k) for k in LinearIndices(x)])
end
fjac (generic function with 1 method)
julia> fjac(x -> x .^ 2, [1,2,3.])
3×3 Matrix{Float64}:
2.0 0.0 0.0
0.0 4.0 0.0
0.0 0.0 6.0
julia> fjac(x -> x ./ x', [1,2,3.])
ERROR: MethodError: no method matching unbundle(::Diffractor.CompositeBundle{1, Adjoint{Float64, Vector{Float64}}, Tuple{Diffractor.TangentBundle{1, Vector{Float64}, Tuple{Vector{Bool}}}}})
Closest candidates are:
unbundle(::Diffractor.TangentBundle{Order, A}) where {Order, Dim, T, A<:AbstractArray{T, Dim}} at /Users/me/.julia/dev/Diffractor/src/tangent.jl:229
unbundle(::Diffractor.TaylorBundle{Order, A}) where {Order, Dim, T, A<:AbstractArray{T, Dim}} at /Users/me/.julia/dev/Diffractor/src/tangent.jl:247
unbundle(::Diffractor.UniformBundle{N, A, ZeroTangent}) where {N, T, Dim, A<:AbstractArray{T, Dim}} at /Users/me/.julia/dev/Diffractor/src/tangent.jl:272
Stacktrace:
[1] (::Diffractor.var"#236#237"{1, ∂☆{1}, Diffractor.CompositeBundle{1, Tuple{Vector{Float64}, Adjoint{Float64, Vector{Float64}}}, Tuple{Diffractor.TangentBundle{1, Vector{Float64}, Tuple{Vector{Bool}}}, Diffractor.CompositeBundle{1, Adjoint{Float64, Vector{Float64}}, Tuple{Diffractor.TangentBundle{1, Vector{Float64}, Tuple{Vector{Bool}}}}}}}})(i::Int64)
@ Diffractor ~/.julia/dev/Diffractor/src/stage1/broadcast.jl:23
[2] ntuple(f::Diffractor.var"#236#237"{1, ∂☆{1}, Diffractor.CompositeBundle{1, Tuple{Vector{Float64}, Adjoint{Float64, Vector{Float64}}}, Tuple{Diffractor.TangentBundle{1, Vector{Float64}, Tuple{Vector{Bool}}}, Diffractor.CompositeBundle{1, Adjoint{Float64, Vector{Float64}}, Tuple{Diffractor.TangentBundle{1, Vector{Float64}, Tuple{Vector{Bool}}}}}}}}, n::Int64)
@ Base ./ntuple.jl:19
[3] (::∂☆{1})(zc::Diffractor.UniformBundle{1, typeof(copy), ZeroTangent}, bc::Diffractor.CompositeBundle{1, Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{2}, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}, typeof(/), Tuple{Vector{Float64}, Adjoint{Float64, Vector{Float64}}}}, Tuple{Diffractor.UniformBundle{1, typeof(/), ZeroTangent}, Diffractor.CompositeBundle{1, Tuple{Vector{Float64}, Adjoint{Float64, Vector{Float64}}}, Tuple{Diffractor.TangentBundle{1, Vector{Float64}, Tuple{Vector{Bool}}}, Diffractor.CompositeBundle{1, Adjoint{Float64, Vector{Float64}}, Tuple{Diffractor.TangentBundle{1, Vector{Float64}, Tuple{Vector{Bool}}}}}}}, Diffractor.CompositeBundle{1, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}, Tuple{Diffractor.TangentBundle{1, Base.OneTo{Int64}, Tuple{ChainRulesCore.NoTangent}}, Diffractor.TangentBundle{1, Base.OneTo{Int64}, Tuple{ChainRulesCore.NoTangent}}}}}})
@ Diffractor ~/.julia/dev/Diffractor/src/stage1/broadcast.jl:16
[4] ∂☆recurse
@ ./broadcast.jl:860 [inlined]
[5] (::Diffractor.∂☆recurse{1})(::Diffractor.UniformBundle{1, typeof(Base.Broadcast.materialize), ZeroTangent}, ::Diffractor.CompositeBundle{1, Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{2}, Nothing, typeof(/), Tuple{Vector{Float64}, Adjoint{Float64, Vector{Float64}}}}, Tuple{Diffractor.UniformBundle{1, typeof(/), ZeroTangent}, Diffractor.CompositeBundle{1, Tuple{Vector{Float64}, Adjoint{Float64, Vector{Float64}}}, Tuple{Diffractor.TangentBundle{1, Vector{Float64}, Tuple{Vector{Bool}}}, Diffractor.CompositeBundle{1, Adjoint{Float64, Vector{Float64}}, Tuple{Diffractor.TangentBundle{1, Vector{Float64}, Tuple{Vector{Bool}}}}}}}, Diffractor.UniformBundle{1, Nothing, ZeroTangent}}})
@ Diffractor ~/.julia/dev/Diffractor/src/stage1/recurse_fwd.jl:0
[6] (::Diffractor.∂☆internal{1})(::Diffractor.UniformBundle{1, typeof(Base.Broadcast.materialize), ZeroTangent}, ::Vararg{Diffractor.AbstractTangentBundle{1}})
@ Diffractor ~/.julia/dev/Diffractor/src/stage1/forward.jl:115
[7] (::∂☆{1})(::Diffractor.UniformBundle{1, typeof(Base.Broadcast.materialize), ZeroTangent}, ::Vararg{Diffractor.AbstractTangentBundle{1}})
@ Diffractor ~/.julia/dev/Diffractor/src/stage1/forward.jl:140
[8] ∂☆recurse
@ ./REPL[104]:1 [inlined]
[9] (::Diffractor.∂☆recurse{1})(::Diffractor.TangentBundle{1, var"#134#135", Tuple{Int64}}, ::Diffractor.TangentBundle{1, Vector{Float64}, Tuple{Vector{Bool}}})
@ Diffractor ~/.julia/dev/Diffractor/src/stage1/recurse_fwd.jl:0
[10] (::Diffractor.∂☆internal{1})(::Diffractor.TangentBundle{1, var"#134#135", Tuple{Int64}}, ::Vararg{Diffractor.AbstractTangentBundle{1}})
@ Diffractor ~/.julia/dev/Diffractor/src/stage1/forward.jl:115
[11] frule_via_ad(::DiffractorRuleConfig, ::Tuple{Int64, Vector{Bool}}, ::Function, ::Vararg{Any})
@ Diffractor ~/.julia/dev/Diffractor/src/stage1/forward.jl:123
[12] (::var"#slice#122"{var"#134#135", Vector{Float64}, Matrix{Bool}})(k::Int64)
@ Main ./REPL[98]:3
[13] #121
@ ./none:0 [inlined]
[14] iterate
@ ./generator.jl:47 [inlined]
[15] collect(itr::Base.Generator{LinearIndices{1, Tuple{Base.OneTo{Int64}}}, var"#121#123"{var"#slice#122"{var"#134#135", Vector{Float64}, Matrix{Bool}}}})
@ Base ./array.jl:774
[16] fjac(f::Function, x::Vector{Float64})
@ Main ./REPL[98]:4
[17] top-level scope
@ REPL[104]:1
julia> versioninfo()
Julia Version 1.8.0-DEV.502
Commit c4f0d8b2f6 (2021-09-10 16:28 UTC)
Platform Info:
OS: macOS (arm64-apple-darwin20.6.0)
CPU: Apple M1
WORD_SIZE: 64
LIBM: libopenlibm
LLVM: libLLVM-12.0.1 (ORCJIT, cyclone)
Environment:
JULIA_NUM_THREADS = 4