1. Introduction to Sympy and the Jupyter Notebook for engineering calculations

Sympy is a computer algebra module for Python. You are looking at the convenient Jupyter Notebook interface. This notebook aims to show some of the useful features of the Sympy system as well as the notebook interface.

This notebook will use Python as the programming language. This means that most of what you learned in MPR can be applied in the notebook. The notebook interface provides “cells” where one can input code. To run the code, click on a cell and press Shift+Enter.

1.1. A quick tour

Take a second to go through the tour of the notebook interface by clicking on “Help, User Interface Tour”. Also note that there is help available for a number of other things under that menu.

Now that you are familiar with the nomenclature, let’s run some code!

Evaluate the cell below to print out a message by clicking inside the cell and then pressing Shift + Enter

[1]:
for word in ['Hello', 'World']:
    print(word)
Hello
World
[2]:
a = 1

1.2. Math in text boxes

The text editor supports math in :math:LaTeX` <>`__ notation. You can double-click on a text box to see the codes used to enter it:

\[f(a)=\int_\infty^0 \frac{1}{a+2} \mathrm{d}a\]

Double-click on the formula above to see the code that produced it.

1.3. Special symbols in variable names

The notebook supports easy entry of special symbols in variable names. Simply type a backslash with the name of the symbol, then press tab to have it replaced by the symbol. For example:

Enter \alpha, then press tab. This will be replaced by α

[3]:
α = 1

1.4. SymPy

We need to import the SymPy module to get symbolic math capabilities.

[4]:
import sympy

We need to start the pretty-printer to get nicely typeset math

Note that this changes somewhat based on the version of sympy

[5]:
sympy.init_printing()

In order to do symbolic calculations, we need to create a symbol

[6]:
x = sympy.Symbol('x')
[7]:
x
[7]:
$$x$$

Sympy allows us to do many mathematical operations that would be tedious by hand. For instance, we can expand a polynomial:

[8]:
polynomial = (2*x + 3)**4
polynomial.expand()
[8]:
$$16 x^{4} + 96 x^{3} + 216 x^{2} + 216 x + 81$$

Notice what happened - we defined a new name called “polynomial” and then used the .expand() method to expand the polynomial. We can see all the methods associated with an object by typing its name and a dot then pressing “tab”.

Call up the list of methods for the polynomial variable by entering “.” and pressing tab at the end of the line in the cell below:

[9]:
polynomial
[9]:
$$\left(2 x + 3\right)^{4}$$

To get help about any method, we can type its name and append a ? at the end, then evaluate the cell

Obtain help about the .expand() method by evaluating the cell below:

[10]:
polynomial.expand()
[10]:
$$16 x^{4} + 96 x^{3} + 216 x^{2} + 216 x + 81$$

It is also possible to obtain help for a function by placing the cursor between the parentheses and pressing Shift+Tab

Of course, we can also factor polynomials:

[11]:
(x**2 + 2*x + 1).factor()
[11]:
$$\left(x + 1\right)^{2}$$

1.5. Calculus

Sympy knows how to integrate and differentiate

[12]:
eq = sympy.tan(sympy.log(x**2 + 1))
[13]:
eq.diff(x)
[13]:
$$\frac{2 x \left(\tan^{2}{\left (\log{\left (x^{2} + 1 \right )} \right )} + 1\right)}{x^{2} + 1}$$
[14]:
polynomial.diff(x) # First derivative
[14]:
$$8 \left(2 x + 3\right)^{3}$$
[15]:
polynomial.diff(x, 2) # Second derivative
[15]:
$$48 \left(2 x + 3\right)^{2}$$
[16]:
polynomial.integrate(x) # indefinite integral - note no constant of integration is added
[16]:
$$\frac{16 x^{5}}{5} + 24 x^{4} + 72 x^{3} + 108 x^{2} + 81 x$$
[17]:
polynomial.integrate((x, 1, 2)) # Note that integrate takes one argument which is a tuple for the definite integral
[17]:
$$\frac{6841}{5}$$

1.6. Limits

We can evaluate limits using SymPy, even for “interesting” limits where we would need L’Hopital’s rule

