Skip to article frontmatterSkip to article content

License: CC-BY-NC-SA 4.0

Author: Murilo M. Marinho (murilo.marinho@manchester.ac.uk)

Pre-requisites

The user of this notebook is expected to have prior knowledge in

I found an issue

Thank you! Please report it at https://github.com/MarinhoLab/OpenExecutableBooksRobotics/issues

Latex Macros

\providecommand{\myvec}[1]{{\mathbf{\boldsymbol{{#1}}}}} \providecommand{\mymatrix}[1]{{\mathbf{\boldsymbol{{#1}}}}}

\providecommand{\myvec}[1]{{\mathbf{\boldsymbol{{#1}}}}}
\providecommand{\mymatrix}[1]{{\mathbf{\boldsymbol{{#1}}}}}

A quick Python refresher

Variable assignment

Let

a10,b5.a\triangleq 10,b\triangleq 5.

We can replicate the above in Python with

a = 10
b = 5

Output variables

Variables can be output using print. For example, for aa

print(a)
10

Output text and variables using f-strings

To output aa and bb within a string, we can use print and f-strings as follows

print(f'The value of a = {a} and b = {b}.')
The value of a = 10 and b = 5.

Basic Arithmetics

Basic mathematical operations are trivially performed as follows.

Sum
c=a+b.c = a + b.
c = a + b

print(f'c={c}')
c=15

Subtraction
c=ab.c = a - b.
c = a - b

print(f'c={c}')
c=5
Multiplication
c=abc=ab
c = a * b

print(f'c={c}')
c=50
Division
c=abc = \frac{a}{b}
c = a / b

print(f'c={c}')
c=2.0

Exponentiation

c=abc = a^{b}
c = a ** b

print(f'c={c}')
c=100000

Math functions

For the following functions, we will need Python’s built-in math module.

from math import sqrt, exp, log, pi, sin, cos, tan

Square root

c=ac = \sqrt{a}
c = sqrt(a)

n-th root

The nth root,

c=an,nN,c= \sqrt[n]{a}, n \in \mathbb{N},

does not seem to have a shorthanded version in Python, but can computed through simple properties such as

c=an=a1n=eln(a)n.c = \sqrt[n]{a} = a^{\frac{1}{n}} = e^{\frac{ln(a)}{n}}.

For example, suppose that

n=3.n = 3.

Then,

n=3

and we can calculate the n-th root like so

# n-th root using fractional exponent. Might be easier but most languages do not support a similar syntax
c = a ** (1/n)

print(f'c={c}')
c=2.154434690031884

or like so

c = exp(log(a)/n)

print(f'c={c}')
c=2.154434690031884

and both should output the same value.

Trigonometric functions

ϕ=π4,\phi = \frac{\pi}{4},
sϕ=sin(ϕ),s_{\phi} = \sin \left( \phi \right),
cϕ=cos(ϕ),c_{\phi} = \cos \left( \phi \right),
tϕ=tan(ϕ).t_{\phi} = \tan \left( \phi \right).
phi = pi/4.0
s_phi = sin(phi)
c_phi = cos(phi)
t_phi = tan(phi)

print(f'phi={phi}')
print(f's_phi={s_phi}')
print(f'c_phi={c_phi}')
print(f't_phi={t_phi}')
phi=0.7853981633974483
s_phi=0.7071067811865475
c_phi=0.7071067811865476
t_phi=0.9999999999999999

Linear Algebra with Numpy

Installing the library

Just in case numpy is not already installed, we can install it with the following command. Nothing will happen if the library is already installed.

%%capture
%pip install numpy 
%pip install numpy --break-system-packages

Importing the library

import numpy as np

Instantiating vectors

A row vector can be instanteated from a list of list. For instance, for

v=[12],\myvec{v} = \left[\begin{array}{ccc} 1 & 2 \end{array}\right],

we have

# Note the double [[]] to instanteate a vector with explicit row shape.
v = np.array([[1, 2]])

print(f'v={v}')
v=[[1 2]]

A column vector can be instanted from a list of singleton lists. For instance, for

u=[12],\myvec{u} = \left[\begin{array}{ccc} 1 \\ 2 \end{array}\right],

we have

# Note that each row is defined by a single element within a [], while the whole vector is within an external []
u = np.array([[1],
              [2]])

print(f'u={u}')
u=[[1]
 [2]]

Dot product

c=<u,u>\myvec{c} = <\myvec{u},\myvec{u}>
c = np.vdot(u,u)

print(f'c={c}')
c=5

Cross product

Cross product is defined for vectors in R3\mathbb{R}^3.

For example, for

u3=[123],\myvec{u}_3 = \left[\begin{array}{ccc} 1 \\ 2 \\ 3 \end{array}\right],

and

v3=[456],\myvec{v}_3 = \left[\begin{array}{ccc} 4 \\ 5 \\ 6 \end{array}\right],

we can obtain the cross product

c=u3×v3\myvec{c} = \myvec{u}_3 \times \myvec{v}_3
u3 = np.array([[1, 2, 3]])
v3 = np.array([[4, 5, 6]])

c = np.cross(u3,v3)

print(f'c={c}')
c=[[-3  6 -3]]

Euclidean norm

c=u\myvec{c} = ||\myvec{u}||
Note that the function is np.linalg.norm, as the norm calculation is within the module linalg.
c = np.linalg.norm(u)

print(f'c={c}')
c=2.23606797749979

Instantiating matrices

For instance, suppose that we want to instanteate two real square matrices

A=[1234],B=[5678]\mymatrix{A} = \left[\begin{array}{ccc} 1 & 2 \\ 3 & 4 \end{array}\right], \mymatrix{B} = \left[\begin{array}{ccc} 5 & 6 \\ 7 & 8 \end{array}\right]
A = np.array([[1, 2], 
              [3, 4]])
B = np.array([[5, 6], 
              [7, 8]])

print(f'A={A},\n\nB={B}')
A=[[1 2]
 [3 4]],

B=[[5 6]
 [7 8]]

Transpose

C=AT\mymatrix{C} = \mymatrix{A}^T
C = A.T

print(f'C={C}')
C=[[1 3]
 [2 4]]

Sum

C=A+B\mymatrix{C} = \mymatrix{A} + \mymatrix{B}
C = A + B

print(f'C={C}')
C=[[ 6  8]
 [10 12]]

Subtraction

C=AB\mymatrix{C} = \mymatrix{A} - \mymatrix{B}
C = A - B

print(f'C={C}')
C=[[-4 -4]
 [-4 -4]]

Matrix multiplication

For instance,

C=ABC = AB

is implemented with

The matrix multiplication operator, @, is very unusual. Pay close attention. Mistaking this can be a major source of bugs and confusion.
C = A @ B # Alternatively C = np.matmul(A,B), but that is too verbose

print(f'C={C}')
C=[[19 22]
 [43 50]]

which will naturally work for the vectors we defined. For example

c=uv=[1224],\myvec{c} = \myvec{u}\myvec{v} = \left[\begin{array}{ccc} 1 & 2 \\ 2 & 4 \end{array}\right],

d=vu=5.\myvec{d} = \myvec{v}\myvec{u} = 5.
c = u @ v 
d = v @ u 

print(f'c={c},\n\nd={d}')
c=[[1 2]
 [2 4]],

d=[[5]]

and, of course, matrices and vectors

c=Au\myvec{c} = \myvec{A}\myvec{u}
We only use the "." sign to denote matrix multiplication when otherwise it would be difficult to read the equation.
c = A @ u 

print(f'c={c},\n')
c=[[ 5]
 [11]],

Diagonal matrices

Diagonal matrices get increasingly sparse with size, so it is important to have shorthanded commands for creating them. For instance, suppose that we have the following diagonal matrix

D=[100020003],\mymatrix{D} = \left[\begin{array}{ccc} 1 & 0 & 0 \\ 0 & 2 & 0 \\ 0 & 0 & 3 \end{array}\right] ,

this can be instanteated in numpy with

D = np.diag([1, 2, 3])

print(f'D={D}.')
D=[[1 0 0]
 [0 2 0]
 [0 0 3]].

Identity matrix

Among frequently used diagonal matrices, the identity matrix appears frequently. For instance,

I3=[100010001],\mymatrix{I}_3 = \left[\begin{array}{ccc} 1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \end{array}\right],

can be instanteated in numpy with

I_3 = np.eye(3)

print(f'I_3={I_3}.')
I_3=[[1. 0. 0.]
 [0. 1. 0.]
 [0. 0. 1.]].

Zero matrix

Another frequently used matrix is the zero matrix. For instance,

O3=[000000000],\mymatrix{O}_3 = \left[\begin{array}{ccc} 0 & 0 & 0 \\ 0 & 0 & 0 \\ 0 & 0 & 0 \end{array}\right],
The np.zeros function takes a tuple to generate a properly sized matrix. Do not confuse it with np.eye that accepts a scalar.
O_3 = np.zeros((3,3))

print(f'O_3={O_3}.')
O_3=[[0. 0. 0.]
 [0. 0. 0.]
 [0. 0. 0.]].