в этом коде в таблице вместо колонки Count from Polynomial выводить то, что посчитал mpi, на графике так же заменить верхную половину на mpi, directly counted оставить

from mpi4py import MPI
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd

def create_jacobi_matrix(n, c1, c2, b):
    c = np.array([c1 if i % 2 == 0 else c2 for i in range(n)])
    b = np.full(n-1, b)
    return np.diag(c) + np.diag(b, k=1) + np.diag(b, k=-1)

def compute_eigenvalues(matrix):
    eigenvalues, _ = np.linalg.eig(matrix)
    return np.sort(eigenvalues)

def eigenvalue_intervals(eigenvalues, n_intervals):
    min_eigenvalue = np.min(eigenvalues)
    max_eigenvalue = np.max(eigenvalues)
    step = (max_eigenvalue - min_eigenvalue) / n_intervals
    return min_eigenvalue - step, max_eigenvalue + step, step

def find_eigenvalue_counts_mpi(eigenvalues, interval_start, interval_end, step):
    interval_edges = np.arange(interval_start, interval_end, step)
    counts = np.zeros(len(interval_edges) - 1, dtype=int)

    comm = MPI.COMM_WORLD
    rank = comm.Get_rank()
    size = comm.Get_size()

    # Determine the ranges each process will handle
    local_n = len(interval_edges) // size
    start = rank * local_n
    end = start + local_n if rank != size - 1 else len(interval_edges) - 1

    for i in range(start, end):
        left = interval_edges[i]
        right = interval_edges[i + 1]
        counts[i] = np.sum((eigenvalues >= left) & (eigenvalues < right))

    # Gathering counts from all processes
    total_counts = None
    if rank == 0:
        total_counts = np.zeros_like(counts)
    comm.Reduce(sendbuf=counts, recvbuf=total_counts, op=MPI.SUM, root=0)

    return total_counts, interval_edges

def plot_eigenvalue_histogram(counts1, counts2, edges):
    plt.figure(figsize=(12, 6))
    bar_width = edges[1] - edges[0]
    centres = (edges[:-1] + edges[1:]) / 2
    plt.bar(centres, counts1, width=bar_width, color='peachpuff', edgecolor='k', label='From polynomial')
    plt.bar(centres, -np.array(counts2), width=bar_width, color='mediumpurple', edgecolor='k', label='Directly counted')
    plt.xlabel('Interval')
    plt.ylabel('Count of Eigenvalues')
    plt.title('Eigenvalue Counts in Intervals')
    plt.xticks(edges, rotation=45)
    plt.grid(axis='x', linestyle='--', alpha=0.7)
    plt.legend()
    plt.show()

def create_table(interval_edges, counts1, counts2):
    intervals = [f"({interval_edges[i]:.2f}, {interval_edges[i+1]:.2f})" for i in range(len(interval_edges) - 1)]
    data = {
        'Interval': intervals,
        'Count from Polynomial': counts1,
        'Direct Count': counts2
    }
    df = pd.DataFrame(data)
    print(df)

def main():
    # Параметры для матрицы Якоби
    n = 100
    c1 = 12
    c2 = 7
    b = 15

    A = create_jacobi_matrix(n, c1, c2, b)
    eigenvalues = compute_eigenvalues(A)

    left, right, step = eigenvalue_intervals(eigenvalues, 20)

    # Perform MPI computation
    counts_direct, interval_edges = find_eigenvalue_counts_mpi(eigenvalues, left, right, step)

    # Count using polynomial as previously done (unparallelized part)
    counts_by_polynomial = np.diff(np.searchsorted(eigenvalues, interval_edges))

    # Rank 0 generates the output and plots
    comm = MPI.COMM_WORLD
    if comm.Get_rank() == 0:
        plot_eigenvalue_histogram(counts_by_polynomial, counts_direct, interval_edges)
        create_table(interval_edges, counts_by_polynomial, counts_direct)
        print(compute_eigenvalues(A))

if __name__ == "__main__":
    main()