import numpy as np
import matplotlib.pyplot as plt
from js import document
from pyodide.ffi import create_proxy, to_js

Exercise 1 Linear algebra in Python

The goal of this first exercise is to get familiar with linear algebra operations in Python and to the use of the web inerface that we will use for the exercises.

This page contains a series of codes that you can edit and run. It might take some time to load (especially the first time you load it). The functionalities have been tested with Chrome and Firefox.

To run the code in each editor box, you can either press shift+enter or click on the green run button that appears on the right corner of the editor when you hover over it.

The last line of the code can be used to display the outputs of the execution (workspace on the right side of the page), by just writing the name of the variable. print(var) can alternatively by used at any place within the code. Only the last output will be displayed on the workspace. At anytime, you can click on the clear buttons to clean the workspace.

When defining functions, you can use two space characters to create tabulations (the tab key should be kept for navigating the web interface).

This first exercise only requires you to run the codes, to display the results, to analyze these outputs, and to modify the examples in order to get familiar with the use of matrices, vectors and associated linear algebra operations in Python. Some of the exercises require the previous codes to have been run once, in order to define the variables.

1. Test your first Python code

print('Hello world!')

2. Create and display a random 3D vector

vec1 = np.array([3., 4.]) # create a vector with given entries
vec2 = np.random.randn(3) # create a random vector
vec1, vec2

3. Create and display a random 3D matrix

mat1 = np.array([[1.,2.],[2., 10.]]) # create a matrix with given entries
mat2 = np.random.randn(3,3) # create a random 3x3 matrix
mat1, mat2

4. Multiplication and product operations

prod1 = mat1 @ mat1 # multiply mat1 by mat1
prod2 = mat1 * mat1 # elementwise product between mat1 by mat1
prod3 = mat1 @ vec1 # multiply mat1 by vec1
prod4a = vec2.T @ vec2 # dot product between vec2 and vec2
prod4b = vec2.dot(vec2) # dot product between vec2 and vec2
prod5 = np.outer(vec2, vec2) # Outer product between vec2 and vec2
prod4a,prod4b # Display two of the results

5. Reformatting and stacking of vectors and matrices

vec3 = np.random.randn(3)
# stack vec2 and vec3 to obtain a matrix of shape (2,3)
stacked1 = np.stack([vec2, vec3])
# stack mat2 and vec2 to obtain a matrix of shape (4,3)
concatenated1 = np.vstack([mat2, vec2[None]])
# stack mat2 and vec2 to obtain a matrix of shape (3,4)
concatenated2 = np.hstack([mat2, vec2[:,None]])
stacked1.shape # display the matrix dimension of stacked1

6. Inversion of a matrix

mat = np.diag([1., 1., 1.]) # set diagonal matrix
mat_inv = np.linalg.inv(mat) # matrix inversion
# Let's make it not invertible by changing the last entry to 0
mat[-1,-1] = 0.
# Let's now check if it is invertible (without inverting it)
is_invertible = np.linalg.det(mat) != 0.
# Pseudoinverses of mat
mat1_pinv = (mat.T @ mat).T @ mat # using (A.T @ A).T @ A
mat2_pinv = np.linalg.pinv(mat) # using np.linalg.pinv()
#Compare the two solutions
diff = np.linalg.norm(mat1_pinv - mat2_pinv, ord='fro')
is_invertible, diff # diff should be almost zero

7. Solve Ax=b using least squares

Complete the code below to compute x so that Ax=b.

Compute the error between Ax and b to see if your solution for x seems correct.

Modify the dimensions of A and b (including rectangular matrices for A) and observe the results.

A = np.random.randn(3,3)
b = np.random.randn(3)
# x = ...

8. Implementing a function

Implement a function fun(x) that inverts a matrix, by taking x as input (matrix) and by generating x_inv as output.

Can you make this function robust to the use of singular matrices? (see part 6 above as a hint)

x = np.arange(5) # create data
fig,ax = plt.subplots(figsize=(5,5))
ax.plot(x, x**2) # plot data in a graph
ax.set_xlabel(r'$x$')
ax.set_ylabel(r'$x^2$')
fig.tight_layout()
fig