From c90a5aedf2be4c95d83cb0b854d01f63cd44ca97 Mon Sep 17 00:00:00 2001 From: David Kong <21kondav@gmail.com> Date: Fri, 14 Mar 2025 13:59:41 -0400 Subject: [PATCH 1/4] Added a linear system solver --- .../com/thealgorithms/matrix/SolveSystem.java | 70 +++++++++++++++++++ .../thealgorithms/matrix/SolveSystemTest.java | 25 +++++++ 2 files changed, 95 insertions(+) create mode 100644 src/main/java/com/thealgorithms/matrix/SolveSystem.java create mode 100644 src/test/java/com/thealgorithms/matrix/SolveSystemTest.java diff --git a/src/main/java/com/thealgorithms/matrix/SolveSystem.java b/src/main/java/com/thealgorithms/matrix/SolveSystem.java new file mode 100644 index 000000000000..f0a392570fd9 --- /dev/null +++ b/src/main/java/com/thealgorithms/matrix/SolveSystem.java @@ -0,0 +1,70 @@ +package com.thealgorithms.matrix; + +/** + * This class implements an algorithm for solving a system of equations of the form Ax=b using gaussian elimination and back substitution. + * + * @link Gaussian Elimination Wiki + * @see InverseOfMatrix finds the full of inverse of a matrice, but is not required to solve a system. + */ +public class SolveSystem { + private SolveSystem() { + } + + /** + * Problem: Given a matrix A and vector b, solve the linear system Ax = b for the vector x.\ + *

+ * This variation uses @link Crout Reduction + * and partial pivoting to decompose the matrix. + * This OVERWRITES the input matrix to save on memory + * + * @param matrix - a square matrix of doubles + * @param constants - an array of constant + * @return solutions + */ + public static double[] solveSystem(double[][] matrix, double[] constants) { + final double TOL = 0.00000001; // tolerance for round off + for (int k = 0; k < matrix.length - 1; k++) { + // find the largest value in column (to avoid zero pivots) + double maxVal = Math.abs(matrix[k][k]); + int maxIdx = k; + for (int j = k + 1; j < matrix.length; j++) { + if (Math.abs(matrix[j][k]) > maxVal) { + maxVal = matrix[j][k]; + maxIdx = j; + } + } + if (Math.abs(maxVal) < TOL) // hope the matrix works out + continue; + // swap rows + double[] temp = matrix[k]; + matrix[k] = matrix[maxIdx]; + matrix[maxIdx] = temp; + double tempConst = constants[k]; + constants[k] = constants[maxIdx]; + constants[maxIdx] = tempConst; + + for (int i = k + 1; i < matrix.length; i++) { + // compute multipliers and save them in the column + + matrix[i][k] /= matrix[k][k]; + for (int j = k + 1; j < matrix.length; j++) { + matrix[i][j] -= matrix[i][k] * matrix[k][j]; + } + constants[i] -= matrix[i][k] * constants[k]; + } + } + // back substitution + double[] x = new double[constants.length]; + System.arraycopy(constants, 0, x, 0, constants.length); + for (int i = matrix.length - 1; i >= 0; i--) { + double sum = 0; + for (int j = i + 1; j < matrix.length; j++) sum += matrix[i][j] * x[j]; + x[i] = constants[i] - sum; + if (Math.abs(matrix[i][i]) > TOL) + x[i] /= matrix[i][i]; + else + throw new IllegalArgumentException("Matrix was found to be singular"); + } + return x; + } +} diff --git a/src/test/java/com/thealgorithms/matrix/SolveSystemTest.java b/src/test/java/com/thealgorithms/matrix/SolveSystemTest.java new file mode 100644 index 000000000000..dad8bdf80c18 --- /dev/null +++ b/src/test/java/com/thealgorithms/matrix/SolveSystemTest.java @@ -0,0 +1,25 @@ +package com.thealgorithms.matrix; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.assertArrayEquals; + +class SolveSystemTest { + + @ParameterizedTest + @MethodSource({"matrixGenerator"}) + void solveSystem(double[][] matrix, double[] constants, double[] solution) { + + double[] expected = SolveSystem.solveSystem(matrix, constants); + assertArrayEquals(expected, solution, 1.0E-10, "Solution does not match expected"); + } + + private static Stream matrixGenerator() { + + return Stream.of(Arguments.of(new double[][] {{-5, 8, -4}, {0, 6, 3}, {0, 0, -4}}, new double[] {38, -9, 20}, new double[] {-2, 1, -5}), Arguments.of(new double[][] {{-2, -1, -1}, {3, 4, 1}, {3, 6, 5}}, new double[] {-11, 19, 43}, new double[] {2, 2, 5})); + } +} From 3acae12dd7cb9aa62868d94874ed9f6cf536c414 Mon Sep 17 00:00:00 2001 From: David Kong <21kondav@gmail.com> Date: Fri, 14 Mar 2025 14:32:30 -0400 Subject: [PATCH 2/4] Pull Request changes --- .../java/com/thealgorithms/matrix/SolveSystem.java | 2 -- .../java/com/thealgorithms/matrix/SolveSystemTest.java | 10 +++------- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/thealgorithms/matrix/SolveSystem.java b/src/main/java/com/thealgorithms/matrix/SolveSystem.java index f0a392570fd9..fd2c9ce28a14 100644 --- a/src/main/java/com/thealgorithms/matrix/SolveSystem.java +++ b/src/main/java/com/thealgorithms/matrix/SolveSystem.java @@ -42,10 +42,8 @@ public static double[] solveSystem(double[][] matrix, double[] constants) { double tempConst = constants[k]; constants[k] = constants[maxIdx]; constants[maxIdx] = tempConst; - for (int i = k + 1; i < matrix.length; i++) { // compute multipliers and save them in the column - matrix[i][k] /= matrix[k][k]; for (int j = k + 1; j < matrix.length; j++) { matrix[i][j] -= matrix[i][k] * matrix[k][j]; diff --git a/src/test/java/com/thealgorithms/matrix/SolveSystemTest.java b/src/test/java/com/thealgorithms/matrix/SolveSystemTest.java index dad8bdf80c18..c8d289bd8339 100644 --- a/src/test/java/com/thealgorithms/matrix/SolveSystemTest.java +++ b/src/test/java/com/thealgorithms/matrix/SolveSystemTest.java @@ -1,25 +1,21 @@ package com.thealgorithms.matrix; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; + +import java.util.stream.Stream; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; -import java.util.stream.Stream; - -import static org.junit.jupiter.api.Assertions.assertArrayEquals; - class SolveSystemTest { @ParameterizedTest @MethodSource({"matrixGenerator"}) void solveSystem(double[][] matrix, double[] constants, double[] solution) { - double[] expected = SolveSystem.solveSystem(matrix, constants); assertArrayEquals(expected, solution, 1.0E-10, "Solution does not match expected"); } - private static Stream matrixGenerator() { - return Stream.of(Arguments.of(new double[][] {{-5, 8, -4}, {0, 6, 3}, {0, 0, -4}}, new double[] {38, -9, 20}, new double[] {-2, 1, -5}), Arguments.of(new double[][] {{-2, -1, -1}, {3, 4, 1}, {3, 6, 5}}, new double[] {-11, 19, 43}, new double[] {2, 2, 5})); } } From 3215c690620be470c72989811f5d71692dc97f36 Mon Sep 17 00:00:00 2001 From: David Kong <21kondav@gmail.com> Date: Fri, 14 Mar 2025 14:42:07 -0400 Subject: [PATCH 3/4] Improving formatting --- .../com/thealgorithms/matrix/SolveSystem.java | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/thealgorithms/matrix/SolveSystem.java b/src/main/java/com/thealgorithms/matrix/SolveSystem.java index fd2c9ce28a14..6653f0b86dc6 100644 --- a/src/main/java/com/thealgorithms/matrix/SolveSystem.java +++ b/src/main/java/com/thealgorithms/matrix/SolveSystem.java @@ -6,15 +6,13 @@ * @link Gaussian Elimination Wiki * @see InverseOfMatrix finds the full of inverse of a matrice, but is not required to solve a system. */ -public class SolveSystem { +public final class SolveSystem { private SolveSystem() { } /** * Problem: Given a matrix A and vector b, solve the linear system Ax = b for the vector x.\ *

- * This variation uses @link Crout Reduction - * and partial pivoting to decompose the matrix. * This OVERWRITES the input matrix to save on memory * * @param matrix - a square matrix of doubles @@ -22,7 +20,7 @@ private SolveSystem() { * @return solutions */ public static double[] solveSystem(double[][] matrix, double[] constants) { - final double TOL = 0.00000001; // tolerance for round off + final double tol = 0.00000001; // tolerance for round off for (int k = 0; k < matrix.length - 1; k++) { // find the largest value in column (to avoid zero pivots) double maxVal = Math.abs(matrix[k][k]); @@ -33,8 +31,10 @@ public static double[] solveSystem(double[][] matrix, double[] constants) { maxIdx = j; } } - if (Math.abs(maxVal) < TOL) // hope the matrix works out + if (Math.abs(maxVal) < tol){ + // hope the matrix works out continue; + } // swap rows double[] temp = matrix[k]; matrix[k] = matrix[maxIdx]; @@ -56,12 +56,16 @@ public static double[] solveSystem(double[][] matrix, double[] constants) { System.arraycopy(constants, 0, x, 0, constants.length); for (int i = matrix.length - 1; i >= 0; i--) { double sum = 0; - for (int j = i + 1; j < matrix.length; j++) sum += matrix[i][j] * x[j]; + for (int j = i + 1; j < matrix.length; j++){ + sum += matrix[i][j] * x[j]; + } x[i] = constants[i] - sum; - if (Math.abs(matrix[i][i]) > TOL) + if (Math.abs(matrix[i][i]) > tol){ x[i] /= matrix[i][i]; - else + } + else{ throw new IllegalArgumentException("Matrix was found to be singular"); + } } return x; } From 4242e873932bb784640f7623bd56d75cfbe8ed03 Mon Sep 17 00:00:00 2001 From: David Kong <21kondav@gmail.com> Date: Fri, 14 Mar 2025 14:44:43 -0400 Subject: [PATCH 4/4] More formatting --- src/main/java/com/thealgorithms/matrix/SolveSystem.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/thealgorithms/matrix/SolveSystem.java b/src/main/java/com/thealgorithms/matrix/SolveSystem.java index 6653f0b86dc6..9e683bc4dc5c 100644 --- a/src/main/java/com/thealgorithms/matrix/SolveSystem.java +++ b/src/main/java/com/thealgorithms/matrix/SolveSystem.java @@ -31,7 +31,7 @@ public static double[] solveSystem(double[][] matrix, double[] constants) { maxIdx = j; } } - if (Math.abs(maxVal) < tol){ + if (Math.abs(maxVal) < tol) { // hope the matrix works out continue; } @@ -56,14 +56,13 @@ public static double[] solveSystem(double[][] matrix, double[] constants) { System.arraycopy(constants, 0, x, 0, constants.length); for (int i = matrix.length - 1; i >= 0; i--) { double sum = 0; - for (int j = i + 1; j < matrix.length; j++){ + for (int j = i + 1; j < matrix.length; j++) { sum += matrix[i][j] * x[j]; } x[i] = constants[i] - sum; - if (Math.abs(matrix[i][i]) > tol){ + if (Math.abs(matrix[i][i]) > tol) { x[i] /= matrix[i][i]; - } - else{ + } else { throw new IllegalArgumentException("Matrix was found to be singular"); } }