# \[Symbolics.jl\] Defining √2 as an (unevaluated) symbol

**URL:** <https://discourse.julialang.org/t/symbolics-jl-defining-2-as-an-unevaluated-symbol/65547>\
**Category:** General Usage\
**Tags:** symbolics\
**Created:** [July 30, 2021, 9:27am UTC](https://discourse.julialang.org/t/symbolics-jl-defining-2-as-an-unevaluated-symbol/65547 "2021-07-30T09:27:16Z")\
**Posts on this page:** 19\
**Page:** 1

<div class="post-metadata">

**Author:** ![sbrisard](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sbrisard/32/24712_2.png) [@sbrisard](https://discourse.julialang.org/u/sbrisard)\
**Post date:** [July 30, 2021, 9:27am UTC](https://discourse.julialang.org/t/symbolics-jl-defining-2-as-an-unevaluated-symbol/65547/1 "2021-07-30T09:27:16Z")

</div>

Hello,

with a colleague of mine, we are trying to evaluate `Symbolics.jl` (vs. `sympy`/`SymPy.jl` vs. `maxima` vs. `maple`).

A feature that we would really need would be to define `√2` as a symbol, **unevaluated**. What we have in mind is something like

```julia
In [1]: import sympy

In [2]: sympy.init_printing(use_unicode=True)

In [3]: sqrt_2 = sympy.sqrt(2)

In [4]: sqrt_2
Out[4]: √2

```

in `python/sympy`, or `sqrt(Sym(2))` in `julia/SymPy`.

Is it possible with `Symbolics.jl`? I am under the impression that `Symbolics.jl` was maybe not designed with such applications in mind.

I am aware of the post [Symbolic sqrt(2) and sin(pi)](https://discourse.julialang.org/t/symbolic-sqrt-2-and-sin-pi/58633). However, the solution proposed is not satisfactory for our use cases. Indeed

```julia
julia> using Symbolics

julia> sqrt_2 = Symbolics.Term(sqrt, [2])
sqrt(2)

julia> sqrt_2^2
sqrt(2)^2

```

What we really want is `sqrt_2^2` to return `2` (as `SymPy` would). Is this feature already existing? If not, is it planned, or completely out of scope?

Thanks for your answers!

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [July 30, 2021, 3:09pm UTC](https://discourse.julialang.org/t/symbolics-jl-defining-2-as-an-unevaluated-symbol/65547/2 "2021-07-30T15:09:38Z")

</div>

I don’t know why this rule isn’t part of the standard set (probably because of some floating point shenanigans with complex numbers), but if you truly desire to simplify like that, here’s how to do that. You just have to add that rewriting rule and make it available to `simplify`:

```julia
julia> using Symbolics, SymbolicUtils  
                                       
julia> r = @rule sqrt(~x)^2 => ~x      
sqrt(~x) ^ 2 => ~x                     
                                       
julia> sqrt_2 = Symbolics.Term(sqrt, 2)
sqrt(2)                                
                                       
julia> simplify(sqrt_2^2, RuleSet([r]))
2                                      

# also works with other numbers here, though again,
# in real applications beware of floating point shenanigans
julia> sqrt_2 = Symbolics.Term(sqrt, 1325)
sqrt(1325)                                
                                          
julia> simplify(sqrt_2^2, RuleSet([r]))   
1325                                      

```

I encourage you to check out the excellent documentation of SymbolicUtils and how those rules work (and how you can define your own!).

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [July 30, 2021, 6:32pm UTC](https://discourse.julialang.org/t/symbolics-jl-defining-2-as-an-unevaluated-symbol/65547/3 "2021-07-30T18:32:38Z")

</div>

Another option would be checking out `Metatheory.jl` (check out a talk introducing it from this years JuliaCon [here](https://live.juliacon.org/talk/F9PLVY)), which is basically very fast term rewriting/simplification (also has support for Symbolics.jl). Not 100% sure whether they have that rewriting rule defined by default though.

---

<div class="post-metadata">

**Author:** ![oscarbenjamin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscarbenjamin/32/22868_2.png) [@oscarbenjamin](https://discourse.julialang.org/u/oscarbenjamin)\
**Post date:** [July 31, 2021, 11:16pm UTC](https://discourse.julialang.org/t/symbolics-jl-defining-2-as-an-unevaluated-symbol/65547/4 "2021-07-31T23:16:10Z")

</div>

Is there a way to make an expression like \sqrt{x} and e.g. substitute 2 for x and get the exact value \sqrt{2}?

```julia
julia> using Symbolics, SymbolicUtils

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

julia> e = sqrt(x)
sqrt(x)

julia> substitute(e, (Dict(x => 2)))
1.4142135623730951

```

---

<div class="post-metadata">

**Author:** ![jzr](https://avatars.discourse-cdn.com/v4/letter/j/eb9ed0/32.png) [@jzr](https://discourse.julialang.org/u/jzr)\
**Post date:** [August 1, 2021, 6:12pm UTC](https://discourse.julialang.org/t/symbolics-jl-defining-2-as-an-unevaluated-symbol/65547/5 "2021-08-01T18:12:07Z")

</div>

That would be awesome. Have there been discussions about symbolic computations like \sqrt x|\_{x=2}\rightarrow \sqrt 2, @YingboMa@shashi?

---

<div class="post-metadata">

**Author:** ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)\
**Post date:** [August 1, 2021, 9:08pm UTC](https://discourse.julialang.org/t/symbolics-jl-defining-2-as-an-unevaluated-symbol/65547/6 "2021-08-01T21:08:04Z")

</div>

> [@jzr](#):
>
> That would be awesome. Have there been discussions about symbolic computations like \sqrt x|\_{x=2}\rightarrow \sqrt 2

There could probably be a keyword argument for “substitute but don’t interpret”. Can you open an issue for that?

---

<div class="post-metadata">

**Author:** ![YingboMa](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yingboma/32/2181_2.png) [@YingboMa](https://discourse.julialang.org/u/YingboMa)\
**Post date:** [August 1, 2021, 10:02pm UTC](https://discourse.julialang.org/t/symbolics-jl-defining-2-as-an-unevaluated-symbol/65547/7 "2021-08-01T22:02:09Z")

</div>

No need to submit an issue. The feature already exists.

```julia
julia> using Symbolics

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

julia> substitute(sqrt(x), Dict(x=>2), fold=false)
sqrt(2)

```

---

<div class="post-metadata">

**Author:** ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)\
**Post date:** [August 1, 2021, 11:25pm UTC](https://discourse.julialang.org/t/symbolics-jl-defining-2-as-an-unevaluated-symbol/65547/8 "2021-08-01T23:25:53Z")

</div>

TBF, undocumented.

---

<div class="post-metadata">

**Author:** ![sbrisard](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sbrisard/32/24712_2.png) [@sbrisard](https://discourse.julialang.org/u/sbrisard)\
**Post date:** [August 2, 2021, 8:10am UTC](https://discourse.julialang.org/t/symbolics-jl-defining-2-as-an-unevaluated-symbol/65547/9 "2021-08-02T08:10:39Z")

</div>

This is quite exciting indeed. I will watch this video very closely, thanks for the suggestion.

---

<div class="post-metadata">

**Author:** ![sbrisard](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sbrisard/32/24712_2.png) [@sbrisard](https://discourse.julialang.org/u/sbrisard)\
**Post date:** [August 2, 2021, 8:17am UTC](https://discourse.julialang.org/t/symbolics-jl-defining-2-as-an-unevaluated-symbol/65547/10 "2021-08-02T08:17:12Z")

</div>

> I encourage you to check out the excellent documentation of SymbolicUtils and how those rules work (and how you can define your own!).

This indeed seems to solve my problem. I will study `SymbolcUtils` more closely, then. Best

---

<div class="post-metadata">

**Author:** ![sbrisard](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sbrisard/32/24712_2.png) [@sbrisard](https://discourse.julialang.org/u/sbrisard)\
**Post date:** [August 2, 2021, 8:26am UTC](https://discourse.julialang.org/t/symbolics-jl-defining-2-as-an-unevaluated-symbol/65547/11 "2021-08-02T08:26:50Z")

</div>

Hello,

First, let me thank everyone which posted on this thread. Just for the record, here is a slightly more complex example (I agree it is quite trivial in this present form, but it might apply to more complex situations)

```julia
julia> using Symbolic
SymbolicUtils Symbolics
julia> using SymbolicUtils, Symbolics

julia> r = @rule sqrt((~x)^2) => abs(~x)
sqrt((~x) ^ 2) => abs(~x)

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

julia> sqr_minus_2 = substitute(x^2, Dict(x=>-2), fold=false)
(-2)^2

julia> simplify(sqrt(sqr_minus_2), RuleSet([r]))
2

```

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [August 2, 2021, 8:37am UTC](https://discourse.julialang.org/t/symbolics-jl-defining-2-as-an-unevaluated-symbol/65547/12 "2021-08-02T08:37:58Z")

</div>

I’m not an expert in terms of Symbolics.jl or CAS, but from my understanding, `substitute` should always be the last step, no? I.e. first simplify the expression given as far as possible, under all known Rules/legal transforms, substitute a variable and continue with evaluation.

As far as I understand from your questions, you basically want to avoid seeing “ugly” results/results containing literal floating point values?

---

<div class="post-metadata">

**Author:** ![sbrisard](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sbrisard/32/24712_2.png) [@sbrisard](https://discourse.julialang.org/u/sbrisard)\
**Post date:** [August 2, 2021, 9:41am UTC](https://discourse.julialang.org/t/symbolics-jl-defining-2-as-an-unevaluated-symbol/65547/13 "2021-08-02T09:41:42Z")

</div>

You’re right. `substitute` is, as far as I understand, a “trick” to define `sqrt(2)` (or in the present case, `(-2)^2`) as an unevaluated symbol.  
Note that we need to be able to define `sqrt(2)` as a symbol, because we use a matrix representation of second- and fourth- rank, tensors with minor symmetries which use the `sqrt(2)` weighting.  
And we really need that `sqrt(2)²` should simplify as `2`.

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [August 2, 2021, 1:26pm UTC](https://discourse.julialang.org/t/symbolics-jl-defining-2-as-an-unevaluated-symbol/65547/14 "2021-08-02T13:26:24Z")

</div>

You mean something like this?

```julia
julia> f = [sqrt(x)^(y*(i+j)) for i in 1:5, j in 1:5]               
5×5 Matrix{Num}:                                                      
 sqrt(x)^(2y) sqrt(x)^(3y) sqrt(x)^(4y) sqrt(x)^(5y) sqrt(x)^(6y)
 sqrt(x)^(3y) sqrt(x)^(4y) sqrt(x)^(5y) sqrt(x)^(6y) sqrt(x)^(7y)
 sqrt(x)^(4y) sqrt(x)^(5y) sqrt(x)^(6y) sqrt(x)^(7y) sqrt(x)^(8y)
 sqrt(x)^(5y) sqrt(x)^(6y) sqrt(x)^(7y) sqrt(x)^(8y) sqrt(x)^(9y)
 sqrt(x)^(6y) sqrt(x)^(7y) sqrt(x)^(8y) sqrt(x)^(9y) sqrt(x)^(10y)
                                                                      
julia> r_3 = @rule ^(sqrt(~x),~y) => ^(~x, ~y/2)                      
sqrt(~x) ^ ~y => (~x) ^ (~y / 2)                                      
                                                                      
julia> simplify.(f, Ref(RuleSet([r_3])))                              
5×5 Matrix{Num}:                                                      
          x^y x^((3//2)*y) x^((2//1)*y) x^((5//2)*y) x^((3//1)*y) 
 x^((3//2)*y) x^((2//1)*y) x^((5//2)*y) x^((3//1)*y) x^((7//2)*y) 
 x^((2//1)*y) x^((5//2)*y) x^((3//1)*y) x^((7//2)*y) x^((4//1)*y) 
 x^((5//2)*y) x^((3//1)*y) x^((7//2)*y) x^((4//1)*y) x^((9//2)*y) 
 x^((3//1)*y) x^((7//2)*y) x^((4//1)*y) x^((9//2)*y) x^((5//1)*y)

```

May not be exactly what you’re looking for, since I have a Matrix of symbolic variables that I simplify via broadcasting. Afterwards I can just `substitute`:

```julia
# just y
julia> substitute.(res, Ref(Dict(y => 1)))                           
5×5 Matrix{Num}:                                                     
        x x^(3//2) x^(2//1) x^(5//2) x^(3//1)                    
 x^(3//2) x^(2//1) x^(5//2) x^(3//1) x^(7//2)                    
 x^(2//1) x^(5//2) x^(3//1) x^(7//2) x^(4//1)                    
 x^(5//2) x^(3//1) x^(7//2) x^(4//1) x^(9//2)                    
 x^(3//1) x^(7//2) x^(4//1) x^(9//2) x^(5//1)                    
           
# just x                                                          
julia> substitute.(res, Ref(Dict(x => 2)))                           
5×5 Matrix{Num}:                                                     
          2^y 2^((3//2)*y) 2^((2//1)*y) 2^((5//2)*y) 2^((3//1)*y)
 2^((3//2)*y) 2^((2//1)*y) 2^((5//2)*y) 2^((3//1)*y) 2^((7//2)*y)
 2^((2//1)*y) 2^((5//2)*y) 2^((3//1)*y) 2^((7//2)*y) 2^((4//1)*y)
 2^((5//2)*y) 2^((3//1)*y) 2^((7//2)*y) 2^((4//1)*y) 2^((9//2)*y)
 2^((3//1)*y) 2^((7//2)*y) 2^((4//1)*y) 2^((9//2)*y) 2^((5//1)*y)
           
# both, which causes all symbolics terms to collapse to equivalent values                                                          
julia> substitute.(res, Ref(Dict(x => 2, y => 1)))                   
5×5 Matrix{Num}:                                                     
 2 2.82843 4.0 5.65685 8.0                         
 2.82843 4.0 5.65685 8.0 11.3137                      
 4.0 5.65685 8.0 11.3137 16.0                         
 5.65685 8.0 11.3137 16.0 22.6274                      
 8.0 11.3137 16.0 22.6274 32.0                         

```

The last example collapses into direct values since under the given rules (+ default rules), the numerical value is equivalent to the uncomputed symbolic value. The full floating point value is still there by the way, it’s just not printed:

```julia
julia> ans[1,2] |> dump        
Num                            
  val: Float64 2.82842712474619

```

* * *

Again, I’m not a CAS expert, I’m just messing around with broadcasting and what I can find in the docs of `Symbolics.jl` 🙂

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [August 2, 2021, 1:39pm UTC](https://discourse.julialang.org/t/symbolics-jl-defining-2-as-an-unevaluated-symbol/65547/15 "2021-08-02T13:39:29Z")

</div>

Hm, I guess my example isn’t quite what you’re thinking of, but it’s a generalized version taking any `sqrt(x)` weighting you’d like 🤔

---

<div class="post-metadata">

**Author:** ![oscarbenjamin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscarbenjamin/32/22868_2.png) [@oscarbenjamin](https://discourse.julialang.org/u/oscarbenjamin)\
**Post date:** [August 5, 2021, 10:07pm UTC](https://discourse.julialang.org/t/symbolics-jl-defining-2-as-an-unevaluated-symbol/65547/16 "2021-08-05T22:07:25Z")

</div>

> [@Sukera](#):
>
> `r = @rule sqrt(~x)^2 => ~x`

How would I go about defining a cleverer rule that can handle powers other than 2?

```julia
julia> using Symbolics, SymbolicUtils
  
julia> @variables x, y
2-element Vector{Num}:
 x
 y

julia> expand((1 + sqrt(y))^10)
1 + sqrt(y)^10 + 10sqrt(y) + 45(sqrt(y)^2) + 120(sqrt(y)^3) + 210(sqrt(y)^4) + 252(sqrt(y)^5) + 210(sqrt(y)^6) + 120(sqrt(y)^7) + 45(sqrt(y)^8) + 10(sqrt(y)^9)

julia> expand((1 + sqrt(y))^6)
1 + sqrt(y)^6 + 6sqrt(y) + 15(sqrt(y)^2) + 20(sqrt(y)^3) + 15(sqrt(y)^4) + 6(sqrt(y)^5)

julia> r = @rule sqrt(~x)^2 => ~x
sqrt(~x) ^ 2 => ~x

julia> simplify(expand((1 + sqrt(y))^6), RuleSet([r]))
1 + 15y + sqrt(y)^6 + 6sqrt(y) + 20(sqrt(y)^3) + 15(sqrt(y)^4) + 6(sqrt(y)^5)

```

It should be possible to reduce this to an expression of the form a + b\sqrt{y} where a and b are integers.

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [August 5, 2021, 10:26pm UTC](https://discourse.julialang.org/t/symbolics-jl-defining-2-as-an-unevaluated-symbol/65547/17 "2021-08-05T22:26:38Z")

</div>

My guess would be going the other way around - define

```julia
r = @rule sqrt(~x) => (~x)^(1//2)

```

instead and all those nested powers should collapse nicely:

```julia
julia> r = @rule sqrt(~x) => (~x)^(1//2)                                    
sqrt(~x) => (~x) ^ (1 // 2)                                                 
                                                                            
julia> simplify(expand((1+ sqrt(y))^6), RuleSet([r]))                       
1 + y^(3//1) + 15y + 6(y^(1//2)) + 20(y^(3//2)) + 15(y^(2//1)) + 6(y^(5//2))

```

That rule alone won’t be enough to make the “ugly” powers go away and bring it into the form you think of, but then again I have to stress that I’m not an expert in CAS 🙂 I may be missing something with writing rules though and matching those non-variable powers for some pattern and extracting something else from them may be possible, so me not knowing how to do this should not be taking as an indicator that Symbolics.jl can’t do it.

---

<div class="post-metadata">

**Author:** ![jzr](https://avatars.discourse-cdn.com/v4/letter/j/eb9ed0/32.png) [@jzr](https://discourse.julialang.org/u/jzr)\
**Post date:** [August 5, 2021, 10:41pm UTC](https://discourse.julialang.org/t/symbolics-jl-defining-2-as-an-unevaluated-symbol/65547/18 "2021-08-05T22:41:46Z")

</div>

I wonder if [Metatheory.jl](https://0x0f0f0f.github.io/Metatheory.jl/dev/) might support that better.

---

<div class="post-metadata">

**Author:** ![oscarbenjamin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscarbenjamin/32/22868_2.png) [@oscarbenjamin](https://discourse.julialang.org/u/oscarbenjamin)\
**Post date:** [August 6, 2021, 12:43am UTC](https://discourse.julialang.org/t/symbolics-jl-defining-2-as-an-unevaluated-symbol/65547/19 "2021-08-06T00:43:39Z")

</div>

> [@oscarbenjamin](#):
>
> It should be possible to reduce this to an expression of the form a + b\sqrt{y} a+b√ya + b\sqrt{y} where a aa and b bb are integers.

Actually that’s not true!

I intended for the y to be 2 so it should be an expression in \sqrt{2} rather than \sqrt{y}. In that case all even powers of \sqrt{2} reduce to rational. Something like \sqrt{y}^3 does not though because it would simplify as y\sqrt{y} and you’d be left with polynomials in y and some \sqrt{y} factors.

To correct the above the expression below should be writeable in the form a + b \sqrt{2}:

```julia
julia> f = substitute(1 + sqrt(y), Dict(y=>2), fold=false)
1 + sqrt(2)

julia> f
1 + sqrt(2)

julia> expand(f^6)
1 + sqrt(2)^6 + 6sqrt(2) + 15(sqrt(2)^2) + 20(sqrt(2)^3) + 15(sqrt(2)^4) + 6(sqrt(2)^5)

julia> r = @rule sqrt(~x) => (~x)^(1//2)
sqrt(~x) => (~x) ^ (1 // 2)

julia> simplify(expand(f^6), RuleSet([r]))
189.9949493661167 + 1.4142135623730951^6

julia> simplify(expand(f^6), RuleSet([r]), fold=false)
ERROR:

```

It doesn’t seem like `simplify` has the `fold=false` argument…
