Не получается нормальное распределение для вычислительной ошибки методов решения СЛАУ Гаусом и прогонкой

гистограммыСами методы решения СЛАУ работают корректно. Проверено при помощи slove. Но при попытке решить большое количество матриц некоторые вектора решений не сходятся с истинными, всвязи с чем не получается нормального распределения для погрешности. На приведенных гистограммах видно, что несколько значений очень большие - это и есть неверно решенные СЛАУ. Такие случаи были выведены и решены отдельно этими же функциями, однако решение было получено верное

import matplotlib.pyplot as plt
from datetime import datetime
from numpy.linalg import norm, solve
import typing as t


def calculate_relative_error(true_solution, computed_solution):
    n = len(true_solution)

    rmse = np.sqrt(np.sum((true_solution - computed_solution)**2))/n
    sup_norm = np.max(np.abs(true_solution - computed_solution))
    return rmse, sup_norm


def generate_symmetric_matrix(n):

    A = (np.random.random((n, n)).astype(np.float64) * 2 - 1).astype(np.float64)

    A = np.dot(A, A.T)
    A += np.eye(n, dtype=np.float64)

    while np.linalg.det(A) == 0:
        generate_symmetric_matrix(n)

    return A

def generate_random_matrix(n = 6 ):

    A = (np.random.random((n, n)).astype(np.float64) * 2 - 1).astype(np.float64)

    while np.linalg.det(A) == 0:
        generate_random_matrix(n)

    return A

def tridiagonal_matrix(n):

    main_diag = (np.random.random(n).astype(np.float64) * 2 - 1).astype(np.float64)
    sub_diag = (np.random.random(n-1).astype(np.float64) * 2 - 1).astype(np.float64)
    super_diag = (np.random.random(n-1).astype(np.float64) * 2 - 1).astype(np.float64)

    A = np.diag(main_diag) + np.diag(sub_diag, k=-1) + np.diag(super_diag, k=1)

    while np.linalg.det(A) == 0:
        tridiagonal_matrix(n=6)

    return A

def gauss(A, b, pivoting):
    n = len(b)

    a = np.hstack((A, b[:, np.newaxis])).astype(np.float64)

    for i in range(n):
        if pivoting:
            max_index = np.argmax(np.abs(a[i:, i])) + i
            a[[i, max_index]] = a[[max_index, i]]

        for j in range(i + 1, n):
            factor = a[j, i] / a[i, i]
            a[j, i:] -= factor * a[i, i:]

    x = np.zeros(n, dtype=np.float64)
    for i in range(n - 1, -1, -1):
        x[i] = (a[i, -1] - np.dot(a[i, i + 1:-1], x[i + 1:])) / a[i, i]
    return x


def thomas(A, b):
    gamma = [-A[0][1] / A[0][0]]
    beta = [b[0] / A[0][0]]

    n = len(b)
    x = [0] * n

    for i in range(1, n):
        if i != n - 1:
            gamma.append(-A[i][i + 1] / (A[i][i - 1] * gamma[i - 1] + A[i][i]))
        beta.append((b[i] - A[i][i - 1] * beta[i - 1]) / (A[i][i - 1] * gamma[i - 1] + A[i][i]))

    x[n - 1] = beta[n - 1]

    for i in range(n - 2, -1, -1):
        x[i] = gamma[i] * x[i + 1] + beta[i]

    return x






num_matrices = 1000
methods = ["gauss_no_pivoting", "thomas"] 


for method in methods:

    errors_rmse = []
    errors_sup_norm = []

    for _ in range(num_matrices):
        A_random = generate_random_matrix(6)
        A = A_random.copy()
        A_tridiagonal = tridiagonal_matrix(6)
        A_symmetric = generate_symmetric_matrix(6)

        b = np.array([1, 1, 1, 1, 1, 1]).astype(np.float64)
        x = np.linalg.solve(A_random, b)
        true_solution = gauss(A_random, b, pivoting=True)

        computed_solution = None
        if method == "gauss_no_pivoting":
            computed_solution = gauss(A_random.copy(), b.copy(), pivoting=False)
        elif method == "thomas":
            computed_solution = thomas(A_tridiagonal.copy(), b.copy())
       
        rmse, sup_norm = calculate_relative_error(true_solution, computed_solution)
        # if rmse <= 1e-3:
        #     print(A)
        #     print(true_solution)
        #     print(computed_solution)
        #     print(rmse)
        #     print(sup_norm)
        errors_rmse.append(rmse)
        errors_sup_norm.append(sup_norm)




    plt.figure(figsize=(10, 5))
    plt.subplot(1, 2, 1)
    plt.hist(errors_rmse, bins=20, color='blue', edgecolor='black')
    plt.title(f'{method} - RMSE Histogram')
    plt.xlabel('RMSE')
    plt.ylabel('Frequency')

    plt.subplot(1, 2, 2)
    plt.hist(errors_sup_norm, bins=20, color='green', edgecolor='black')
    plt.title(f'{method} - Sup Norm Histogram')
    plt.xlabel('Sup Norm')
    plt.ylabel('Frequency')

    plt.tight_layout()
    plt.show()

Ответы (0 шт):