Can Symbolics.jl simplify subexpressions?

I have been trying out Symbolics.jl for a few projects recently. Initially I was excited but have run into a few issues that are road blocks. Some are probably asking too much this early in development - (A::SparseMatrixCSC{Num, Int64})^(1/2) doesn’t work (I get the" non-boolean (Num) used in a boolean context" error referenced in the docs) - but more surprising to me is I couldn’t get simplify to work below the first level of an expression. I’m coming from Mathematica for symbolic math, and this was really disappointing (and I am hoping user error). As an MWE,

using Symbolics

@variables y
t1 = sqrt(y^2)
t2 = abs(sqrt(y^2))
sqrtrule = @rule sqrt((~x)^2) => ~x

s1 = simplify(t1, sqrtrule)
s2 = simplify(t2, sqrtrule)

In this example, (a common simplification for a real positive variable) I get s1=y, but s2=abs(sqrt(y^2)).
Symbolics is (rightfully) giving me some gigantic expressions during my computations, and this is one example of the kind of pattern embedded in the result that I would like to simplify before generating a function… how can I do this?


Square root of a sparse matrix is hard to do numerically. Did you mean .^?

You need to add a Postwalk to that I think?

Did you run simplify or were you using your own rule set?

Thanks for the reply. Point by point…

  1. Nope, I meant the square root of the matrix. I guessed that would be hard / unsupported, and can probably cut of the symbolic part before that (and do it numerically later).
  2. I also tried making the rule a post walk, but maybe I didn’t do it right? Doing
simplify(t2, SymbolicUtils.Postwalk(sqrtrule))

also does nothing.
3. I tried plain simplify first, but it didn’t do anything to my expression. Coming from Mathematica for symbolics (Julia for numerics for a while now), I had hoped to specify some assumptions about variable domains, but that doesn’t appear to be supported yet. Baring that I tried passing my own simplification for this simple case, but even that didn’t do anything (and hence my post).


I think you need the matrix log to define that. Yeah, I don’t think you’ll get a good general symbolic solution there?

Yeah, open an issue. This is a question for @shashi

Variable domains are not implemented yet, though we’re getting there: Added the ability to pass known SymPy symbols to symbolics_to_sympy function by owiecc · Pull Request #351 · JuliaSy

Ok, thanks for the reply. I opened an issue at Symbolics.jl (maybe it should be at SymbolicUtils?).

1 Like

That’s good, thanks.

For anyone that comes across this, I thought I would share the answer I got from shashi to the issue. In short, if you want a rewrite rule that operates below the top level of an expression it does need to be a Prewalk/Postwalk, BUT those require a rewriter with passthrough behavior (by default rewriters return nothing if there is no change). If combining multiple rules, Chain has this behavior, and for just one rule you can wrap it in PassThrough. So, for the example above,

simplify(t2, Rewriters.Prewalk(Rewriters.PassThrough(sqrtrule)))

gives the desired behavior.