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
- * 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");
}
}