[18]:
badeq = (2*sympy.sin(x) - sympy.sin(2*x))/(x - sympy.sin(x))
[19]:
badeq
[19]:
$$\frac{2 \sin{\left (x \right )} - \sin{\left (2 x \right )}}{x - \sin{\left (x \right )}}$$
[20]:
a = sympy.symbols('a')
[21]:
lim = sympy.limit(badeq, x, a)
[22]:
lim
[22]:
$$- \frac{- 2 \sin{\left (a \right )} + \sin{\left (2 a \right )}}{a - \sin{\left (a \right )}}$$
[23]:
lim.subs(sympy.sin(a), 1)
[23]:
$$- \frac{\sin{\left (2 a \right )} - 2}{a - 1}$$

1.7. Approximation

SymPy has built-in support for taylor series expansion

[24]:
nonlinear_expression = sympy.sin(x)
sympy.series(nonlinear_expression, x, 2, 7) # taylor expansion in terms of the x variable, around x=2, first order.
[24]:
$$\sin{\left (2 \right )} + \left(x - 2\right) \cos{\left (2 \right )} - \frac{\left(x - 2\right)^{2} \sin{\left (2 \right )}}{2} - \frac{\left(x - 2\right)^{3} \cos{\left (2 \right )}}{6} + \frac{\left(x - 2\right)^{4} \sin{\left (2 \right )}}{24} + \frac{\left(x - 2\right)^{5} \cos{\left (2 \right )}}{120} - \frac{\left(x - 2\right)^{6} \sin{\left (2 \right )}}{720} + O\left(\left(x - 2\right)^{7}; x\rightarrow 2\right)$$

To remove the order term use .removeO()

[25]:
temp = sympy.series(nonlinear_expression, x, 2, 2)
temp.removeO()
[25]:
$$\left(x - 2\right) \cos{\left (2 \right )} + \sin{\left (2 \right )}$$

You will also notice that SymPy’s default behaviour is to retain exact representations of certain numbers:

[26]:
number = sympy.sqrt(2)*sympy.pi
number
[26]:
$$\sqrt{2} \pi$$

To convert the exact representations above to an approximate floating point representations, use one of these methods. sympy.N works with complicated expressions containing variables as well. float will return a normal Python float and is useful when interacting with non-sympy programs.

[27]:
sympy.N(number*x)
[27]:
$$4.44288293815837 x$$
[28]:
float(number)
[28]:
$$4.442882938158366$$

1.8. Solving equations

Sympy can help us solve manipulate equations using the solve function. Like many solving functions, it finds zeros of a function, so we have to rewrite equalities to be equal to zero,

\begin{align} 2x^2 + 2 &= 4 \\ 2x^2 + 2 - 4 &= 0\end{align}
[29]:
sympy.plot(x**2 + 1)
<Figure size 640x480 with 1 Axes>
[29]:
<sympy.plotting.plot.Plot at 0x10b531438>
[30]:
solutions = sympy.solve(2*x**2 + 2 - 4)
solutions
[30]:
$$\left [ -1, \quad 1\right ]$$
[31]:
solutions[0]
[31]:
$$-1$$

We can also use sympy.Eq to construct equations

[32]:
equation = sympy.Eq(2*x**2 + 2, 4)
equation
[32]:
$$2 x^{2} + 2 = 4$$

The roots function will give us the multiplicity of the roots as well.

[33]:
sympy.roots(equation)
[33]:
$$\left \{ -1 : 1, \quad 1 : 1\right \}$$

The results are given as a dictionary. If this is not familiar to you, have a look in the Extra Python notebook.

We can also solve systems of equations by passing a list of equations to solve and asking for a list of variables to solve for

[34]:
x, y = sympy.symbols('x, y')
sympy.solve([x + y - 2,
             x - y - 0], [x, y])
[34]:
$$\left \{ x : 1, \quad y : 1\right \}$$

This even works with symbolic variables in the equations

[35]:
a, b, c = sympy.var('a, b, c')
solution = sympy.solve([a*x + b*y - 2,
                        a*x - b*y - c], [x, y])
solution
[35]:
$$\left \{ x : \frac{c + 2}{2 a}, \quad y : \frac{- c + 2}{2 b}\right \}$$
[ ]: