ForwardDiff.jl
ForwardDiff.jl copied to clipboard
Perturbation Confusion II: The Tag Wars
@vtjnash was able to rewrite the classic perturbation confusion example into a form that thwarts ForwardDiff's tag generation:
julia> using ForwardDiff
julia> const D = ForwardDiff.derivative
derivative (generic function with 4 methods)
julia> struct Confuse
whoami::Bool
x
end
julia> function (c::Confuse)(xy)
if c.whoami
return xy * D(Confuse(false, xy), 1)
else
return c.x + xy
end
end
julia> D(Confuse(true, 0), 1) # this should be 1
2
Essentially, since the function type is constant whether or not the function recursively differentiates itself, ForwardDiff generates the same tag for the nested call that it generates for the outer call.
So it seems that sufficiently unique tags cannot be generated from local type information alone...