# Лабораторная работа №6 - Параллельный поиск значения детерминанта матрицы **Кратко**: реализовать нахождение детерминанта квадратной матрицы. **Подробно**: в лабораторной работе требуется сделать два алгоритма: обычный и параллельный. В параллельном алгоритме предусмотреть ручное задание количества потоков, каждый из которых будет выполнять нахождение отдельной группы множителей. *** ## *Ход работы:* ### Обычный алгоритм SequentialDeterminant: ``` public static int SequentialDeterminant(int[][] matrix, int size) { if (size == 1) { return matrix[0][0]; } else if (size == 2) { return matrix[0][0] * matrix[1][1] - matrix[0][1] * matrix[1][0]; } else { int det = 0; for (int i = 0; i < size; i++) { var submatrix = Submatrix(matrix, i); det += Math.pow(-1, i) * matrix[0][i] * SequentialDeterminant(submatrix, submatrix.length); } return det; } } ``` Если матрица имеет размер более 2х2, то вычисление определителя происходит с рекурсивным вызовом с использованием миноров: ``` private static int[][] Submatrix(int[][] matrix, int excludeCol) { int size = matrix.length - 1; int[][] submatrix = new int[size][size]; int rowIndex = 0; for (int i = 0; i < matrix.length; i++) { if (i == 0) { continue; } int colIndex = 0; for (int j = 0; j < matrix[i].length; j++) { if (j == excludeCol) { continue; } submatrix[rowIndex][colIndex] = matrix[i][j]; colIndex++; } rowIndex++; } return submatrix; } ``` Метод создает подматрицу матрицы, исключая указанный столбец. ### Параллельный алгоритм ParallelDeterminant: ``` public static int ParallelDeterminant(int[][] matrix, int size, int threads) { if (size == 1) { return matrix[0][0]; } else if (size == 2) { return matrix[0][0] * matrix[1][1] - matrix[0][1] * matrix[1][0]; } else { int det = 0; ExecutorService executor = Executors.newFixedThreadPool(threads); List> tasks = new ArrayList<>(); for (int i = 0; i < size; i++) { var submatrix = Submatrix(matrix, i); int finalI = i; tasks.add(() -> (int) Math.pow(-1, finalI) * matrix[0][finalI] * SequentialDeterminant(submatrix, submatrix.length)); } try { List> futures = executor.invokeAll(tasks); for (Future future : futures) { det += future.get(); } } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); return -1; } finally { executor.shutdown(); } return det; } } ``` Создается исполнительский сервис (ExecutorService) с фиксированным числом потоков. Создается список задач (tasks), где каждая задача представляет собой вычисление минора для соответствующего столбца. После запуска задач в пуле потоков, ожидаем завершения выполнения. Далее формируется конечный результат. ### Результат _На больших матрицах алгоритм работает очень долго_* ![](images/result.jpg "") * На матрице 6x6 последовательный алгоритм справился намного быстрее параллельного. * На матрице 9x9 уже параллельный алгоритм справляется быстрее. * На матрице 12x12 параллельный алгоритм тоже лидирует.