Zygote cannot take gradient of a sum when the sum has negative number raised to integer powers?

using Zygote
f(x) = sum((-1)^k*x for k in 0:5)
gradient(f, 0)

gives

ERROR: DomainError with -1.0:
log will only return a complex result if called with a complex argument. Try log(Complex(x)).

That’s not a zygote problem. You’ll get the same result just running the code.

1 Like

But it looks like it is a Zygote problem.

julia> f(x) = sum((-1)^k * x for k in 0: 10)
f (generic function with 1 method)

julia> f(0.1)
0.1

julia> f(0.2)
0.2

julia> using Zygote

julia> gradient(f, 0)
ERROR: DomainError with -1.0:
log will only return a complex result if called with a complex argument. Try log(Complex(x)).
Stacktrace:
 [1] throw_complex_domainerror(::Symbol, ::Float64) at .\math.jl:32
 [2] log(::Float64) at .\special\log.jl:285
 [3] log at .\special\log.jl:395 [inlined]
 [4] #610 at C:\Users\DeadScholar\.julia\packages\Zygote\fw4Oc\src\lib\number.jl:28 [inlined]
 [5] #1610#back at C:\Users\DeadScholar\.julia\packages\ZygoteRules\6nssF\src\adjoint.jl:49 [inlined]
 [6] #13 at .\none:0 [inlined]
 [7] (::typeof(∂(λ)))(::Int64) at C:\Users\DeadScholar\.julia\packages\Zygote\fw4Oc\src\compiler\interface2.jl:0
 [8] iterate at .\generator.jl:47 [inlined]
 [9] (::typeof(∂(iterate)))(::Tuple{Int64,Nothing}) at C:\Users\DeadScholar\.julia\packages\Zygote\fw4Oc\src\compiler\interface2.jl:0
 [10] mapfoldl_impl at .\reduce.jl:47 [inlined]
 [11] (::typeof(∂(mapfoldl_impl)))(::Int64) at C:\Users\DeadScholar\.julia\packages\Zygote\fw4Oc\src\compiler\interface2.jl:0
 [12] mapfoldl_impl at .\reduce.jl:61 [inlined]
 [13] (::typeof(∂(mapfoldl_impl)))(::Int64) at C:\Users\DeadScholar\.julia\packages\Zygote\fw4Oc\src\compiler\interface2.jl:0
 [14] mapfoldl at .\reduce.jl:72 [inlined]
 [15] (::typeof(∂(mapfoldl)))(::Int64) at C:\Users\DeadScholar\.julia\packages\Zygote\fw4Oc\src\compiler\interface2.jl:0
 [16] #mapreduce#194 at .\reduce.jl:200 [inlined]
 [17] (::typeof(∂(#mapreduce#194)))(::Int64) at C:\Users\DeadScholar\.julia\packages\Zygote\fw4Oc\src\compiler\interface2.jl:0
 [18] mapreduce at .\reduce.jl:200 [inlined]
 [19] (::typeof(∂(mapreduce)))(::Int64) at C:\Users\DeadScholar\.julia\packages\Zygote\fw4Oc\src\compiler\interface2.jl:0
 [20] sum at .\reduce.jl:395 [inlined]
 [21] f at .\REPL[24]:1 [inlined]
 [22] (::typeof(∂(f)))(::Int64) at C:\Users\DeadScholar\.julia\packages\Zygote\fw4Oc\src\compiler\interface2.jl:0
 [23] (::Zygote.var"#28#29"{typeof(∂(f))})(::Int64) at C:\Users\DeadScholar\.julia\packages\Zygote\fw4Oc\src\compiler\interface.jl:38
 [24] gradient(::Function, ::Int64, ::Vararg{Int64,N} where N) at C:\Users\DeadScholar\.julia\packages\Zygote\fw4Oc\src\compiler\interface.jl:47
 [25] top-level scope at REPL[28]: 

The problem is that Zygote is trying to differentiate (-1)^k with respect to k, but this function only has a complex derivative, so this fails because k is real. You can explicitly tell Zygote not to differentiate (-1)^k, since you don’t need this derivative anyways, with the function Zygote.dropgrad:

julia> using Zygote

julia> f(x) = sum(Zygote.dropgrad((-1)^k)*x for k in 0:5)
f (generic function with 1 method)

julia> gradient(f, 0)
(0,)
1 Like