import random as rnd
import time
import concurrent.futures
def gen_square_matrix(size):
    return [[rnd.randint(1, 100) for _ in range(size)] for _ in range(size)]
# Параллельное вычисление определителя
def parallel_det(matrix, num_threads):
    n = len(matrix)
    # Определитель
    det_value = 1
    def process_row(i, j):
        factor = matrix[j][i] / matrix[i][i]
        for k in range(i, n):
            matrix[j][k] -= factor * matrix[i][k]
    for i in range(n):
        if matrix[i][i] == 0:
            for j in range(i + 1, n):
                if matrix[j][i] != 0:
                    matrix[i], matrix[j] = matrix[j], matrix[i]
                    det_value *= -1
                    break
                else:
                    return 0
        # Параллельное вычисление
        with concurrent.futures.ThreadPoolExecutor(max_workers=num_threads) as executor:
            futures = [
                executor.submit(process_row, i, j) for j in range(i + 1, n)
            ]
            concurrent.futures.wait(futures)
        # Обновление определителя
        det_value *= matrix[i][i]
    return det_value
    
if __name__ == "__main__":
    sizes = [100, 300, 500]
    num_threads = [1, 5, 8]
    for size in sizes:
        matrix = gen_square_matrix(size)
        for threads in num_threads:
            start_time = time.time()
            parallel_det(matrix, threads)
            end_time = time.time()
            print(f"Параллельное вычисление определителя.\tРазмер: {size}, {threads} потоков\t|\t {end_time - start_time}")
        print("=" * 100)