Wrong answer for derivative at branch points
LilithHafner opened this issue · 0 comments
The function f(x) == ifelse(x == 0, 0, x)
over the reals is mathematically equal to function f(x) = x
. It is continuously differentiable wit ha derivative of 1 everywhere. However, Symbolics.jl miscomputes it's value at zero:
julia> Symbolics.derivative(ifelse(x == 0, 0, x), x)
ifelse(x == 0, 0, 1)
Better answers would be 1
, ifelse(x == 0, 1, 1)
, or ifelse(x == 0, UNKNOWN, 1)
.
Getting the right answer on this sort of edge case is hard. It requires full symbolic limit calculation. A reduction from symbolic limit calculation to symbolic differentiation follows:
Take an arbitrary expression expr
and variable x
. To compute the limit of expr
as x
approaches 0
, consider the expression expr2 = ifelse(x == 0, 0, x*expr)
. The derivative of expr2
with respect to x
, evaluated at x0
is defined as the limit as h -> 0
of (expr2(x0+h) - expr2(x0)) / h
. Setting x0
to zero we find the derivative of expr2
with respect to x
, evaluated at 0
is the limit as h -> 0
of (expr2(0+h) - expr2(0)) / h = (expr2(h) - 0) / h = expr2(h) / h
. Because we are taking the limit as h -> 0
, we can assume h != 0
and simplify to expr2(h) / h = h*expr(h) / h = expr(h)
. Thus the derivative of expr2
with respect to x
evaluated at zero is equal to the limit of expr
as x
approaches zero. Because expr
and x
were arbitrary, any two-sided limit at zero can be trivially solved with a symbolic derivative oracle.