import threading
#fix
import time
import random
import numpy as np
from concurrent.futures import ThreadPoolExecutor

def gaussian_determinant(matrix):
    n = len(matrix)
    mat = [row[:] for row in matrix]

    for i in range(n):
        max_row = max(range(i, n), key=lambda r: abs(mat[r][i]))
        mat[i], mat[max_row] = mat[max_row], mat[i]

        if mat[i][i] == 0:
            return 0

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

    det = 1
    for i in range(n):
        det *= mat[i][i]
    return det

def parallel_determinant(matrix, num_threads=4):
    n = len(matrix)
    result = []
    def worker(start_row, end_row):
        partial_det = 1
        for i in range(start_row, end_row):
            partial_det *= matrix[i][i]
        result.append(partial_det)

    with ThreadPoolExecutor(max_workers=num_threads) as executor:
        rows_per_thread = n // num_threads
        futures = [executor.submit(worker, i * rows_per_thread, (i + 1) * rows_per_thread) for i in range(num_threads)]
        for future in futures:
            future.result()

    return sum(result)

def generate_matrix(size):
    return [[random.randint(1, 10) for _ in range(size)] for _ in range(size)]

matrix_sizes = [100, 300, 500]
num_threads = 4

for size in matrix_sizes:
    print(f"\nБенчмарки для матрицы {size}x{size}:")

    matrix = generate_matrix(size)

    start = time.time()
    det_seq = gaussian_determinant(matrix)
    end = time.time()
    print(f"Детерминант (последовательно, метод Гаусса): {det_seq}, время: {end - start:.5f} сек")

    start = time.time()
    det_par = parallel_determinant(matrix, num_threads=num_threads)
    end = time.time()
    print(f"Детерминант (параллельно): {det_par}, время: {end - start:.5f} сек")