Compare commits

...

2 Commits

5 changed files with 236 additions and 0 deletions

View File

@ -0,0 +1,26 @@
# Отчет. Лабораторная работа 6
## Описание
В рамках лабораторной работы была реализована программа, которая производит вычисление детерминанта матрицы
с применением последовательного и паралелльного алгоритма.
В качестве способа нахождения определителя матрицы был выбран алгоритм нахождения путем разложения по столбцу (строке).
При данном подходе определитель находится как сумма произведений элементов выбранной строки на их алгебраические дополнения.
Была произведена небольшая оптимизация алгоритма - выбор строки для разложения основывался на количестве нулевых элементов в ней.
Чем больше нулей в строке - тем меньше будет выполняться подзадач в алгоритме.
Результаты представлены на следующих изображениях:
![results](images/results.PNG)
Как мы можем увидеть, производительность паралелльной реализации на маленьких матрицах ниже, чем у последовательного подхода,
это связано с дополнительными действиями по созданию и управлению потоками. Однако с увеличением размера матриц мы можем
наблюдать увеличение производительности. Но на больших размерах (от 12х12) матриц алгоритм становится довольно медленным
вне зависимости от применения многопоточности.
## Как запустить
Необходимо иметь установленную JDK 21. Можно воспользоваться встроенным в нее компилятором (javac), а затем запустить исполняемый файл (java)
или запускать из среды разработки.
## Видео-отчет
Работоспособность лабораторной работы можно оценить в следующем [видео](https://disk.yandex.ru/i/-sWDKdW3Q-vbHg).

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

View File

@ -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

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>ru.uni.rvip</groupId>
<artifactId>matrix-det</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>

View File

@ -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<Future<Double>>();
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();
}
}
}