2024-10-20 16:30:42 +02:00
|
|
|
from linear_algebra_utils import LinearAlgebraUtils
|
|
|
|
|
from eigenvalue_methods import EigenvalueMethods
|
2024-10-20 17:47:37 +02:00
|
|
|
from matrix_generator import MatrixGenerator
|
2024-10-20 16:30:42 +02:00
|
|
|
|
|
|
|
|
class RichardsonMethod:
|
2024-10-20 17:47:37 +02:00
|
|
|
def __init__(self, A, b, size: int, x0=None, max_iterations=1000, tol=1e-5):
|
2024-10-20 16:30:42 +02:00
|
|
|
self.A = A
|
|
|
|
|
self.b = b
|
|
|
|
|
self.x0 = x0 if x0 is not None else [0.0] * len(b)
|
|
|
|
|
self.max_iterations = max_iterations
|
|
|
|
|
self.tol = tol
|
2024-10-20 17:47:37 +02:00
|
|
|
self.I = MatrixGenerator.generate_identity_matrix(size)
|
2024-10-20 16:30:42 +02:00
|
|
|
|
|
|
|
|
def solve(self):
|
|
|
|
|
x = self.x0[:]
|
|
|
|
|
lambda_min = EigenvalueMethods.inverse_power_method(self.A)
|
|
|
|
|
lambda_max = EigenvalueMethods.power_method(self.A)
|
|
|
|
|
|
|
|
|
|
if lambda_min < 0:
|
|
|
|
|
raise ValueError("Matrix A is not positive semi-definite.")
|
|
|
|
|
|
|
|
|
|
omega = 2 / (lambda_min + lambda_max)
|
|
|
|
|
|
|
|
|
|
for iteration in range(self.max_iterations):
|
|
|
|
|
Ax = LinearAlgebraUtils.matrix_vector_multiply(self.A, x)
|
2024-10-20 17:47:37 +02:00
|
|
|
residual = LinearAlgebraUtils.vector_vector_subtraction(self.b, Ax)
|
|
|
|
|
wA = LinearAlgebraUtils.matrix_scalar_multiply(self.A, omega)
|
|
|
|
|
IMinuswA = LinearAlgebraUtils.matrix_matrix_subtraction(self.I, wA)
|
|
|
|
|
if LinearAlgebraUtils.matrix_norm(IMinuswA) < 1:
|
2024-10-20 16:30:42 +02:00
|
|
|
print('Convergence achieved.')
|
|
|
|
|
return x
|
|
|
|
|
|
2024-10-20 17:47:37 +02:00
|
|
|
x = LinearAlgebraUtils.vector_vector_addition(x, LinearAlgebraUtils.scalar_matrix_multiply(omega, residual))
|
2024-10-20 16:30:42 +02:00
|
|
|
|
|
|
|
|
print('Maximum number of iterations reached without convergence.')
|
|
|
|
|
return x
|