# How to simplify a symbolic expression

I want to simplify an expression by replacing a sub-expression with a new variable, called `Q`.

The following code doesn’t work:

``````# simplify an expression
using Symbolics

@variables t
@syms ω(t) Pg(t) Pge(t) Pgc(t)
@variables A R a b Γ ρ U J Q

expr = (0.5A*R*a*Γ*ρ*(U^2)) / (J*ω(t)) - J*((0.5A*Γ*ρ*(U^3)*(b + (R*a*ω(t)) / U) - Pgc(t) - Pge(t)) / ((J^2)*(ω(t)^2)))
# Q = 0.5A*R*a*Γ*ρ

# how to substitute 0.5A*R*a*Γ*ρ by Q in expr?
expr2 = substitute(expr, Dict([0.5A*R*a*Γ*ρ => Q]))
``````

Q does not appear in expr2, the substitute command has no effect.

Why?

EDIT:
Is it possible to solve this task with Symbolics, or should I try other packages like GitHub - chakravala/Reduce.jl: Symbolic parser for Julia language term rewriting using REDUCE algebra ?

This needs to be done with a rule application, not substitute.

1 Like

Good suggestion, but not yet working.

``````using Symbolics

@variables t
@syms ω(t) Pg(t) Pge(t) Pgc(t)
@variables A R a b Γ ρ U J Q

expr = (0.5A*R*a*Γ*ρ*(U^2)) / (J*ω(t)) - J*((0.5A*Γ*ρ*(U^3)*(b + (R*a*ω(t)) / U) - Pgc(t) - Pge(t)) / ((J^2)*(ω(t)^2)))

r1 = @rule 0.5A*R*a*Γ*ρ => Q
# Q = 0.5A*R*a*Γ*ρ

# how to substitute 0.5A*R*a*Γ*ρ by Q in expr?
expr2 = r1(expr)
``````

The output is empty.

Any suggestion how to do this correctly?

Perhaps I should ask different questions. For example:

• is `expr` above actually an expression, because it is of type `Num`?
• how can I iterate over the elements of such an expression?
• what is the difference between `@syms` and `@variables` ?

Maybe you should use the package SymbolicUtils

Well, I think Symbolics re-exports SymbolicUtils, so that makes no difference…

On paper this is trivial, why is it so hard with Julia?

`substitute` currently only allows you to substitute variables for other expressions, not the other way around unfortunately…

To walk the expression, `tree = Symbolics.unwrap(expr)` which removes the `Num <: Real` wrapper.

Then you can use the expression walking interface: https://github.com/JuliaSymbolics/SymbolicUtils.jl/blob/master/page/interface.md

If I run this script:

``````using Symbolics

@variables t
@syms ω(t) Pg(t) Pge(t) Pgc(t) A
@variables R a b Γ ρ U J Q

expr = (0.5A*R*a*Γ*ρ*(U^2)) / (J*ω(t)) - J*((0.5A*Γ*ρ*(U^3)*(b + (R*a*ω(t)) / U) - Pgc(t) - Pge(t)) / ((J^2)*(ω(t)^2)))

tree = Symbolics.unwrap(expr)

function walk(tree, level=0)
for arg in arguments(tree)
indent = " "^level
println(indent, arg)
if istree(arg)
level += 1
walk(arg, level)
level -= 1
end
end
end

walk(tree)
``````

the output is:

``````(Pgc(t) + Pge(t) - 0.5A*Γ*ρ*(U^3)*(b + (R*a*ω(t)) / U)) / (J*(ω(t)^2))
Pgc(t) + Pge(t) - 0.5A*Γ*ρ*(U^3)*(b + (R*a*ω(t)) / U)
-0.5A*Γ*ρ*(U^3)*(b + (R*a*ω(t)) / U)
-0.5
A
Γ
ρ
U^3
U
3
b + (R*a*ω(t)) / U
b
(R*a*ω(t)) / U
R*a*ω(t)
R
a
ω(t)
t
U
Pgc(t)
t
Pge(t)
t
J*(ω(t)^2)
J
ω(t)^2
ω(t)
t
2
(0.5A*R*a*Γ*ρ*(U^2)) / (J*ω(t))
0.5A*R*a*Γ*ρ*(U^2)
0.5
A
R
a
Γ
ρ
U^2
U
2
J*ω(t)
J
ω(t)
t
``````

So I can walk the tree.

Next questions are how to identify the expression I want to replace, how to replace it, and then how to re-assemble it.

Next question: How can I check if two expressions are equal?

``````Q=0.5A*R*a*Γ*ρ*(U^2)
# now check if another expression is equal to Q
Q==0.5A*R*a*Γ*ρ*(U^2)
# the output is another expression, and not true or false
(0.5A*R*a*Γ*ρ*(U^2)) == (0.5A*R*a*Γ*ρ*(U^2))
``````

EDIT:
I am using now:

``````repr(subexpr) == "0.5A*R*a*Γ*ρ*(U^2)"
``````

Definitly not a robust solution, but works for now…

My current solution:

``````using Symbolics

@variables t
@syms ω(t) Pg(t) Pge(t) Pgc(t)
@variables R a b Γ ρ U J Q A

expr = (0.5A*R*a*Γ*ρ*(U^2)) / (J*ω(t)) - J*((0.5A*Γ*ρ*(U^3)*(b + (R*a*ω(t)) / U) - Pgc(t) - Pge(t)) / ((J^2)*(ω(t)^2)))

Qs = "0.5A*R*a*Γ*ρ"

# how to substitute 0.5A*R*a*Γ*ρ by Q in expr?

function subst(expr, from="", to="")
sexpr = repr(expr)
sres = replace(sexpr, from => to)
eval(Meta.parse(sres))
end

simple = subst(expr, Qs, "Q")
``````

Output:

``````(Pgc(t) + Pge(t) - 0.5A*Γ*ρ*(U^3)*(b + (R*a*ω(t)) / U)) / (J*(ω(t)^2)) + (Q*(U^2)) / (J*ω(t))
``````

Not a good solution because it uses eval and requires to the symbolic variables to be defined globally.

I will create two issues on this topic: