2024-11-20 08:59:48 +00:00
|
|
|
import numpy as np
|
2024-11-20 09:43:25 +00:00
|
|
|
|
|
|
|
|
2024-11-20 09:36:33 +00:00
|
|
|
def lanczos(a: np.ndarray) -> tuple[list[float], list[float]]:
|
2024-11-20 08:59:48 +00:00
|
|
|
"""
|
|
|
|
Implements the Lanczos algorithm for a symmetric matrix.
|
|
|
|
|
|
|
|
Parameters:
|
|
|
|
-----------
|
|
|
|
matrix : numpy.ndarray
|
|
|
|
Symmetric matrix of size (n, n).
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
--------
|
|
|
|
alpha : [float]
|
|
|
|
List of diagonal elements of the resulting tridiagonal matrix.
|
|
|
|
beta : [float]
|
|
|
|
List of off-diagonal elements of the resulting tridiagonal matrix.
|
|
|
|
"""
|
2024-11-20 09:36:33 +00:00
|
|
|
n = a.shape[0]
|
|
|
|
v = np.zeros((n, n))
|
|
|
|
rng = np.random.default_rng()
|
|
|
|
v[:, 0] = rng.standard_normal(n)
|
|
|
|
v[:, 0] /= np.linalg.norm(v[:, 0])
|
2024-11-20 09:43:25 +00:00
|
|
|
alpha: list[float] = []
|
|
|
|
beta: list[float] = []
|
2024-11-20 08:59:48 +00:00
|
|
|
for j in range(n):
|
2024-11-20 09:36:33 +00:00
|
|
|
w = np.dot(a, v[:, j])
|
|
|
|
alpha.append(np.dot(w, v[:, j]))
|
2024-11-20 08:59:48 +00:00
|
|
|
if j == n - 1:
|
|
|
|
break
|
2024-11-20 09:36:33 +00:00
|
|
|
w -= alpha[j] * v[:, j]
|
2024-11-20 08:59:48 +00:00
|
|
|
if j > 0:
|
2024-11-20 09:36:33 +00:00
|
|
|
w -= beta[j - 1] * v[:, j - 1]
|
2024-11-20 08:59:48 +00:00
|
|
|
beta.append(np.linalg.norm(w))
|
2024-11-20 09:36:33 +00:00
|
|
|
v[:, j + 1] = w / beta[j]
|
2024-11-20 09:43:25 +00:00
|
|
|
return alpha, beta
|