## Numeric vs symbolic computing


```python
1.01 - 1
```




    0.010000000000000009



Floating point numbers have limited accuracy (53 bits for double precision IEEE 754)


```python
import math
math.log10(2**53)
```




    15.954589770191003



That is, about 15 decimal places. Additionally, decimal numbers don't have exact representation in binary in general. In some cases, it may lead to accumulation of errors (numerically unstable algorithms)


```python
x = 1
for i in range(10):
    x = (1.01-x)*100
    print(x)
```

    1.0000000000000009
    0.9999999999999121
    1.0000000000087939
    0.9999999991206154
    1.0000000879384574
    0.9999912061542604
    1.0008793845739605
    0.912061542603948
    9.7938457396052
    -878.38457396052


## SymPy as a calculator

Symbolic computing uses exact mathematical rules. Numbers in sympy are represented by objects of type Integer, Rational, and Float and they have overloaded mathematical operators


```python
from sympy import *
```


```python
Rational(101, 100)-Integer(1)
```




    1/100




```python
sympify("101/100-1")
```




    1/100




```python
nsimplify("1.01") - 1
```




    1/100




```python
x = Integer(1)
for i in range(10):
    x = (Rational(101, 100)-x)*100
    print(x)
```

    1
    1
    1
    1
    1
    1
    1
    1
    1
    1


Sympy has some predefined mathematical constants


```python
E*I - pi
```




    -pi + E*I



and many functions...


```python
cos(0)
```




    1




```python
sin(pi/3)
```




    sqrt(3)/2



and you can evaluate the expressions numerically with function N() or method .evalf() with arbirtary precision (based on mpmath)


```python
N(pi+E*I, 30)
```




    3.14159265358979323846264338328 + 2.71828182845904523536028747135*I




```python
sqrt(2).evalf(1000)
```




    1.414213562373095048801688724209698078569671875376948073176679737990732478462107038850387534327641572735013846230912297024924836055850737212644121497099935831413222665927505592755799950501152782060571470109559971605970274534596862014728517418640889198609552329230484308714321450839762603627995251407989687253396546331808829640620615258352395054745750287759961729835575220337531857011354374603408498847160386899970699004815030544027790316454247823068492936918621580578463111596668713013015618568987237235288509264861249497715421833420428568606014682472077143585487415565706967765372022648544701585880162075847492265722600208558446652145839889394437092659180031138824646815708263010059485870400318648034219489727829064104507263688131373985525611732204024509122770022694112757362728049573810896750401836986836845072579936472906076299694138047565482372899718032680247442062926912485905218100445984215059112024944134172853147810580360337107730918286931471017111168391658172688941975871658215212822951848847



## Symbolic computing
Symbols are python objects


```python
x, y, z = symbols("x, y, z")
alpha, beta, delta = symbols('alpha, beta, delta')
```

symbolic expressions are created using standard python syntax


```python
expr = x**y + sqrt(alpha)/2
expr
```




    sqrt(alpha)/2 + x**y



SymPy can print expressions in various forms, including $\LaTeX$, unicode pretty printing, and others. The pretty printing is enabled with `init_printing()`


```python
init_printing()
```


```python
expr
```

Lists of symbols can be created with the following notation


```python
symbols("x0:10")
```

### Basic manipulation with the expressions
#### Polynomials and rational functions


```python
(x+y)**10
```

Polynomials can be expanded


```python
expand(_)
```

and, more importantly, factorized


```python
factor(_)
```


```python
_.subs(x+y, z)
```

We can collect the terms with the same power of a given variable


```python
collect(y*x**2 + 3*x**2 - x*y + x - 1, x)
```

Cancel rational functions


```python
cancel((x**2 + 2*x + 1)/(x**2 - 1))
```

or decompose them into partial fractions


```python
apart((x**3 + 4*x - 1)/(x**2 - 1))
```

#### Trigonometric functions


```python
sin(x+y)
```


```python
expand(_, trig=True)
```


