diff --git a/src/main/java/com/thealgorithms/matrix/LUDecomposition.java b/src/main/java/com/thealgorithms/matrix/LUDecomposition.java new file mode 100644 index 000000000..e41aaa201 --- /dev/null +++ b/src/main/java/com/thealgorithms/matrix/LUDecomposition.java @@ -0,0 +1,88 @@ +package com.thealgorithms.matrix; + +/** + * LU Decomposition algorithm + * -------------------------- + * Decomposes a square matrix a into a product of two matrices: + * a = l * u + * where: + * - l is a lower triangular matrix with 1s on its diagonal + * - u is an upper triangular matrix + * + * Reference: + * https://en.wikipedia.org/wiki/lu_decomposition + */ +public final class LUDecomposition { + + private LUDecomposition() { + } + + /** + * A helper class to store both l and u matrices + */ + public static class LU { + double[][] l; + double[][] u; + + LU(double[][] l, double[][] u) { + this.l = l; + this.u = u; + } + } + + /** + * Performs LU Decomposition on a square matrix a + * + * @param a input square matrix + * @return LU object containing l and u matrices + */ + public static LU decompose(double[][] a) { + int n = a.length; + double[][] l = new double[n][n]; + double[][] u = new double[n][n]; + + for (int i = 0; i < n; i++) { + // upper triangular matrix + for (int k = i; k < n; k++) { + double sum = 0; + for (int j = 0; j < i; j++) { + sum += l[i][j] * u[j][k]; + } + u[i][k] = a[i][k] - sum; + } + + // lower triangular matrix + for (int k = i; k < n; k++) { + if (i == k) { + l[i][i] = 1; // diagonal as 1 + } else { + double sum = 0; + for (int j = 0; j < i; j++) { + sum += l[k][j] * u[j][i]; + } + l[k][i] = (a[k][i] - sum) / u[i][i]; + } + } + } + + return new LU(l, u); + } + + /** + * Utility function to print a matrix + * + * @param m matrix to print + */ + public static void printMatrix(double[][] m) { + for (double[] row : m) { + System.out.print("["); + for (int j = 0; j < row.length; j++) { + System.out.printf("%7.3f", row[j]); + if (j < row.length - 1) { + System.out.print(", "); + } + } + System.out.println("]"); + } + } +} diff --git a/src/test/java/com/thealgorithms/matrix/LUDecompositionTest.java b/src/test/java/com/thealgorithms/matrix/LUDecompositionTest.java new file mode 100644 index 000000000..d3cc6d64b --- /dev/null +++ b/src/test/java/com/thealgorithms/matrix/LUDecompositionTest.java @@ -0,0 +1,40 @@ +package com.thealgorithms.matrix; + +import static org.junit.jupiter.api.Assertions.assertArrayEquals; + +import org.junit.jupiter.api.Test; + +public class LUDecompositionTest { + + @Test + public void testLUDecomposition() { + double[][] a = {{4, 3}, {6, 3}}; + + // Perform LU decomposition + LUDecomposition.LU lu = LUDecomposition.decompose(a); + double[][] l = lu.l; + double[][] u = lu.u; + + // Reconstruct a from l and u + double[][] reconstructed = multiplyMatrices(l, u); + + // Assert that reconstructed matrix matches original a + for (int i = 0; i < a.length; i++) { + assertArrayEquals(a[i], reconstructed[i], 1e-9); + } + } + + // Helper method to multiply two matrices + private double[][] multiplyMatrices(double[][] a, double[][] b) { + int n = a.length; + double[][] c = new double[n][n]; + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + for (int k = 0; k < n; k++) { + c[i][j] += a[i][k] * b[k][j]; + } + } + } + return c; + } +}