diff --git a/borschevskaya_anna_lab_6/README.md b/borschevskaya_anna_lab_6/README.md new file mode 100644 index 0000000..4869b36 --- /dev/null +++ b/borschevskaya_anna_lab_6/README.md @@ -0,0 +1,26 @@ +# Отчет. Лабораторная работа 6 + +## Описание +В рамках лабораторной работы была реализована программа, которая производит вычисление детерминанта матрицы +с применением последовательного и паралелльного алгоритма. + +В качестве способа нахождения определителя матрицы был выбран алгоритм нахождения путем разложения по столбцу (строке). +При данном подходе определитель находится как сумма произведений элементов выбранной строки на их алгебраические дополнения. +Была произведена небольшая оптимизация алгоритма - выбор строки для разложения основывался на количестве нулевых элементов в ней. +Чем больше нулей в строке - тем меньше будет выполняться подзадач в алгоритме. + +Результаты представлены на следующих изображениях: + +![results](images/results.PNG) + +Как мы можем увидеть, производительность паралелльной реализации на маленьких матрицах ниже, чем у последовательного подхода, +это связано с дополнительными действиями по созданию и управлению потоками. Однако с увеличением размера матриц мы можем +наблюдать увеличение производительности. Но на больших размерах (от 12х12) матриц алгоритм становится довольно медленным +вне зависимости от применения многопоточности. + +## Как запустить +Необходимо иметь установленную JDK 21. Можно воспользоваться встроенным в нее компилятором (javac), а затем запустить исполняемый файл (java) +или запускать из среды разработки. + +## Видео-отчет +Работоспособность лабораторной работы можно оценить в следующем [видео](https://disk.yandex.ru/i/-sWDKdW3Q-vbHg). \ No newline at end of file diff --git a/borschevskaya_anna_lab_6/images/results.PNG b/borschevskaya_anna_lab_6/images/results.PNG new file mode 100644 index 0000000..df739dd Binary files /dev/null and b/borschevskaya_anna_lab_6/images/results.PNG differ diff --git a/borschevskaya_anna_lab_6/matrix-det/.gitignore b/borschevskaya_anna_lab_6/matrix-det/.gitignore new file mode 100644 index 0000000..5ff6309 --- /dev/null +++ b/borschevskaya_anna_lab_6/matrix-det/.gitignore @@ -0,0 +1,38 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/borschevskaya_anna_lab_6/matrix-det/pom.xml b/borschevskaya_anna_lab_6/matrix-det/pom.xml new file mode 100644 index 0000000..f034aac --- /dev/null +++ b/borschevskaya_anna_lab_6/matrix-det/pom.xml @@ -0,0 +1,17 @@ + + + 4.0.0 + + ru.uni.rvip + matrix-det + 1.0-SNAPSHOT + + + 21 + 21 + UTF-8 + + + \ No newline at end of file diff --git a/borschevskaya_anna_lab_6/matrix-det/src/main/java/ru/uni/rvip/Main.java b/borschevskaya_anna_lab_6/matrix-det/src/main/java/ru/uni/rvip/Main.java new file mode 100644 index 0000000..db3f997 --- /dev/null +++ b/borschevskaya_anna_lab_6/matrix-det/src/main/java/ru/uni/rvip/Main.java @@ -0,0 +1,155 @@ +package ru.uni.rvip; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.Random; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.stream.IntStream; + +public class Main { + + private static final ExecutorService executor = Executors.newFixedThreadPool(8); + + public static void main(String[] args) { + int size = 12; + + for (int i = 5; i <= size; i += 2) { + System.out.printf("Размер матриц %dx%d\n", i, i); + + var matrix = createRandomMatrix(i); + + var startTime = System.currentTimeMillis(); + var result = findDeterminant(matrix); + var timeOfExecution = System.currentTimeMillis() - startTime; + System.out.printf("Детерминант матрицы = %f\n", result); + System.out.printf("Время нахождения детерминанта с помощью последовательного алгоритма: %d ms\n", timeOfExecution); + + startTime = System.currentTimeMillis(); + findDeterminantParallel(matrix); + timeOfExecution = System.currentTimeMillis() - startTime; + System.out.printf("Время нахождения детерминанта с помощью параллельного алгоритма: %d ms\n", timeOfExecution); + } + executor.shutdown(); + } + + private static double findDeterminant(double[][] matrix) { + int rows = matrix.length; + int n = matrix[0].length; + if (rows == n && rows == 1) { + return matrix[0][0]; + } + if (rows == n && rows == 2) { + return matrix[0][0] * matrix[1][1] - matrix[0][1] * matrix[1][0]; + } + + if (rows == n && rows == 3) { + return matrix[0][0] * matrix[1][1] * matrix[2][2] + matrix[0][1] * matrix[1][2] * matrix[2][0] + matrix[0][2] * matrix[1][0] * matrix[2][1] + - (matrix[0][2] * matrix[1][1] * matrix[2][0] + matrix[1][0] * matrix[0][1] * matrix[2][2] + matrix[0][0] * matrix[1][2] * matrix[2][1]); + } + double[][] temporary; + double det = 0; + // поиск наиболее подходящей строки + int indexWithMaxZeros = IntStream.range(0, matrix.length) + .boxed() + .max(Comparator.comparingInt(i -> + (int) Arrays.stream(matrix[i]).filter(x -> x == 0).count())) + .orElse(-1); + + double[] maxZerosCountRow = matrix[indexWithMaxZeros]; + + + for (int i = 0; i < n; i++) { + if (maxZerosCountRow[i] > 0) { + temporary = getSubmatrix(matrix, rows, n, i, indexWithMaxZeros); + det += maxZerosCountRow[i] * Math.pow(-1, i) * findDeterminant(temporary); + } + } + + return det; + } + + private static double findDeterminantParallel(double[][] matrix) { + int rows = matrix.length; + int n = matrix[0].length; + if (rows == n && rows == 1) { + return matrix[0][0]; + } + if (rows == n && rows == 2) { + return matrix[0][0] * matrix[1][1] - matrix[0][1] * matrix[1][0]; + } + if (rows == n && rows == 3) { + return matrix[0][0] * matrix[1][1] * matrix[2][2] + matrix[0][1] * matrix[1][2] * matrix[2][0] + matrix[0][2] * matrix[1][0] * matrix[2][1] + - (matrix[0][2] * matrix[1][1] * matrix[2][0] + matrix[1][0] * matrix[0][1] * matrix[2][2] + matrix[0][0] * matrix[1][2] * matrix[2][1]); + } + double det = 0; + // поиск наиболее подходящей строки + int indexWithMaxZeros = IntStream.range(0, matrix.length) + .boxed() + .max(Comparator.comparingInt(i -> + (int) Arrays.stream(matrix[i]).filter(x -> x == 0).count())) + .orElse(-1); + + double[] maxZerosCountRow = matrix[indexWithMaxZeros]; + var futures = new ArrayList>(); + for (int i = 0; i < n; i++) { + // нахождение подматрицы + final var finalRow = i; + + futures.add(executor.submit(() -> { + final var temporary = getSubmatrix(matrix, rows, n, finalRow, indexWithMaxZeros); + return maxZerosCountRow[finalRow] * Math.pow(-1, finalRow) * findDeterminant(temporary); + })); + } + + try { + for (var future : futures) { + det += future.get(); + } + } catch (InterruptedException | ExecutionException e) { + System.out.println("Возникла ошибка во время многопоточного нахождения определителя матрицы"); + return -1; + } + return det; + } + + private static double[][] getSubmatrix(double[][] matrix, int rows, int n, int col, int row) { + final var temporary = new double[rows - 1][n - 1]; + for (int j = 0; j < rows; j++) { + if (j == row) continue; + + for (int k = 0; k < n; k++) { + if (k == col) continue; + + //temporary[j][k] = matrix[j][k]; + temporary[j < row ? j : j - 1][k < col ? k : k - 1] = matrix[j][k]; + } + } + return temporary; + } + + private static double[][] createRandomMatrix(Integer size) { + var matrix = new double[size][size]; + var random = new Random(); + for (var i = 0; i < size; i++) { + for (var j = 0; j < size; j++) { + matrix[i][j] = random.nextInt(50); + } + } + return matrix; + } + + private static void printMatrix(double[][] matrix) { + for (double[] ints : matrix) { + for (double elem : ints) { + System.out.printf("%5f\t", elem); + } + System.out.println(); + } + } +} + +