```python
trigsimp(_)
```


```python
trigsimp(sin(x)**2 + cos(x)**2)
```

#### Exponentiation


```python
x**alpha * y**alpha
```


```python
powsimp(_)
```

Note that symbols in SymPy are complex by default. However, $x^\alpha y^\alpha$ does not equal $(xy)^\alpha$ in general. For example $\sqrt{-1}\sqrt{-1} \neq \sqrt{-1\cdot-1}$.

It is valid for $x, y \ge 0$ and $\alpha\in\mathbb R$ and we have to define the symbols as such.

Similarly $(x^a)^b = x^{ab}$ holds only for $b\in\mathbb Z$


```python
x_pos, y_pos = symbols("x_pos, y_pos", positive=True)
alpha_R = symbols("alpha_R", real=True)
beta_Z = symbols("beta_Z", integer=True)
```


```python
powsimp(x_pos**alpha_R * y_pos**alpha_R)
```


```python
(expand_power_base(_))
```


```python
(z**delta)**beta_Z
```


```python
log(x_pos**alpha_R * y_pos)
```


```python
expand_log(_)
```


```python
logcombine(_)
```

The need for assumptions can be avoided using `force=True` (not recommended :)


```python
expand_log(log(x**alpha * y))
```


```python
expand_log(log(x**alpha * y), force=True)
```

#### Rewriting functions


```python
tan(x).rewrite(sin)
```

Note that there are many special functions defined in SymPy...


```python
factorial(x).rewrite(gamma)
```


```python
k, m, n = symbols('k, m, n')
binomial(k, n).rewrite(factorial)
```


```python
binomial(k, k-2)
```


```python
combsimp(_)
```

#### Equation solving
Equations are defined using `Eq`. Note that `=` is assignment and `==` tests for exact identity of two expressions


```python
Eq(x**2, 1)
```

`solveset` attempts to find all solutions of the given equation. If it fails, you may try to use `solve`...


```python
solveset(_, x)
```


```python
solveset(sin(x), x)
```


```python
solveset(x**2+1, x)
```


```python
solveset(x**2+1, x, domain=S.Reals)
```


```python
solveset(exp(x)-1, x)
```


```python
solveset(exp(x) > 1, x, domain=S.Reals)
```


```python
linsolve([x + y + z - 1, x + y + 2*z - 3 ], (x, y, z))
```


```python
nonlinsolve([x**2 + 1, y**2 + 1], [x, y])
```

## Sympy internals
Expressions are represented as trees. This can be seen by printing with srepr


```python
x*y
```


```python
srepr(x*y)
```




    "Mul(Symbol('x'), Symbol('y'))"




```python
from IPython.display import Image
def show_tree(expr):
    with open("xy.dot", "w") as f:
        f.write(dotprint(expr))
    !dot xy.dot -Tpng > xy.png
    return Image(filename='xy.png') 
```


```python
show_tree(x*y)
```


```python
expr = sin(x)/y+1-x
show_tree(expr)
```


```python
expr.func
```




    sympy.core.add.Add




```python
expr.args
```


```python
expr.args[1].func
```




    sympy.core.mul.Mul




```python
expr.args[1].args
```

34a7ed36f345365af0a7d0e96bdc1c2c4c2762b9
ipynb
Jupyter Notebook
notebooks/01 Basics.ipynb
rouckas/sympy-slides
c2777f0eddedd19c4bf094d40489f49c1ef8ad28
BSD-3-Clause
2018-10-22T19:52:48.000Z
2018-12-01T16:59:45.000Z
notebooks/01 Basics.ipynb
rouckas/sympy-slides
c2777f0eddedd19c4bf094d40489f49c1ef8ad28
BSD-3-Clause
notebooks/01 Basics.ipynb
rouckas/sympy-slides
c2777f0eddedd19c4bf094d40489f49c1ef8ad28
BSD-3-Clause
Qwen/Qwen-72B
1. YES
2. YES