DAS_2024_1/afanasev_dmitry_lab_6/FastDeterminantCalculator.java

119 lines
4.1 KiB
Java

import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class FastDeterminantCalculator {
public static void main(String[] args) {
int[] sizes = {100, 300, 500};
int[] threads = {1, 4, 8, 10};
for (int size : sizes) {
BigDecimal[][] matrix = generateMatrix(size);
for (int threadCount : threads) {
long start = System.currentTimeMillis();
BigDecimal determinant = calculateDeterminant(matrix, threadCount);
long end = System.currentTimeMillis();
System.out.printf("Matrix size: %dx%d, Threads: %d, Time: %d ms\n",
size, size, threadCount, (end - start));
}
}
}
public static BigDecimal[][] generateMatrix(int size) {
BigDecimal[][] matrix = new BigDecimal[size][size];
for (int i = 0; i < size; i++) {
BigDecimal rowSum = BigDecimal.ZERO;
for (int j = 0; j < size; j++) {
matrix[i][j] = BigDecimal.valueOf(Math.random() * 10);
if (i != j) {
rowSum = rowSum.add(matrix[i][j]);
}
}
matrix[i][i] = rowSum.add(BigDecimal.valueOf(Math.random() * 10 + 1));
}
return matrix;
}
public static BigDecimal calculateDeterminant(BigDecimal[][] matrix, int threadCount) {
int size = matrix.length;
BigDecimal[][] lu = new BigDecimal[size][size];
int[] permutations = new int[size];
ExecutorService executor = Executors.newFixedThreadPool(threadCount);
if (!luDecomposition(matrix, lu, permutations, executor)) {
executor.shutdown();
return BigDecimal.ZERO; // Матрица вырожденная
}
executor.shutdown();
BigDecimal determinant = BigDecimal.ONE;
for (int i = 0; i < size; i++) {
determinant = determinant.multiply(lu[i][i]);
if (permutations[i] != i) {
determinant = determinant.negate(); // Меняем знак при перестановке
}
}
return determinant;
}
public static boolean luDecomposition(BigDecimal[][] matrix, BigDecimal[][] lu, int[] permutations, ExecutorService executor) {
int size = matrix.length;
for (int i = 0; i < size; i++) {
System.arraycopy(matrix[i], 0, lu[i], 0, size);
permutations[i] = i;
}
for (int k = 0; k < size; k++) {
int pivot = k;
for (int i = k + 1; i < size; i++) {
if (lu[i][k].abs().compareTo(lu[pivot][k].abs()) > 0) {
pivot = i;
}
}
if (lu[pivot][k].abs().compareTo(BigDecimal.valueOf(1e-10)) < 0) {
return false;
}
if (pivot != k) {
BigDecimal[] temp = lu[k];
lu[k] = lu[pivot];
lu[pivot] = temp;
int tempPerm = permutations[k];
permutations[k] = permutations[pivot];
permutations[pivot] = tempPerm;
}
CountDownLatch latch = new CountDownLatch(size - k - 1);
for (int i = k + 1; i < size; i++) {
int row = i;
int finalK = k;
executor.submit(() -> {
MathContext mc = new MathContext(20, RoundingMode.HALF_UP);
lu[row][finalK] = lu[row][finalK].divide(lu[finalK][finalK], mc);
for (int j = finalK + 1; j < size; j++) {
lu[row][j] = lu[row][j].subtract(lu[row][finalK].multiply(lu[finalK][j], mc));
}
latch.countDown();
});
}
try {
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
return false;
}
}
return true;
}
}