119 lines
4.1 KiB
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;
|
||
|
}
|
||
|
}
|