SymbolicUtils.jl icon indicating copy to clipboard operation
SymbolicUtils.jl copied to clipboard

expand_derivatives returns float expression

Open karlwessel opened this issue 10 months ago • 7 comments

The following MWE demonstrates a case where expand_derivatives returns a floating point constant instead of a rational:

julia> using Symbolics

julia> @variables a x
2-element Vector{Num}:
 a
 x

julia> ex = exp(a*x)/(2a)
exp(a*x) / (2a)

julia> D = Differential(x)
Differential(x)

julia> expand_derivatives(D(D(ex)))
0.5a*exp(a*x)

Note that expanding the derivative of the manual input of the result of the inner derivative correctly uses an rational:

julia> expand_derivatives(D(ex))
exp(a*x) / 2

julia> expand_derivatives(D(exp(a*x)/2))
(1//2)*a*exp(a*x)

This is likely because the manual input gets automatically changed to $\frac 12 \exp(ax)$ but the result of the expanded inner derivative is $\exp(ax)/2$.

Tested with Symbolics v6.22.1 and v6.10.0.

karlwessel avatar Jan 08 '25 09:01 karlwessel

I think this is a problem with cancelling fractions in Div by SymbolicUtils and better expressed with this MWE:

julia> using SymbolicUtils
julia> @syms x
(x,)

julia> 2x^2/3x
(2x) / 3

julia> 2x / 3
(2//3)*x

The second call prefers representing Integer denominators as a rational factor, which avoids dividing by Number and creating a floating point expression at later times.

I would propose that Div also returns a multiplication with a rational when the denominator is a number by adding the method

Div(n, d::Number) = n / d

Should I transfer the issue to SymbolicUtils?

karlwessel avatar Apr 03 '25 16:04 karlwessel

Yes. And I like that solution.

ChrisRackauckas avatar Apr 03 '25 16:04 ChrisRackauckas

Can you transfer the issue, or do I have to manually close this one and reopen a new one at SymbolicUtils?

karlwessel avatar Apr 03 '25 16:04 karlwessel

Div(n, d::Number) = n / d

That would returns something else than a Div however, isn't that bad style?

karlwessel avatar Apr 04 '25 13:04 karlwessel

We should still make it a BasicSymbolic, but since it's a unitype I don't think it necessarily needs to be a "Div", which is just a runtime change.

ChrisRackauckas avatar Apr 05 '25 00:04 ChrisRackauckas

I've just seen that Div already returns Rationals instead of Div in certain cases (Line 672 in types.jl):

n isa Rat && d isa Rat && return n // d

I could just change that line to

d isa Rat && return n * 1/d

as a fix.

karlwessel avatar Apr 05 '25 12:04 karlwessel

yeah that seems reasonable

ChrisRackauckas avatar Apr 05 '25 12:04 ChrisRackauckas