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

Trivial simplification not happening. #494

Closed
KronosTheLate opened this issue Jan 7, 2022 · 6 comments · Fixed by JuliaSymbolics/SymbolicUtils.jl#423
Closed

Trivial simplification not happening. #494

KronosTheLate opened this issue Jan 7, 2022 · 6 comments · Fixed by JuliaSymbolics/SymbolicUtils.jl#423

Comments

@KronosTheLate
Copy link

KronosTheLate commented Jan 7, 2022

I differentiated an expression. The result had a couple of glaring simplifications that Symbolics.jl does not seem to be able to see:

julia> using Symbolics

julia> @variables θ, n, x̄
3-element Vector{Num}:
  θ
  n
 x̄

julia> expr = n*log(1/(2*θ^3)) - 1/θ * n * x̄
n*log(1 / (2^3))) + (-n*x̄) / θ

julia> Symbolics.derivative(expr, θ)
(n*x̄) /^2) - 6n*^2)*(1 / (4^6)))*((1 / (2^3)))^-1)

julia> simplify(ans)
(n*x̄) /^2) - 6n*^2)*(1 / (4^6)))*((1 / (2^3)))^-1)

In this final expression, there are 5 powers of theta that can be cancelled. This is something I expect a simplify command to do.
But the worst offender has to be ((1 / (2(θ^3)))^-1), which is equal to 2(θ^3).

I have no idea how to fix it, but as I consider it an issue, I though I should report it.

@ForceBru
Copy link

ForceBru commented Jan 10, 2022

Same thing here. SymPy produces a very short expression, but Symbolics doesn't do obvious simplifications, especially with fractions.

Code

let K = 3
    @variables h[1:K] c[1:K] eps rho
    
    q(h) = (h + eps) / (1 + eps * K)
    
    ELBO = (
        sum(q(h[k]) * c[k] for k in 1:K)
        - sum(q(h[k]) * log(q(h[k])) for k in 1:K)
        - sum(log(h[k]) for k in 1:K) / rho
    )
    
    hess = Symbolics.hessian(ELBO, collect(h), simplify=true)
end

Output in Jupyter Lab:

hess

What's up with -1 / ((eps + h) / (1 + 3eps)) / (1 + 3eps) in the numerator? That's just -1 / (h + eps). Why write -1 / ((eps + h) / (1 + 3eps)) instead of -(1+3eps) / (eps + h)? Why write h^{-2} / rho instead of 1 / (rho * h^2)? This is complexification, not simplification.

SymPy simplifies this nicely:

hess_sp

Versions

  • Symbolics v4.2.3
  • Julia 1.8

@ChrisRackauckas
Copy link
Member

Did you try calling simplify_fractions?

@ForceBru
Copy link

@ChrisRackauckas, for my case, the Hessian becomes even more complicated. Symbolics.simplify_fractions.(hess)[1,1] returns this:

hess

@ChrisRackauckas
Copy link
Member

That's fun.

@KronosTheLate
Copy link
Author

It seems like simplify_fractions has other issues as well: #487
Now I have no idea how these things are implemented, but I feel that two such glaring problems might point to some deeper problem with the function.

@KronosTheLate
Copy link
Author

How the original example now works:

julia> using Symbolics

julia> @variables θ, n, x̄;

julia> expr = n*log(1/(2*θ^3)) - 1/θ * n * x̄;

julia> Symbolics.derivative(expr, θ)
(n*x̄) /^2) - 6n*^2)*(1 / (4^6)))*((1 / (2^3)))^-1)

julia> simplify(ans)
(n*- 3.0n*θ) /^2)

Thanks a lot for the quick and effective solution!

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

Successfully merging a pull request may close this issue.

3 participants