JuliaDiff / ForwardDiff.jl

Forward Mode Automatic Differentiation for Julia
Other
892 stars 145 forks source link

Symbolics.jl compatibility #674

Open polhager opened 12 months ago

polhager commented 12 months ago

Arithmetic operations between Num and Dual based on Num is not clearly defined. The basic usecase is this:

using ForwardDiff, Symbolics.jl

@variables a, x
f = x -> a*x
Differential(x)(f(x)) |> expand_derivatives # This works, and gives what I would expect from ForwardDiff.derivative
ForwardDiff.derivative(f, x) # This returns an error

The error given by the last line is this

ERROR: MethodError: *(::Num, ::ForwardDiff.Dual{ForwardDiff.Tag{var"#5#6", Num}, Num, 1}) is ambiguous.

Candidates:
  *(x::Real, y::ForwardDiff.Dual{Ty}) where Ty
    @ ForwardDiff ~/.julia/packages/ForwardDiff/PcZ48/src/dual.jl:145
  *(a::Num, b::Real)
    @ Symbolics ~/.julia/packages/SymbolicUtils/ssQsQ/src/methods.jl:73
  *(a::Num, b::Number)
    @ Symbolics ~/.julia/packages/SymbolicUtils/ssQsQ/src/methods.jl:75

Possible fix, define
  *(::Num, ::ForwardDiff.Dual{Ty}) where Ty

Stacktrace:
 [1] (::var"#5#6")(x::ForwardDiff.Dual{ForwardDiff.Tag{var"#5#6", Num}, Num, 1})
   @ Main ./REPL[21]:1
 [2] derivative(f::var"#5#6", x::Num)
   @ ForwardDiff ~/.julia/packages/ForwardDiff/PcZ48/src/derivative.jl:14
 [3] top-level scope
   @ REPL[22]:1

This seems to be the case for (at least) all basic arithmetic operations. Not sure if this should be fixed here or in Symbolics.jl.

KristofferC commented 12 months ago

ForwardDiff has a custom number type D and claims that d::D + x should be evaluated as d + D(x). Symbolics has a custom number type N and claims that n::N + x should be evaluated as n + N(x).

The question now is, what should d + n evaluate to? Without cooperation between ForwardDiff and Symbolics, there is no way to tell. Could maybe be added as an extension?