Generate matrices A A , with random Gaussian entries, B B , a Toeplitz matrix, where A∈Rn×m A ∈ R n × m and B∈Rm×m B ∈ R m × m , for n = 200, m = 500.
# Apply to each of the following three programs.
import numpy as np
from scipy.linalg import toeplitz
A = np.random.normal(loc=0, scale=1, size=(200,500))
B = toeplitz(list(range(1,501)))
Exercise 9.1: Matrix operations
Calculate A+A A + A , AAT A A T , ATA A T A and AB A B . Write a function that computes A(B−λI) A ( B − λ I ) for any λ λ .
AplusA = A + A
AAT = A @ A.T
ATA = A.T @ A
AB = A @ B
def compute(A, B, lambda_in):
return AB - A @ (lambda_in * np.eye(500))
Exercise 9.2: Solving a linear system
Generate a vector b b with m m entries and solve Bx=b B x = b .
b = np.random.random_integers(500, size=(500,1))
x = np.linalg.solve(B, b)
Exercise 9.3: Norms
Compute the Frobenius norm of A A : ∥A∥F ∥ A ∥ F and the infinity norm of B B : ∥B∥∞ ∥ B ∥ ∞ . Also find the largest and smallest singular values of B B .
# the Frobenius norm of A.
NA = np.linalg.norm(A, 'fro')
# the infinity norm of B.
NB = np.linalg.norm(B, np.inf)
u, s, vh = np.linalg.svd(B)
# find the largest singular value of B
max_value = max(s)
# find the smallest singular value of B
min_value = min(s)
Exercise 9.4: Power iteration
Generate a matrix Z Z , n×n n × n , with Gaussian entries, and use the power iteration to find the largest eigenvalue and corresponding eigenvector of Z Z . How many iterations are needed till convergence?
Optional: use the time.clock()
method to compare computation time when varying n n .
# power_iteration.py
import numpy as np
from time import clock
def power_iteration(Z):
'''
input: matrix Z;
output: the largest eigenvalue lambda_in,
the corresponding eigenvector u,
the number of iterations n,
the computation time t.
comment: the precision is 1e-4.
'''
start_time = clock()
u = np.random.normal(loc=5, scale=1, size=(200,1))
last_lambda = 1
lambda_in = 0
n = 0
while abs(lambda_in - last_lambda) > 0.0001:
last_lambda = lambda_in
v = Z @ u
lambda_in = max(np.fabs(v))
u = v / lambda_in
n += 1
end_time = clock()
t = end_time - start_time
return lambda_in, u, n, t
Z = np.random.normal(loc=5, scale=1, size=(200,200))
lambda_in, u, n, t = power_iteration(Z)
print("The number of iterations is %d." %(n))
print("The computation time is %f." %(t))
Output:
The number of iterations is 6.
The computation time is 0.002424.
Exercise 9.5: Singular values
Generate an n×n n × n matrix, denoted by C C , where each entry is 1 with probability p p and 0 otherwise. Use the linear algebra library of Scipy to compute the singular values of C C . What can you say about the relationship between n n , p p and the largest singular value?
# singular_values.py
import numpy as np
for p in range(0, 11, 1):
print("p = %f: " %(p / 10), end='')
C = np.random.binomial(1, p / 10, size=(200,200))
u, s, vh = np.linalg.svd(C)
max_value = max(s)
print("The largest singular value = %f." %(max_value))
Output:
p = 0.000000: The largest singular value = 0.000000.
p = 0.100000: The largest singular value = 21.242593.
p = 0.200000: The largest singular value = 40.142971.
p = 0.300000: The largest singular value = 60.467025.
p = 0.400000: The largest singular value = 80.575267.
p = 0.500000: The largest singular value = 100.071420.
p = 0.600000: The largest singular value = 120.163364.
p = 0.700000: The largest singular value = 139.919164.
p = 0.800000: The largest singular value = 160.677734.
p = 0.900000: The largest singular value = 179.996733.
p = 1.000000: The largest singular value = 200.000000.
It seems to satisfy such a relationship: the largest singular value =n×p = n × p .
Exercise 9.6: Nearest neighbor
Write a function that takes a value z z and an array A A and fi nds the element in A A that is closest to z z . The function should return the closest value, not index.
Hint: Use the built-in functionality of Numpy rather than writing code to find this value manually. In particular, use brackets and argmin
.
# nearest_neighbor.py
import numpy as np
def closest_value(A, z):
'''
input: matrix A,
value z.
output: the element in A that is closest to z.
'''
index = np.argmin(np.fabs(A - z))
row_A = len(A[0])
return A[index // row_A][index % row_A]
A = np.random.normal(loc=0, scale=1, size=(200,500))
z = 0.5
print("The element in A that is closest to z: %f." %(closest_value(A, z)))
Output:
The element in A that is closest to z: 0.500001.