Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

simplify returns incorrect result #1373

Open
devmotion opened this issue Nov 22, 2024 · 5 comments
Open

simplify returns incorrect result #1373

devmotion opened this issue Nov 22, 2024 · 5 comments

Comments

@devmotion
Copy link
Contributor

I ran into the following issue on Symbolics#master:

julia> using Symbolics

julia> ex = (1.1540262529490819e-7(5.011872336272725e-8 + a)*(10^(-x))) / (2.511886431509582e-15((a + 10^(-x))^2)) + (-2.302585092994046(5.011872336272725e-8 + a)*(10^(-x))) / (5.011872336272725e-8(a + 10^(-x)));

julia> Symbolics.simplify(ex)
0

even though the expression is clearly not zero. As an example, compare

julia> Symbolics.substitute(ex, Dict(x => 1.0, a => 1.0))
-379691.03250567336

A bit longer story: I encountered this problem when using Symbolics.hessian(...; simplify=true). I got

julia> using Symbolics

julia> @variables t Ka ktr ph(t) tr1(t);

julia> D = Differential(t);

julia> ex = 10^(-ph)/(10^(-ph) + Ka) / (10^(-7.3) / (10^(-7.3) + Ka)) - ktr * tr1;

julia> Symbolics.hessian(ex, [ph, tr1]; simplify=true)
2×2 Matrix{Num}:
 0  0
 0  0

even though the second derivative of ex with respect to ph should be non-zero

julia> Symbolics.hessian(ex, [ph, tr1])
2×2 Matrix{Num}:
 (-2.65724e-7(5.01187e-8 + Ka)*(10^(-2ph(t)))) / (2.51189e-15((Ka + 10^(-ph(t)))^2)) + (5.3019(5.01187e-8 + Ka)*(10^(-ph(t)))) / (5.01187e-8(Ka + 10^(-ph(t)))) + 1.15403e-7(10^(-ph(t)))*((-2.30259(5.01187e-8 + Ka)*(10^(-ph(t)))) / (2.51189e-15((Ka + 10^(-ph(t)))^2))) + 1.15403e-7((-2.30259(5.01187e-8 + Ka)*(10^(-ph(t)))) / (2.51189e-15((Ka + 10^(-ph(t)))^2)) + 1.15677e-14(Ka + 10^(-ph(t)))*(10^(-ph(t)))*(((5.01187e-8 + Ka)*(10^(-ph(t)))) / (6.30957e-30((Ka + 10^(-ph(t)))^4))))*(10^(-ph(t)))    0
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              0     0

The example above is actually the slightly simpler case

julia> Symbolics.derivative(ex, ph; simplify=true)
0

julia> Symbolics.derivative(ex, ph)
(-2.302585092994046(5.011872336272725e-8 + Ka)*(10^(-ph(t)))) / (5.011872336272725e-8(Ka + 10^(-ph(t)))) + 1.1540262529490819e-7(((5.011872336272725e-8 + Ka)*(10^(-ph(t)))) / (2.511886431509582e-15((Ka + 10^(-ph(t)))^2)))*(10^(-ph(t)))
@ChrisRackauckas
Copy link
Member

Ooof that's not good. @shashi do you have an idea for where to start looking for this?

@benneti
Copy link
Contributor

benneti commented Dec 18, 2024

I did some digging and I think it has something to do with concrete (non-symbolic) prefactors in the numerator and denominator at the same time.
Furthermore, I think the problem is directly inherited from SymbolicUtils.jl where I could reproduce the issue on [d1185830] SymbolicUtils v3.7.2.

The following examples should be equivalent, apart from global factors:

using SymbolicUtils
@syms a x
> 1e-2x/(1e-2*a^3) - x/a^2 |> simplify
(0.01x - 0.01a*x) / (0.01(a^3))
> # we multiply the whole thing by 1e-7 and suddenly get 0
> 1e-9x/(1e-2*a^3) - 1e-7x/a^2 |> simplify
0
> # we do not get zero if we only have two concrete numbers in the expression
> x/(1e-2*a^3) - 1e2x/a^2 |> simplify
(x - a*x) / (0.01(a^3))
> 1e2x/(a^3) - 1e2x/a^2 |> simplify
(100.0x - 100.0a*x) / (a^3)
> # what about 4 concrete prefactors
> 1e-9x/(1e-2*a^3) - 1e-9x/(1e-2*a^2) |> simplify
0

I think this might at least narrow it down to the fraction cancellation logic, where concrete numbers are involved in both numerator and denominator in one fraction and at least one of them in the other fraction in an addition.

@devmotion
Copy link
Contributor Author

where I could reproduce the issue on [d1185830] SymbolicUtils v3.7.2

I detected the problem initially on SymbolicUtils 1.5.1, so it seems it has existed for quite some time.

@benneti
Copy link
Contributor

benneti commented Dec 18, 2024

Ok even more confident it is about fractions:

> 1e-9x/(1e-2*a^3) - 1e-9x/(1e-2*a^2) |> ex->simplify(ex; simplify_fractions=false)
(-1.0e-9x) / (0.01(a^2)) + (1.0e-9x) / (0.01(a^3))
> 1e-9x/(1e-2*a^3) - 1e-9x/(1e-2*a^2) |> simplify_fractions
0

@benneti
Copy link
Contributor

benneti commented Dec 19, 2024

even more digging: it is also related to the order of magnitude somehow of the concrete prefactors and both terms having polynomial expressions in the denominator:

> 1e-9/1e-2a^2 - 1e-6/a^3 |> simplify
0
> 1e-9/1e-2a^2 - 1e-5/a^3 |> simplify # also completely wrong but it somehow only discards the part that is 1e-7
-1.0000000000000001e-7 / (0.01(a^3))
> 1e-7/1e-2a^2 - 1e-7/a |> simplify # also wrong
1.0e-7 / (0.01(a^2))
> 1e-7/1e-2a^2 - 1e-5/a |> simplify # OK
(1.0e-7 - 1.0000000000000001e-7a) / (0.01(a^2))
> 1e-9/1e-2a^2 - 1e-5a^1/2 |> simplify # OK
-5.0e-6a + 1.0e-9 / (0.01(a^2))
> 1e-9/1e-2a^2 - 1e-7a^1/2 |> simplify # OK
-5.0e-8a + 1.0e-9 / (0.01(a^2))
> 1e-9a^2/1e-2 - 1e-5a^1/2 |> simplify # OK
-5.0e-6a + 1.0000000000000001e-7(a^2)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants