Symbolics.jl
Symbolics.jl copied to clipboard
Unable to differentiate sum of broadcast
let
@variables q[1:5]
Symbolics.gradient(
sum(q .* log.(q)), collect(q)
)
end
This outputs a vector of zeros: [0, 0, 0, 0, 0]
, but the correct gradient consists of elements like 1 + log(q[k])
:
import sympy as sp
q = sp.symbols("q1:5", real=True)
the_sum = sum(
q_ * sp.log(q_) for q_ in q
)
sp.Matrix([
[the_sum.diff(q_) for q_ in q]
]).T
Output:
┆Issue is synchronized with this Trello card by Unito
Seems that the symbolic array is not working properly when computing gradients, I have a similar issue here.
@variables t[1:3]
println(Symbolics.derivative(cos.(t)[1], t[1]));
println(Symbolics.derivative(Symbolics.scalarize(cos.(t)[1]), t[1]));
println(Symbolics.jacobian(cos.(t), t));
Output:
0
-sin(t[1])
Num[-sin(t[1]) 0 0; 0 -sin(t[2]) 0; 0 0 -sin(t[3])]
The derivative computed by the first line is clearly not correct, while the problem goes away when I forcibly convert the symbolic expression with symbolic arrays to a scalar expression.
I do have a similar failing example with Symbolics v5.4.0
. I have used the scalarize
trick found here https://github.com/JuliaSymbolics/Symbolics.jl/issues/580#issuecomment-1109988415.
using Symbolics
using LinearAlgebra
@variables Ω[1:3] x[1:3] y[1:3] τ
# the below expressions should all have the same jacobian with respect to `x`
eqn1 = x / τ - cross(Ω, x) # note the absence of `y`
eqn2 = x / τ - cross(Ω, x - y)
eqn3 = x ./ τ .- cross(Ω, x .- y)
eqn4 = Symbolics.scalarize(x / τ - cross(Ω, x - y))
Symbolics.jacobian(eqn1, x) # OK
Symbolics.jacobian(eqn2, x) # KO
Symbolics.jacobian(eqn3, x) # KO
Symbolics.jacobian(eqn4, x) # OK
For me it is a dangerous bug since we start by building simple expressions to check everything is ok (and it is), and then we complexify things with confidence but the result is wrong.