# Symbolic Computation
Symbolic computation deals with symbols, representing them exactly, instead of numerical approximations (floating point). 

We will start with the following [borrowed](https://docs.sympy.org/latest/tutorial/intro.html) tutorial to introduce the concepts of SymPy. Devito uses SymPy heavily and builds upon it in its DSL. 


```python
import math

math.sqrt(3)
```




    1.7320508075688772




```python
math.sqrt(8)
```




    2.8284271247461903



$\sqrt(8) = 2\sqrt(2)$, but it's hard to see that here


```python
import sympy
sympy.sqrt(3)
```




$\displaystyle \sqrt{3}$



SymPy can even simplify symbolic computations


```python
sympy.sqrt(8)
```




$\displaystyle 2 \sqrt{2}$




```python
from sympy import symbols
x, y = symbols('x y')
expr = x + 2*y
expr

```




$\displaystyle x + 2 y$



Note that simply adding two symbols creates an expression. Now let's play around with it. 


```python
expr + 1
```




$\displaystyle x + 2 y + 1$




```python
expr - x
```




$\displaystyle 2 y$



Note that `expr - x` was not `x + 2y -x`


```python
x*expr
```




$\displaystyle x \left(x + 2 y\right)$




```python
from sympy import expand, factor
expanded_expr = expand(x*expr)
expanded_expr
```




$\displaystyle x^{2} + 2 x y$




```python
factor(expanded_expr)
```




$\displaystyle x \left(x + 2 y\right)$




```python
from sympy import diff, sin, exp

diff(sin(x)*exp(x), x)
```




$\displaystyle e^{x} \sin{\left(x \right)} + e^{x} \cos{\left(x \right)}$




```python
from sympy import limit

limit(sin(x)/x, x, 0)
```




$\displaystyle 1$



### Exercise

Solve $x^2 - 2 = 0$ using sympy.solve


```python
# Type solution here
from sympy import solve
```

## Pretty printing


```python
from sympy import init_printing, Integral, sqrt

init_printing(use_latex=True)
```


```python
Integral(sqrt(1/x), x)
```


```python
from sympy import latex

latex(Integral(sqrt(1/x), x))
```




    '\\int \\sqrt{\\frac{1}{x}}\\, dx'



More symbols.
Exercise: fix the following piece of code


```python
# NBVAL_SKIP
# The following piece of code is supposed to fail as it is
# The exercise is to fix the code

expr2 = x + 2*y +3*z
```

### Exercise 

Solve $x + 2*y + 3*z$ for $x$


```python
# Solution here
from sympy import solve
```

Difference between symbol name and python variable name


```python
x, y = symbols("y z")
```


```python
x
```


```python
y
```


```python
# NBVAL_SKIP
# The following code will error until the code in cell 16 above is
# fixed
z
```

Symbol names can be more than one character long


```python
crazy = symbols('unrelated')

crazy + 1
```


```python
x = symbols("x")
expr = x + 1
x = 2
```

What happens when I print expr now? Does it print 3?


```python
print(expr)
```

    x + 1


How do we get 3?


```python
x = symbols("x")
expr = x + 1
expr.subs(x, 2)
```

## Equalities


```python
x + 1 == 4
```




    False




```python
from sympy import Eq

Eq(x + 1, 4)
```

Suppose we want to ask whether $(x + 1)^2 = x^2 + 2x + 1$


```python
(x + 1)**2 == x**2 + 2*x + 1
```




    False




```python
from sympy import simplify

a = (x + 1)**2
b = x**2 + 2*x + 1

simplify(a-b)
```

### Exercise 
Write a function that takes two expressions as input, and returns a tuple of two booleans. The first if they are equal symbolically, and the second if they are equal mathematically.

## More operations


```python
z = symbols("z")
expr = x**3 + 4*x*y - z
expr.subs([(x, 2), (y, 4), (z, 0)])
```


```python
from sympy import sympify

str_expr = "x**2 + 3*x - 1/2"
expr = sympify(str_expr)
expr
```


```python
expr.subs(x, 2)
```


```python
expr = sqrt(8)
```


```python
expr
```


```python
expr.evalf()
```


```python
from sympy import pi

pi.evalf(100)
```


```python
from sympy import cos

expr = cos(2*x)
expr.evalf(subs={x: 2.4})
```

### Exercise



```python
from IPython.core.display import Image 
Image(filename='figures/comic.png') 
```

Write a function that takes a symbolic expression (like pi), and determines the first place where 789 appears.
Tip: Use the string representation of the number. Python starts counting at 0, but the decimal point offsets this

## Solving an ODE


```python
from sympy import Function

f, g = symbols('f g', cls=Function)
f(x)
```


```python
f(x).diff()
```


```python
diffeq = Eq(f(x).diff(x, x) - 2*f(x).diff(x) + f(x), sin(x))
diffeq
```


```python
from sympy import dsolve

dsolve(diffeq, f(x))
```

## Finite Differences


```python

f = Function('f')
dfdx = f(x).diff(x)
dfdx.as_finite_difference()
```


```python
from sympy import Symbol

d2fdx2 = f(x).diff(x, 2)
h = Symbol('h')
d2fdx2.as_finite_difference(h)
```

Now that we have seen some relevant features of vanilla SymPy, let's move on to Devito, which could be seen as SymPy finite differences on steroids!

b1e9cbb90d1c64e70bfdc05aa98bfe7e4846a069
ipynb
Jupyter Notebook
examples/userapi/00-sympy.ipynb
tallamjr/devito
677ea0f00809c865c54276b3f44821052913ffcf
MIT
2019-04-05T20:52:23.000Z
2019-11-03T21:36:53.000Z
examples/userapi/00-sympy.ipynb
tallamjr/devito
677ea0f00809c865c54276b3f44821052913ffcf
MIT
2019-06-11T20:54:19.000Z
2020-04-06T17:56:10.000Z
examples/userapi/00-sympy.ipynb
vmickus/devito
1e8d6af2cb8615e47ae20b68d5f2e30d530d03ff
MIT
Qwen/Qwen-72B
1. YES
2. YES