From 98cc02c9c261a284de4fa51de09c13779b77e44c Mon Sep 17 00:00:00 2001 From: Frames White Date: Thu, 8 Feb 2024 16:01:14 +0800 Subject: [PATCH 1/4] Define a bunch of zero_tangents that should just NoTangent --- src/tangent_types/abstract_zero.jl | 18 +++++++++++++++--- test/tangent_types/abstract_zero.jl | 5 +++++ 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/tangent_types/abstract_zero.jl b/src/tangent_types/abstract_zero.jl index f921db29d..ce1544cd5 100644 --- a/src/tangent_types/abstract_zero.jl +++ b/src/tangent_types/abstract_zero.jl @@ -112,8 +112,6 @@ function zero_tangent end zero_tangent(x::Number) = zero(x) -zero_tangent(::Type) = NoTangent() - function zero_tangent(x::MutableTangent{P}) where {P} zb = backing(zero_tangent(backing(x))) return MutableTangent{P}(zb) @@ -171,10 +169,24 @@ function zero_tangent(x::Array{P,N}) where {P,N} return y end +zero_tangent(::T) where {K,V,T<:AbstractDict{K,V}} = Tangent{T}(Dict{K, guess_zero_tangent_type(V)}()) + # Sad heauristic methods we need because of unassigned values guess_zero_tangent_type(::Type{T}) where {T<:Number} = T guess_zero_tangent_type(::Type{T}) where {T<:Integer} = typeof(float(zero(T))) function guess_zero_tangent_type(::Type{<:Array{T,N}}) where {T,N} return Array{guess_zero_tangent_type(T),N} end -guess_zero_tangent_type(T::Type) = Any \ No newline at end of file +guess_zero_tangent_type(T::Type) = Any + + +# Stuff that conceptually has its own identity regardless of structual implementation and doesn't have a tangent +zero_tangent(::Base.AbstractLogger) = NoTangent() + +# Prevent zero_tangent going wild on the internals +zero_tangent(::Type) = NoTangent() +zero_tangent(::Expr) = NoTangent() +zero_tangent(::Core.Compiler.AbstractInterpreter) = NoTangent() +zero_tangent(::Core.Compiler.InstructionStream) = NoTangent() +zero_tangent(::Core.CodeInfo) = NoTangent() +zero_tangent(::Core.MethodInstance) = NoTangent() \ No newline at end of file diff --git a/test/tangent_types/abstract_zero.jl b/test/tangent_types/abstract_zero.jl index 245d9a29d..8d9dbd1a4 100644 --- a/test/tangent_types/abstract_zero.jl +++ b/test/tangent_types/abstract_zero.jl @@ -183,6 +183,9 @@ end @test zero_tangent((1.0, 2.0)) == Tangent{Tuple{Float64,Float64}}(0.0, 0.0) + @test zero_tangent(Dict{Int, Float64}(1=>2.4)) == Tangent{Dict{Int,Float64}}(Dict{Int, Float64}()) + + # Higher order # StructuralTangents are valid tangents for themselves (just like Numbers) # and indeed we prefer that, otherwise higher order structural tangents are kinda @@ -200,6 +203,8 @@ end @test iszero(zero_tangent(:abc)) @test iszero(zero_tangent("abc")) @test iszero(zero_tangent(sin)) + + @test iszero(zero_tangent(:(1+1))) end @testset "undef elements Vector" begin From 4f9723c2d55cebef641bd034333622621f9b517d Mon Sep 17 00:00:00 2001 From: Frames White Date: Thu, 8 Feb 2024 16:06:59 +0800 Subject: [PATCH 2/4] formatting Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- src/tangent_types/abstract_zero.jl | 5 +++-- test/tangent_types/abstract_zero.jl | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/tangent_types/abstract_zero.jl b/src/tangent_types/abstract_zero.jl index ce1544cd5..b3b72d313 100644 --- a/src/tangent_types/abstract_zero.jl +++ b/src/tangent_types/abstract_zero.jl @@ -169,7 +169,9 @@ function zero_tangent(x::Array{P,N}) where {P,N} return y end -zero_tangent(::T) where {K,V,T<:AbstractDict{K,V}} = Tangent{T}(Dict{K, guess_zero_tangent_type(V)}()) +function zero_tangent(::T) where {K,V,T<:AbstractDict{K,V}} + return Tangent{T}(Dict{K,guess_zero_tangent_type(V)}()) +end # Sad heauristic methods we need because of unassigned values guess_zero_tangent_type(::Type{T}) where {T<:Number} = T @@ -179,7 +181,6 @@ function guess_zero_tangent_type(::Type{<:Array{T,N}}) where {T,N} end guess_zero_tangent_type(T::Type) = Any - # Stuff that conceptually has its own identity regardless of structual implementation and doesn't have a tangent zero_tangent(::Base.AbstractLogger) = NoTangent() diff --git a/test/tangent_types/abstract_zero.jl b/test/tangent_types/abstract_zero.jl index 8d9dbd1a4..86de66e70 100644 --- a/test/tangent_types/abstract_zero.jl +++ b/test/tangent_types/abstract_zero.jl @@ -183,8 +183,8 @@ end @test zero_tangent((1.0, 2.0)) == Tangent{Tuple{Float64,Float64}}(0.0, 0.0) - @test zero_tangent(Dict{Int, Float64}(1=>2.4)) == Tangent{Dict{Int,Float64}}(Dict{Int, Float64}()) - + @test zero_tangent(Dict{Int,Float64}(1 => 2.4)) == + Tangent{Dict{Int,Float64}}(Dict{Int,Float64}()) # Higher order # StructuralTangents are valid tangents for themselves (just like Numbers) @@ -204,7 +204,7 @@ end @test iszero(zero_tangent("abc")) @test iszero(zero_tangent(sin)) - @test iszero(zero_tangent(:(1+1))) + @test iszero(zero_tangent(:(1 + 1))) end @testset "undef elements Vector" begin From c1c9cfc2ca190a9d923ea377051a3a576df5fb38 Mon Sep 17 00:00:00 2001 From: Frames White Date: Thu, 8 Feb 2024 17:38:49 +0800 Subject: [PATCH 3/4] Given we require the AbstractDicts to be backed by DIcts we must make that constructable --- src/tangent_types/structural_tangent.jl | 2 +- test/tangent_types/abstract_zero.jl | 11 +++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/tangent_types/structural_tangent.jl b/src/tangent_types/structural_tangent.jl index 832d32a22..07a824a69 100644 --- a/src/tangent_types/structural_tangent.jl +++ b/src/tangent_types/structural_tangent.jl @@ -340,7 +340,7 @@ function Tangent{P}() where {P<:Tuple} return Tangent{P,typeof(backing)}(backing) end -function Tangent{P}(d::Dict) where {P<:Dict} +function Tangent{P}(d::Dict) where {P<:AbstractDict} return Tangent{P,typeof(d)}(d) end diff --git a/test/tangent_types/abstract_zero.jl b/test/tangent_types/abstract_zero.jl index 86de66e70..7ac1807ef 100644 --- a/test/tangent_types/abstract_zero.jl +++ b/test/tangent_types/abstract_zero.jl @@ -183,8 +183,15 @@ end @test zero_tangent((1.0, 2.0)) == Tangent{Tuple{Float64,Float64}}(0.0, 0.0) - @test zero_tangent(Dict{Int,Float64}(1 => 2.4)) == - Tangent{Dict{Int,Float64}}(Dict{Int,Float64}()) + @test ==( + zero_tangent(Dict{Int, Float64}(1=>2.4)), + Tangent{Dict{Int,Float64}}(Dict{Int, Float64}()) + ) + @test ==( + zero_tangent(Base.PersistentDict(1=>2.4)), + Tangent{Base.PersistentDict{Int,Float64}}(Dict{Int, Float64}()) + ) + # Higher order # StructuralTangents are valid tangents for themselves (just like Numbers) From a105ba930ed620bc547b5d14d933528537fec354 Mon Sep 17 00:00:00 2001 From: Frames White Date: Thu, 8 Feb 2024 18:35:32 +0800 Subject: [PATCH 4/4] only test behavour with PersistentDict if it is defined --- test/tangent_types/abstract_zero.jl | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/test/tangent_types/abstract_zero.jl b/test/tangent_types/abstract_zero.jl index 7ac1807ef..b7d2eba5c 100644 --- a/test/tangent_types/abstract_zero.jl +++ b/test/tangent_types/abstract_zero.jl @@ -184,13 +184,15 @@ end @test zero_tangent((1.0, 2.0)) == Tangent{Tuple{Float64,Float64}}(0.0, 0.0) @test ==( - zero_tangent(Dict{Int, Float64}(1=>2.4)), + zero_tangent(Dict{Int, Float64}(1 => 2.4)), Tangent{Dict{Int,Float64}}(Dict{Int, Float64}()) ) - @test ==( - zero_tangent(Base.PersistentDict(1=>2.4)), - Tangent{Base.PersistentDict{Int,Float64}}(Dict{Int, Float64}()) - ) + if isdefined(Base, :PersistentDict) + @test ==( + zero_tangent(Base.PersistentDict(1 => 2.4)), + Tangent{Base.PersistentDict{Int,Float64}}(Dict{Int, Float64}()) + ) + end # Higher order