2024-10-20 18:27:51 +02:00
|
|
|
import pytest
|
2024-10-20 16:30:42 +02:00
|
|
|
import numpy as np
|
|
|
|
|
from matrix_generator import MatrixGenerator
|
|
|
|
|
from richardson_method import RichardsonMethod
|
2024-12-28 13:24:58 +01:00
|
|
|
from threads import RichardsonMethodThreads
|
2024-10-25 17:01:19 +02:00
|
|
|
from processing_type import ProcessingType
|
2024-11-11 17:25:36 +01:00
|
|
|
from time_measurement import time_measurement, tests_time
|
2024-10-20 16:30:42 +02:00
|
|
|
|
2024-10-20 19:06:15 +02:00
|
|
|
def calculate_norm_numpy(I, w, A):
|
|
|
|
|
difference = I - w * A
|
|
|
|
|
norm = np.linalg.norm(difference)
|
|
|
|
|
return norm
|
|
|
|
|
|
|
|
|
|
def calculate_eigenvalues(A):
|
|
|
|
|
eigenvalues = np.linalg.eigvals(A)
|
|
|
|
|
lambda_min = np.min(eigenvalues)
|
|
|
|
|
lambda_max = np.max(eigenvalues)
|
|
|
|
|
return lambda_min, lambda_max
|
|
|
|
|
|
2024-12-05 20:16:13 +01:00
|
|
|
def calcualte_norm_from_matrix_numpy(A, n):
|
2024-10-20 19:06:15 +02:00
|
|
|
lambda_min, lambda_max = calculate_eigenvalues(A)
|
|
|
|
|
omega = 2 / (lambda_min + lambda_max)
|
|
|
|
|
I = np.eye(n)
|
2024-10-20 19:34:12 +02:00
|
|
|
return calculate_norm_numpy(I, omega, A)
|
|
|
|
|
|
2024-11-28 17:48:11 +01:00
|
|
|
@time_measurement(tests_time)
|
2024-12-05 20:16:13 +01:00
|
|
|
def solution_lib(A, b):
|
|
|
|
|
return np.linalg.solve(A, b)
|
|
|
|
|
|
2024-12-05 20:24:53 +01:00
|
|
|
@pytest.mark.parametrize("n", [
|
|
|
|
|
2,
|
|
|
|
|
5,
|
|
|
|
|
10,
|
|
|
|
|
50,
|
|
|
|
|
100,
|
|
|
|
|
300,
|
|
|
|
|
500,
|
|
|
|
|
750,
|
|
|
|
|
1000,
|
|
|
|
|
5000,
|
|
|
|
|
10000
|
|
|
|
|
])
|
|
|
|
|
@pytest.mark.parametrize("processing_type", [
|
2024-12-28 13:24:58 +01:00
|
|
|
# ProcessingType.SEQUENTIAL,
|
|
|
|
|
ProcessingType.THREADS#,
|
|
|
|
|
# ProcessingType.PROCESSES,
|
|
|
|
|
# ProcessingType.DISTRIBUTED_ARRAYS
|
2024-12-05 20:24:53 +01:00
|
|
|
])
|
|
|
|
|
@pytest.mark.parametrize("matrix_type", [
|
|
|
|
|
"spd",
|
|
|
|
|
"nemeth12",
|
|
|
|
|
"poli3"
|
|
|
|
|
])
|
2024-11-11 17:25:36 +01:00
|
|
|
def test_richardson_vs_cg(n: int, processing_type: ProcessingType, matrix_type: str, capsys):
|
|
|
|
|
print("matrix type: ", matrix_type)
|
|
|
|
|
print("matrix size: ", n if matrix_type == "spd" else "fixed")
|
2024-12-05 20:16:13 +01:00
|
|
|
tolerance = 8e-3
|
2024-11-17 17:44:45 +01:00
|
|
|
max_iterations=100
|
2024-11-11 17:25:36 +01:00
|
|
|
if matrix_type in ["nemeth12", "poli3"] and n != 2:
|
|
|
|
|
pytest.skip("Fixed matrix size for nemeth12 and poli3, skipping redundant runs.")
|
|
|
|
|
|
|
|
|
|
if matrix_type == "spd":
|
2024-12-05 20:16:13 +01:00
|
|
|
A, b, lambda_min, lambda_max = MatrixGenerator.generate_matrix_and_vector('spd', size=n)
|
2024-11-11 17:25:36 +01:00
|
|
|
elif matrix_type == "poli3":
|
2024-12-05 20:16:13 +01:00
|
|
|
A, b, lambda_min, lambda_max = MatrixGenerator.generate_matrix_and_vector('poli3')
|
2024-11-11 17:25:36 +01:00
|
|
|
elif matrix_type == "nemeth12":
|
2024-12-05 20:16:13 +01:00
|
|
|
A, b, lambda_min, lambda_max = MatrixGenerator.generate_matrix_and_vector('nemeth12')
|
2024-11-11 17:25:36 +01:00
|
|
|
else:
|
|
|
|
|
raise ValueError("Invalid matrix type specified. Choose 'spd', 'poli3', or 'nemeth12'.")
|
|
|
|
|
|
2024-10-31 17:50:21 +01:00
|
|
|
solution_richardson, info_richardson = None, None
|
2024-12-28 13:24:58 +01:00
|
|
|
|
|
|
|
|
if processing_type != ProcessingType.THREADS:
|
|
|
|
|
richardson_solver = RichardsonMethod(processing_type, A, b, lambda_min, lambda_max, max_iterations, size=A.shape[0], tol=1e-7)
|
|
|
|
|
with capsys.disabled():
|
|
|
|
|
solution_richardson, info_richardson = richardson_solver.solve()
|
|
|
|
|
else:
|
|
|
|
|
with capsys.disabled():
|
|
|
|
|
solution_richardson, info_richardson = RichardsonMethodThreads(A, b, lambda_min, lambda_max, max_iterations, tol=1e-7)
|
|
|
|
|
|
2024-10-31 17:50:21 +01:00
|
|
|
# Przechwytywanie wyjścia po solve
|
|
|
|
|
captured = capsys.readouterr()
|
|
|
|
|
print("Captured output:", captured.out)
|
2024-10-20 18:27:51 +02:00
|
|
|
|
2024-12-05 20:16:13 +01:00
|
|
|
solution = solution_lib(A,b)
|
2024-10-20 18:27:51 +02:00
|
|
|
|
2024-12-05 20:16:13 +01:00
|
|
|
assert_converged(solution_richardson, info_richardson, solution, tolerance, A, n)
|
2024-10-20 16:30:42 +02:00
|
|
|
|
2024-12-05 20:16:13 +01:00
|
|
|
def assert_converged(solution_richardson, info_richardson, solution, tolerance, A, n):
|
2024-10-20 19:34:12 +02:00
|
|
|
if info_richardson == "Richardson method for those values will NOT converge":
|
2024-12-05 20:16:13 +01:00
|
|
|
numpy_norm = calcualte_norm_from_matrix_numpy(A, n)
|
2024-10-20 19:34:12 +02:00
|
|
|
print("Numpy norm: ", numpy_norm, " Richardson norm: ", solution_richardson)
|
2024-12-05 20:16:13 +01:00
|
|
|
assert False, "Richardson did not converge"
|
2024-10-20 18:27:51 +02:00
|
|
|
else:
|
2024-12-05 20:16:13 +01:00
|
|
|
difference = np.linalg.norm(solution_richardson - solution)
|
|
|
|
|
print(f"Difference between Richardson and numpy solutions: {difference:.8f}")
|
2024-10-20 18:39:01 +02:00
|
|
|
if difference < tolerance:
|
2024-12-05 20:16:13 +01:00
|
|
|
print("Both Richardson and numpy method converged and calculated correct values.")
|
2024-11-17 17:44:45 +01:00
|
|
|
else:
|
2024-12-05 20:16:13 +01:00
|
|
|
print("Solution numpy:\n", solution)
|
2024-10-20 18:39:01 +02:00
|
|
|
print("Solution Richardson:\n", solution_richardson)
|
2024-10-20 18:27:51 +02:00
|
|
|
assert difference < tolerance, f"The solutions are different! Difference: {difference:.8f}"
|
|
|
|
|
|
2024-10-20 18:39:01 +02:00
|
|
|
if __name__ == "__main__":
|
2024-10-27 20:13:43 +01:00
|
|
|
pytest.main()
|