From d9221213ddaff10e2f41391863c6fe8e33218e92 Mon Sep 17 00:00:00 2001 From: dmifed Date: Wed, 5 Dec 2018 16:13:20 +0400 Subject: [PATCH 1/7] My solution 05 12 18 16.00 --- .idea/misc.xml | 2 +- .idea/modules.xml | 2 +- .idea/project.iml | 10 ------ src/solver/Answer.java | 38 +++++++++++++++++++++ src/solver/Main.java | 25 +++++++++++++- src/solver/Matrix.java | 42 +++++++++++++++++++++++ src/solver/Solver.java | 75 ++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 181 insertions(+), 13 deletions(-) delete mode 100644 .idea/project.iml create mode 100644 src/solver/Answer.java create mode 100644 src/solver/Matrix.java create mode 100644 src/solver/Solver.java diff --git a/.idea/misc.xml b/.idea/misc.xml index a165cb3..e208459 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml index a0733a5..d040f98 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -2,7 +2,7 @@ - + \ No newline at end of file diff --git a/.idea/project.iml b/.idea/project.iml deleted file mode 100644 index 47baa8c..0000000 --- a/.idea/project.iml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/src/solver/Answer.java b/src/solver/Answer.java new file mode 100644 index 0000000..a8aafb4 --- /dev/null +++ b/src/solver/Answer.java @@ -0,0 +1,38 @@ +package solver; + +import java.io.FileWriter; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Scanner; +import java.util.stream.Collectors; + +/** + * Created by DIMA, on 04.12.2018 + */ +public class Answer { + + private List createAnswer(double[][] gaussJordanMatrix){ + List answer = new ArrayList<>(); + for(int i = 0; i < gaussJordanMatrix.length; i++){ + answer.add(gaussJordanMatrix[i][gaussJordanMatrix[i].length-1]); + } + return answer; + } + + + + void writeAnswer(String fileNameToWrite, double[][] gaussJordanMatrix){ + List answer = createAnswer(gaussJordanMatrix); + try (FileWriter fileWriter = new FileWriter(fileNameToWrite)){ + String s = answer.stream().map(String::valueOf).collect(Collectors.joining(" ")); + fileWriter.write(s); + fileWriter.flush(); + }catch (IOException e){ + System.out.println("Wrong fileOut, please check"); + System.out.println(e.getMessage()); + } + } + + +} diff --git a/src/solver/Main.java b/src/solver/Main.java index 4404714..883ed26 100644 --- a/src/solver/Main.java +++ b/src/solver/Main.java @@ -1,7 +1,30 @@ package solver; public class Main { + + private String fileNameSource; + private String fileNameAnswer; + private Matrix matrix; + private Solver solver; + private Answer answer; + public static void main(String[] args) { - System.out.print("Hello world!"); + Main m = new Main(); + m.fileNameSource = args[0]; + m.fileNameAnswer = args[1]; + m.matrix = new Matrix(m.fileNameSource); + m.solver = new Solver(); + m.answer = new Answer(); + + double[][] gaussJordanMatrix = m.solver.calcGausJordan(m.matrix.getMatrix()); + m.answer.writeAnswer(m.fileNameAnswer, gaussJordanMatrix); + + + + + + + //============================TESTS======================// + } } \ No newline at end of file diff --git a/src/solver/Matrix.java b/src/solver/Matrix.java new file mode 100644 index 0000000..fbecda4 --- /dev/null +++ b/src/solver/Matrix.java @@ -0,0 +1,42 @@ +package solver; + +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.util.Arrays; +import java.util.Scanner; +import java.util.stream.Collectors; + +/** + * Created by DIMA, on 03.12.2018 + */ +public class Matrix { + private double[][] matrix; + + Matrix(String fileName){ + try (Scanner scanner = new Scanner(new FileInputStream(fileName))){ + int rows = scanner.nextInt(); + matrix = new double[rows][rows+1]; + for(int i = 0; i < rows; i++){ + for (int j = 0; j < rows + 1; j++){ + matrix[i][j] = scanner.nextDouble(); + } + } + }catch (FileNotFoundException e){ + System.out.println("Please check file of coefficients"); + System.out.println(e.getMessage()); + } + } + + @Override + public String toString() { + return Arrays.stream(matrix) + .map(i -> Arrays.stream(i).boxed() + .map(String::valueOf) + .collect(Collectors.joining(" "))) + .collect(Collectors.joining("\n")); + } + + public double[][] getMatrix() { + return matrix; + } +} diff --git a/src/solver/Solver.java b/src/solver/Solver.java new file mode 100644 index 0000000..5f29e90 --- /dev/null +++ b/src/solver/Solver.java @@ -0,0 +1,75 @@ +package solver; + +import java.util.Arrays; +import java.util.stream.Collectors; + +/** + * Created by DIMA, on 03.12.2018 + */ +class Solver { + + private double[][] calcGaussian(double[][] matrix){ + // 1*x1 + if(matrix[0][0] != 1){ + divideRowToOne(0, matrix[0][0], matrix); + } + for(int row = 1; row < matrix.length; row++){ + //nulling columns [0, row) + for(int column = 0; column < row; column++){ + double multifactorXi = matrix[row][column]; + // -multiFactorXi * matrix[column] + matrix[row] + for(int k = 0; k < matrix[row].length; k++){ + double oldValue = matrix[column][k]; + double newValue = -oldValue*multifactorXi + matrix[row][k]; + matrix[row][k] = newValue; + } + } + //1*xi + if(matrix[row][row] != 1){ + divideRowToOne(row, matrix[row][row], matrix); + } + } + return matrix; + } + + double[][] calcGausJordan(double[][] matrix){ + double[][] matrixGausJordan = calcGaussian(matrix); + //from row last but one + for (int row = matrixGausJordan.length - 2; row >= 0; row--){ + //above main diagonal + // 1 a b c + // 0 1 d f + // 0 0 1 k + for (int column = row + 1; column < matrixGausJordan.length; column++){ + double multifactorXi = matrixGausJordan[row][column]; + for(int k = 0; k < matrixGausJordan[row].length; k++){ + double oldValue = matrixGausJordan[column][k]; + double newValue = -oldValue*multifactorXi + matrixGausJordan[row][k]; + matrixGausJordan[row][k] = newValue; + } + } + } + return matrixGausJordan; + } + + + private void divideRowToOne(int row, double devide, double[][] matrix){ + for(int column = 0; column < matrix[row].length; column++){ + double item = matrix[row][column]; + matrix[row][column] = item/devide; + } + } + + void print(double matrix[][]){ + String s = Arrays.stream(matrix) + .map(i -> Arrays.stream(i).boxed() + .map(String::valueOf) + .collect(Collectors.joining(" "))) + .collect(Collectors.joining("\n")); + + System.out.println(s); + } + + + +} From 6a75f354f74e8e2cd1af2a530ee3ccba4aa54a1d Mon Sep 17 00:00:00 2001 From: dmifed Date: Mon, 17 Dec 2018 19:20:48 +0400 Subject: [PATCH 2/7] specialCases 17 12 18 19.30 --- .idea/misc.xml | 5 +- src/solver/Answer.java | 9 +++- src/solver/Main.java | 4 +- src/solver/Solver.java | 49 ++++++++++++-------- src/solver/specialCases/Checker.java | 23 +++++++++ src/solver/specialCases/Searcher.java | 34 ++++++++++++++ src/solver/specialCases/Special.java | 67 +++++++++++++++++++++++++++ src/solver/specialCases/Swap.java | 22 +++++++++ src/solver/specialCases/Swapper.java | 43 +++++++++++++++++ src/solver/tmpTests/CopyArr.java | 31 +++++++++++++ src/solver/tmpTests/TestVoid.java | 55 ++++++++++++++++++++++ 11 files changed, 318 insertions(+), 24 deletions(-) create mode 100644 src/solver/specialCases/Checker.java create mode 100644 src/solver/specialCases/Searcher.java create mode 100644 src/solver/specialCases/Special.java create mode 100644 src/solver/specialCases/Swap.java create mode 100644 src/solver/specialCases/Swapper.java create mode 100644 src/solver/tmpTests/CopyArr.java create mode 100644 src/solver/tmpTests/TestVoid.java diff --git a/.idea/misc.xml b/.idea/misc.xml index e208459..556829f 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,6 +1,9 @@ - + + + + \ No newline at end of file diff --git a/src/solver/Answer.java b/src/solver/Answer.java index a8aafb4..07f743a 100644 --- a/src/solver/Answer.java +++ b/src/solver/Answer.java @@ -11,6 +11,7 @@ * Created by DIMA, on 04.12.2018 */ public class Answer { + private String fileNameToWrite; private List createAnswer(double[][] gaussJordanMatrix){ List answer = new ArrayList<>(); @@ -20,9 +21,11 @@ private List createAnswer(double[][] gaussJordanMatrix){ return answer; } + Answer(String fileNameToWrite){ + this.fileNameToWrite = fileNameToWrite; + } - - void writeAnswer(String fileNameToWrite, double[][] gaussJordanMatrix){ + void writeAnswer(double[][] gaussJordanMatrix){ List answer = createAnswer(gaussJordanMatrix); try (FileWriter fileWriter = new FileWriter(fileNameToWrite)){ String s = answer.stream().map(String::valueOf).collect(Collectors.joining(" ")); @@ -35,4 +38,6 @@ void writeAnswer(String fileNameToWrite, double[][] gaussJordanMatrix){ } + + } diff --git a/src/solver/Main.java b/src/solver/Main.java index 883ed26..db2072a 100644 --- a/src/solver/Main.java +++ b/src/solver/Main.java @@ -14,10 +14,10 @@ public static void main(String[] args) { m.fileNameAnswer = args[1]; m.matrix = new Matrix(m.fileNameSource); m.solver = new Solver(); - m.answer = new Answer(); + m.answer = new Answer(m.fileNameAnswer); double[][] gaussJordanMatrix = m.solver.calcGausJordan(m.matrix.getMatrix()); - m.answer.writeAnswer(m.fileNameAnswer, gaussJordanMatrix); + m.answer.writeAnswer(gaussJordanMatrix); diff --git a/src/solver/Solver.java b/src/solver/Solver.java index 5f29e90..c12c6ae 100644 --- a/src/solver/Solver.java +++ b/src/solver/Solver.java @@ -1,5 +1,8 @@ package solver; +import solver.specialCases.Searcher; +import solver.specialCases.Special; + import java.util.Arrays; import java.util.stream.Collectors; @@ -15,15 +18,7 @@ private double[][] calcGaussian(double[][] matrix){ } for(int row = 1; row < matrix.length; row++){ //nulling columns [0, row) - for(int column = 0; column < row; column++){ - double multifactorXi = matrix[row][column]; - // -multiFactorXi * matrix[column] + matrix[row] - for(int k = 0; k < matrix[row].length; k++){ - double oldValue = matrix[column][k]; - double newValue = -oldValue*multifactorXi + matrix[row][k]; - matrix[row][k] = newValue; - } - } + matrix = calcGaussianOneRow(row, matrix); //1*xi if(matrix[row][row] != 1){ divideRowToOne(row, matrix[row][row], matrix); @@ -32,6 +27,19 @@ private double[][] calcGaussian(double[][] matrix){ return matrix; } + private double[][] calcGaussianOneRow (int row, double[][] matrix){ + for(int column = 0; column < row; column++){ + double multifactorXi = matrix[row][column]; + // -multiFactorXi * matrix[column] + matrix[row] + for(int k = 0; k < matrix[row].length; k++){ + double oldValue = matrix[column][k]; + double newValue = -oldValue*multifactorXi + matrix[row][k]; + matrix[row][k] = newValue; + } + } + return matrix; + } + double[][] calcGausJordan(double[][] matrix){ double[][] matrixGausJordan = calcGaussian(matrix); //from row last but one @@ -52,6 +60,19 @@ private double[][] calcGaussian(double[][] matrix){ return matrixGausJordan; } + private double[][] calcSpecialGaussian(double[][] matrix){ + //first row + + + + + if(matrix[0][0] != 1){ + divideRowToOne(0, matrix[0][0], matrix); + } + return matrix; + } + + private void divideRowToOne(int row, double devide, double[][] matrix){ for(int column = 0; column < matrix[row].length; column++){ @@ -60,16 +81,6 @@ private void divideRowToOne(int row, double devide, double[][] matrix){ } } - void print(double matrix[][]){ - String s = Arrays.stream(matrix) - .map(i -> Arrays.stream(i).boxed() - .map(String::valueOf) - .collect(Collectors.joining(" "))) - .collect(Collectors.joining("\n")); - - System.out.println(s); - } - } diff --git a/src/solver/specialCases/Checker.java b/src/solver/specialCases/Checker.java new file mode 100644 index 0000000..2fadcda --- /dev/null +++ b/src/solver/specialCases/Checker.java @@ -0,0 +1,23 @@ +package solver.specialCases; + +/** + * Created by DIMA, on 07.12.2018 + */ +public class Checker { + public static final double DELTA_DOUBLE = 0.000001; + + public static boolean hasZeroCorrespondingElement(int row, double[][] matrix){ + if (matrix[row].length < row) return false; + return Math.abs(matrix[row][row]) < DELTA_DOUBLE; + } + + public static boolean checkRowToNoSolution(int row, double[][] matrix){ + for(int column = 0; column < matrix[row].length - 1; column ++){ + if(Math.abs(matrix[row][column]) > DELTA_DOUBLE){ + return false; + } + } + // if no return that means all elements is zero + return Math.abs(matrix[row][matrix[row].length - 1]) > DELTA_DOUBLE; + } +} diff --git a/src/solver/specialCases/Searcher.java b/src/solver/specialCases/Searcher.java new file mode 100644 index 0000000..60ec6fb --- /dev/null +++ b/src/solver/specialCases/Searcher.java @@ -0,0 +1,34 @@ +package solver.specialCases; + +/** + * Created by DIMA, on 10.12.2018 + */ +public class Searcher { + public static int searchRowDown(int startRow, int targetColumn, double[][] matrix){ + int row = -1; + for(int i = startRow + 1; i < matrix.length; i ++){ + if(Math.abs(matrix[i][targetColumn]) > Checker.DELTA_DOUBLE){ + return i; + } + } + return row; + } + + public static int searchColumnRight(int startColumn, int currentRow, double[][] matrix){ + int column = -1; + for(int i = startColumn + 1; i < matrix[currentRow].length - 1; i++){ + if(Math.abs(matrix[currentRow][i]) > Checker.DELTA_DOUBLE){ + return i; + } + } + return column; + } + + public static int[][] searchInBottomLeftCorner(int startRow, int startColumn, double[][] matrix){ + int[][] rowAndColumn = null; + for(int i = startRow + 1; i < matrix.length; i++){ + // for(int j = ) + } + return rowAndColumn; + } +} diff --git a/src/solver/specialCases/Special.java b/src/solver/specialCases/Special.java new file mode 100644 index 0000000..b0c43fc --- /dev/null +++ b/src/solver/specialCases/Special.java @@ -0,0 +1,67 @@ +package solver.specialCases; + +import java.util.ArrayDeque; +import java.util.Arrays; +import java.util.Deque; +import java.util.Stack; +import java.util.stream.Collectors; + +/** + * Created by DIMA, on 06.12.2018 + */ +public class Special { + public static Deque swapStack = new ArrayDeque<>(); + + public void addSwap(int oldColumn, int newColumn){ + Swap swap = new Swap(oldColumn, newColumn); + swapStack.addLast(swap); + } + + public static double[][] deleteRow (int row, double[][] matrix){ + double[][] trimMatrix = new double[matrix.length-1][matrix[row].length]; + for(int i = 0; i < row; i++){ + for (int j = 0; j < matrix[i].length; j ++){ + trimMatrix[i][j] = matrix[i][j]; + } + } + for(int i = row+1; i < matrix.length; i++){ + for (int j = 0; j < matrix[i].length; j++){ + trimMatrix[i-1][j] = matrix[i][j]; + } + } + return trimMatrix; + } + + public double[][] transformMatrix(int row, double[][] matrix){ + if(matrix[row][row] == 0){ + int newRow = Searcher.searchRowDown(0, 0, matrix); + if(newRow == -1){ + newRow = Searcher.searchColumnRight(0,0,matrix); + if(newRow == -1){ + if(matrix[row][matrix[row].length-1] != 0){ + // no solution + }else { + Special.deleteRow(0, matrix); + } + } + } + } + return null; + + + + } + + + public static void print(double matrix[][]){ + String s = Arrays.stream(matrix) + .map(i -> Arrays.stream(i).boxed() + .map(String::valueOf) + .collect(Collectors.joining(" "))) + .collect(Collectors.joining("\n")); + + System.out.println(s); + } + + +} diff --git a/src/solver/specialCases/Swap.java b/src/solver/specialCases/Swap.java new file mode 100644 index 0000000..0902e46 --- /dev/null +++ b/src/solver/specialCases/Swap.java @@ -0,0 +1,22 @@ +package solver.specialCases; + +/** + * Created by DIMA, on 06.12.2018 + */ +public class Swap { + private int oldColumnsNumber; + private int newColumnsNumber; + + public Swap(int oldColumnsNumber, int newColumnsNumber) { + this.oldColumnsNumber = oldColumnsNumber; + this.newColumnsNumber = newColumnsNumber; + } + + public int getOldColumnsNumber() { + return oldColumnsNumber; + } + + public int getNewColumnsNumber() { + return newColumnsNumber; + } +} diff --git a/src/solver/specialCases/Swapper.java b/src/solver/specialCases/Swapper.java new file mode 100644 index 0000000..a850402 --- /dev/null +++ b/src/solver/specialCases/Swapper.java @@ -0,0 +1,43 @@ +package solver.specialCases; + +import java.util.Deque; + +/** + * Created by DIMA, on 07.12.2018 + */ +public class Swapper { + + public static void swapColumns (int oldColumns, int newColumns, double[][] matrix){ + for (int row = 0; row < matrix.length; row++){ + double tmp = matrix[row][newColumns]; + matrix[row][newColumns] = matrix[row][oldColumns]; + matrix[row][oldColumns] = tmp; + } + } + + public static void swapRows(int oldRow, int newRow, double[][] matrix){ + for(int column = 0; column < matrix[oldRow].length; column++){ + double tmp = matrix[newRow][column]; + matrix[newRow][column] = matrix[oldRow][column]; + matrix[oldRow][column] = tmp; + } + } + + private static void unSwapColumns(Swap swap, double[][] matrix){ + int sourceColumn = swap.getNewColumnsNumber(); + int targetColumn = swap.getOldColumnsNumber(); + for(int row = 0; row < matrix.length; row++){ + double tmp = matrix[row][sourceColumn]; + matrix[row][sourceColumn] = matrix[row][targetColumn]; + matrix[row][targetColumn] = tmp; + } + } + + public static void unSwapAllC(Deque swapDeque, double[][] matrix){ + Swap swap; + while ((swap = swapDeque.pollLast()) != null){ + unSwapColumns(swap, matrix); + } + } + +} diff --git a/src/solver/tmpTests/CopyArr.java b/src/solver/tmpTests/CopyArr.java new file mode 100644 index 0000000..ad17d8e --- /dev/null +++ b/src/solver/tmpTests/CopyArr.java @@ -0,0 +1,31 @@ +package solver.tmpTests; + +import solver.specialCases.Special; + +import java.util.Arrays; + +/** + * Created by DIMA, on 10.12.2018 + */ +public class CopyArr { + public static void main(String[] args) { + double[][] a1 = {{1,1}, {2,2}, {0, 0}, {4,4}, {5,5}}; + double[][] a2; + double[][] a3; + + a2 = Arrays.copyOf(a1, 2); + Special.print(a2); + + a3 = Arrays.copyOfRange(a1, 3, a1.length); + Special.print(a3); + + + + + + + + + + } +} diff --git a/src/solver/tmpTests/TestVoid.java b/src/solver/tmpTests/TestVoid.java new file mode 100644 index 0000000..702b2a6 --- /dev/null +++ b/src/solver/tmpTests/TestVoid.java @@ -0,0 +1,55 @@ +package solver.tmpTests; + +import java.util.Arrays; +import java.util.stream.Collectors; + +/** + * Created by DIMA, on 17.12.2018 + */ +public class TestVoid { + public String getStringMultyTwo(int [] arr){ + String s = Arrays.stream(arr).boxed().map(String::valueOf).collect(Collectors.joining(" ")); + System.out.println(s); + arr = deleteElem(arr, 3); + s = Arrays.stream(arr).boxed().map(String::valueOf).collect(Collectors.joining(" ")); + System.out.println(s); + devide(arr, 3); + return Arrays.stream(arr).boxed().map(String::valueOf).collect(Collectors.joining(" ")); + + + + } + + private int[] deleteElem(int[] arr, int index){ + int[] ar1 = new int[arr.length -1]; + for(int i = 0; i < index; i++){ + ar1[i] = arr[i]; + } + for(int i = index+1; i < arr.length; i++){ + ar1[i-1] = arr[i]; + } + //System.out.println(Arrays.stream(ar1).boxed().map(String::valueOf).collect(Collectors.joining(" "))); + return ar1; + } + + private void changeInt(int a){ + a = a*2; + } + + private void devide (int[] arr, int a){ + for(int i = 0; i < arr.length; i++){ + arr[i] = arr[i]/a; + } + + + + } + + public static void main(String[] args) { + int[] a = {0,1,2,3,4,5,6,7}; + TestVoid t = new TestVoid(); + System.out.println(t.getStringMultyTwo(a)); + } + + +} From 193fe3d22318e5e7b853248d0e5a06a693416949 Mon Sep 17 00:00:00 2001 From: dmifed Date: Mon, 17 Dec 2018 19:40:54 +0400 Subject: [PATCH 3/7] specialCases 17 12 18 20.00 --- out.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 out.txt diff --git a/out.txt b/out.txt new file mode 100644 index 0000000..b624f8a --- /dev/null +++ b/out.txt @@ -0,0 +1 @@ +1.0 2.0 3.0 \ No newline at end of file From 4e4bc555db8c6279697912a2bedc35968fe8631c Mon Sep 17 00:00:00 2001 From: dmifed Date: Mon, 17 Dec 2018 19:43:38 +0400 Subject: [PATCH 4/7] specialCases 17 12 18 20.00 --- in.txt | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 in.txt diff --git a/in.txt b/in.txt new file mode 100644 index 0000000..b0bf574 --- /dev/null +++ b/in.txt @@ -0,0 +1,4 @@ +3 +1 1 2 9 +2 4 -3 1 +3 6 -5 0 \ No newline at end of file From 4d1b605e706c287a6dcd55c69bddc6a3d16ea5d4 Mon Sep 17 00:00:00 2001 From: dmifed Date: Thu, 20 Dec 2018 22:13:42 +0300 Subject: [PATCH 5/7] Create linear-equations-solver.iml --- linear-equations-solver.iml | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 linear-equations-solver.iml diff --git a/linear-equations-solver.iml b/linear-equations-solver.iml new file mode 100644 index 0000000..a3c52db --- /dev/null +++ b/linear-equations-solver.iml @@ -0,0 +1,9 @@ + + + + + + + + + From 39c0d7cf7c3274bcf8c2d914802c1378a835b0d6 Mon Sep 17 00:00:00 2001 From: dmifed Date: Wed, 16 Jan 2019 12:42:53 +0400 Subject: [PATCH 6/7] Linear Equations Solver Step4: Special cases. 16.01.2019 12:40 --- in.txt | 9 +- linear-equations-solver.iml | 11 +++ out.txt | 2 +- src/solver/Answer.java | 17 +++- src/solver/Main.java | 16 ++-- src/solver/Matrix.java | 5 +- src/solver/Solver.java | 121 ++++++++++++++++++------- src/solver/specialCases/Checker.java | 41 ++++++--- src/solver/specialCases/Helper.java | 31 +++++++ src/solver/specialCases/Searcher.java | 22 ++--- src/solver/specialCases/Special.java | 67 -------------- src/solver/specialCases/SwapStore.java | 23 +++++ src/solver/specialCases/Swapper.java | 10 +- src/solver/tmpTests/CopyArr.java | 7 +- 14 files changed, 235 insertions(+), 147 deletions(-) create mode 100644 linear-equations-solver.iml create mode 100644 src/solver/specialCases/Helper.java delete mode 100644 src/solver/specialCases/Special.java create mode 100644 src/solver/specialCases/SwapStore.java diff --git a/in.txt b/in.txt index b0bf574..674a535 100644 --- a/in.txt +++ b/in.txt @@ -1,4 +1,5 @@ -3 -1 1 2 9 -2 4 -3 1 -3 6 -5 0 \ No newline at end of file +4 4 +0 0 0 0 +0 1 3 1 +4 0 6 0 +1 -1 1 15 diff --git a/linear-equations-solver.iml b/linear-equations-solver.iml new file mode 100644 index 0000000..c90834f --- /dev/null +++ b/linear-equations-solver.iml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/out.txt b/out.txt index b624f8a..74ef871 100644 --- a/out.txt +++ b/out.txt @@ -1 +1 @@ -1.0 2.0 3.0 \ No newline at end of file +-9.6 -18.2 6.4 \ No newline at end of file diff --git a/src/solver/Answer.java b/src/solver/Answer.java index 07f743a..ca5af7f 100644 --- a/src/solver/Answer.java +++ b/src/solver/Answer.java @@ -2,6 +2,8 @@ import java.io.FileWriter; import java.io.IOException; +import java.math.BigDecimal; +import java.math.BigInteger; import java.util.ArrayList; import java.util.List; import java.util.Scanner; @@ -16,7 +18,9 @@ public class Answer { private List createAnswer(double[][] gaussJordanMatrix){ List answer = new ArrayList<>(); for(int i = 0; i < gaussJordanMatrix.length; i++){ - answer.add(gaussJordanMatrix[i][gaussJordanMatrix[i].length-1]); + double x = gaussJordanMatrix[i][gaussJordanMatrix[i].length-1]; + x = new BigDecimal(x).setScale(6, BigDecimal.ROUND_HALF_UP).doubleValue(); + answer.add(x); } return answer; } @@ -37,6 +41,17 @@ void writeAnswer(double[][] gaussJordanMatrix){ } } + void writeAnswer(String s){ + try (FileWriter fileWriter = new FileWriter(fileNameToWrite)){ + fileWriter.write(s); + fileWriter.flush(); + }catch (IOException e){ + System.out.println("Wrong fileOut, please check"); + System.out.println(e.getMessage()); + } + } + + diff --git a/src/solver/Main.java b/src/solver/Main.java index db2072a..f873d9a 100644 --- a/src/solver/Main.java +++ b/src/solver/Main.java @@ -13,16 +13,18 @@ public static void main(String[] args) { m.fileNameSource = args[0]; m.fileNameAnswer = args[1]; m.matrix = new Matrix(m.fileNameSource); - m.solver = new Solver(); + m.solver = new Solver(m.matrix); m.answer = new Answer(m.fileNameAnswer); - double[][] gaussJordanMatrix = m.solver.calcGausJordan(m.matrix.getMatrix()); - m.answer.writeAnswer(gaussJordanMatrix); - - - - + double[][] gaussJordanMatrix = m.solver.calcGaussJordan(m.matrix.getMatrix()); + if(m.solver.noSolutions){ + m.answer.writeAnswer("No Solution"); + }else if(m.solver.infinitySolutions){ + m.answer.writeAnswer("Infinity Solutions"); + }else { + m.answer.writeAnswer(gaussJordanMatrix); + } //============================TESTS======================// diff --git a/src/solver/Matrix.java b/src/solver/Matrix.java index fbecda4..86d1af2 100644 --- a/src/solver/Matrix.java +++ b/src/solver/Matrix.java @@ -15,9 +15,10 @@ public class Matrix { Matrix(String fileName){ try (Scanner scanner = new Scanner(new FileInputStream(fileName))){ int rows = scanner.nextInt(); - matrix = new double[rows][rows+1]; + int columns = scanner.nextInt(); + matrix = new double[rows][columns]; for(int i = 0; i < rows; i++){ - for (int j = 0; j < rows + 1; j++){ + for (int j = 0; j < columns; j++){ matrix[i][j] = scanner.nextDouble(); } } diff --git a/src/solver/Solver.java b/src/solver/Solver.java index c12c6ae..6866be5 100644 --- a/src/solver/Solver.java +++ b/src/solver/Solver.java @@ -1,33 +1,72 @@ package solver; -import solver.specialCases.Searcher; -import solver.specialCases.Special; - -import java.util.Arrays; -import java.util.stream.Collectors; +import solver.specialCases.*; /** * Created by DIMA, on 03.12.2018 */ class Solver { + boolean noSolutions = false; + boolean infinitySolutions = false; + double[][] matrix; + + public Solver(Matrix m){ + matrix = m.getMatrix(); + } + private double[][] calcGaussian(double[][] matrix){ // 1*x1 - if(matrix[0][0] != 1){ - divideRowToOne(0, matrix[0][0], matrix); - } - for(int row = 1; row < matrix.length; row++){ - //nulling columns [0, row) - matrix = calcGaussianOneRow(row, matrix); - //1*xi - if(matrix[row][row] != 1){ + int matrixSize = matrix.length; + for (int row = 0; row < matrixSize; row++){ + if(!Checker.isAllZero(row, matrix)){ + if(!Checker.hasMainNumber(row, matrix)){ + int findedRow = Searcher.searchRowDown(row,matrix); + if(findedRow != -1){ + Swapper.swapRows(row, findedRow, matrix); + }else { + int findedColumn = Searcher.searchColumnRight(row, matrix); + if (findedColumn != -1){ + Swapper.swapColumns(row, findedColumn, matrix); + SwapStore.addSwap(row, findedColumn); + }else { + if(!Checker.isZeroInRightColumn(row, matrix)){ + noSolutions = true; + return null; + }else { + continue; + } + } + } + } + }else { + matrix = deleteRow(row, matrix); + row--; + matrixSize--; + continue; + } + if(row != 0){ + nullingRowGauss(row, matrix); + } + if(!Checker.isAllZero(row, matrix)){ divideRowToOne(row, matrix[row][row], matrix); } } + if(Checker.checkToNoSolution(matrix)){ + noSolutions = true; + return null; + } + //Helper.print(matrix); + Swapper.unSwapAllC(SwapStore.swapStack, matrix); + matrix = deleteZeroRows(matrix); + if(Checker.checkToNoSolution(matrix)){ + noSolutions = true; + return null; + } return matrix; } - private double[][] calcGaussianOneRow (int row, double[][] matrix){ + private void nullingRowGauss(int row, double[][] matrix){ for(int column = 0; column < row; column++){ double multifactorXi = matrix[row][column]; // -multiFactorXi * matrix[column] + matrix[row] @@ -37,11 +76,11 @@ private double[][] calcGaussianOneRow (int row, double[][] matrix){ matrix[row][k] = newValue; } } - return matrix; } - double[][] calcGausJordan(double[][] matrix){ + double[][] calcGaussJordan(double[][] matrix){ double[][] matrixGausJordan = calcGaussian(matrix); + if(noSolutions || matrixGausJordan == null) return null; //from row last but one for (int row = matrixGausJordan.length - 2; row >= 0; row--){ //above main diagonal @@ -57,30 +96,48 @@ private double[][] calcGaussianOneRow (int row, double[][] matrix){ } } } + if(matrixGausJordan.length < matrixGausJordan[0].length - 1){ + infinitySolutions = true; + } + //Helper.print(matrixGausJordan); return matrixGausJordan; } - private double[][] calcSpecialGaussian(double[][] matrix){ - //first row - - - + private void divideRowToOne(int row, double devide, double[][] matrix){ + //if(row >= matrix[0].lenght) do nothing + if(row < matrix[0].length){ + for(int column = 0; column < matrix[row].length; column++){ + double item = matrix[row][column]; + matrix[row][column] = item/devide; + } + } + } - if(matrix[0][0] != 1){ - divideRowToOne(0, matrix[0][0], matrix); + private double[][] deleteZeroRows(double[][] matrix){ + int matrixSize = matrix.length; + for(int row = 0; row < matrixSize; row++){ + if(Checker.isAllZero(row, matrix)){ + //del row + matrix = deleteRow(row, matrix); + row--; + matrixSize--; + } } return matrix; } - - - private void divideRowToOne(int row, double devide, double[][] matrix){ - for(int column = 0; column < matrix[row].length; column++){ - double item = matrix[row][column]; - matrix[row][column] = item/devide; + private static double[][] deleteRow (int row, double[][] matrix){ + double[][] trimMatrix = new double[matrix.length-1][matrix[row].length]; + for(int i = 0; i < row; i++){ + for (int j = 0; j < matrix[i].length; j ++){ + trimMatrix[i][j] = matrix[i][j]; + } + } + for(int i = row+1; i < matrix.length; i++){ + for (int j = 0; j < matrix[i].length; j++){ + trimMatrix[i-1][j] = matrix[i][j]; + } } + return trimMatrix; } - - - } diff --git a/src/solver/specialCases/Checker.java b/src/solver/specialCases/Checker.java index 2fadcda..cace7c5 100644 --- a/src/solver/specialCases/Checker.java +++ b/src/solver/specialCases/Checker.java @@ -4,20 +4,39 @@ * Created by DIMA, on 07.12.2018 */ public class Checker { - public static final double DELTA_DOUBLE = 0.000001; + static final double DELTA_DOUBLE = 0.000001; - public static boolean hasZeroCorrespondingElement(int row, double[][] matrix){ - if (matrix[row].length < row) return false; - return Math.abs(matrix[row][row]) < DELTA_DOUBLE; + public static boolean hasMainNumber(int row, double[][] matrix){ + if (row >= matrix[row].length) return true; + return Math.abs(matrix[row][row]) > DELTA_DOUBLE; } - public static boolean checkRowToNoSolution(int row, double[][] matrix){ - for(int column = 0; column < matrix[row].length - 1; column ++){ - if(Math.abs(matrix[row][column]) > DELTA_DOUBLE){ - return false; - } - } - // if no return that means all elements is zero + public static boolean isZeroInRightColumn(int row, double[][] matrix){ return Math.abs(matrix[row][matrix[row].length - 1]) > DELTA_DOUBLE; } + + public static boolean isAllZero(int row, double[][] matrix){ + for (int column = 0; column < matrix[row].length; column++){ + if(matrix[row][column] > DELTA_DOUBLE) return false; + } + return true; + } + + public static boolean checkToNoSolution(double[][] matrix){ + for(int row = 0; row < matrix.length; row++){ + boolean zeroInLeftSide = true; + //check left side + for(int column = 0; column < matrix[0].length - 1; column ++){ + if(Math.abs(matrix[row][column]) > DELTA_DOUBLE){ + zeroInLeftSide = false; + } + } + if(zeroInLeftSide){ + if(Math.abs(matrix[row][matrix[row].length - 1]) > DELTA_DOUBLE){ + return true; + } + } + } + return false; + } } diff --git a/src/solver/specialCases/Helper.java b/src/solver/specialCases/Helper.java new file mode 100644 index 0000000..965d148 --- /dev/null +++ b/src/solver/specialCases/Helper.java @@ -0,0 +1,31 @@ +package solver.specialCases; + +import java.util.Arrays; +import java.util.stream.Collectors; + +/** + * Created by DIMA, on 14.01.2019 + */ +public class Helper { + public static void print(double matrix[][]){ + System.out.println("Start print"); + String s = Arrays.stream(matrix) + .map(i -> Arrays.stream(i).boxed() + .map(String::valueOf) + .collect(Collectors.joining(" "))) + .collect(Collectors.joining("\n")); + + System.out.println(s); + System.out.println("End print"); + } + + public static void roundInMatrix(double[][] matrix){ + for(int i = 0; i < matrix.length; i++){ + for(int j = 0; j < matrix[i].length; j++){ + if(Math.abs(matrix[i][j]) < Checker.DELTA_DOUBLE){ + matrix[i][j] = 0; + } + } + } + } +} diff --git a/src/solver/specialCases/Searcher.java b/src/solver/specialCases/Searcher.java index 60ec6fb..c58b546 100644 --- a/src/solver/specialCases/Searcher.java +++ b/src/solver/specialCases/Searcher.java @@ -4,31 +4,29 @@ * Created by DIMA, on 10.12.2018 */ public class Searcher { - public static int searchRowDown(int startRow, int targetColumn, double[][] matrix){ - int row = -1; + public static int searchRowDown(int startRow, double[][] matrix){ for(int i = startRow + 1; i < matrix.length; i ++){ - if(Math.abs(matrix[i][targetColumn]) > Checker.DELTA_DOUBLE){ + if(Math.abs(matrix[i][startRow]) > Checker.DELTA_DOUBLE){ return i; } } - return row; + return -1; } - public static int searchColumnRight(int startColumn, int currentRow, double[][] matrix){ - int column = -1; - for(int i = startColumn + 1; i < matrix[currentRow].length - 1; i++){ - if(Math.abs(matrix[currentRow][i]) > Checker.DELTA_DOUBLE){ - return i; + public static int searchColumnRight(int row, double[][] matrix){ + for(int column = row + 1; column < matrix[row].length - 1; column++){ + if(Math.abs(matrix[row][column]) > Checker.DELTA_DOUBLE){ + return column; } } - return column; + return -1; } - public static int[][] searchInBottomLeftCorner(int startRow, int startColumn, double[][] matrix){ +/* public static int[][] searchInBottomLeftCorner(int startRow, int startColumn, double[][] matrix){ int[][] rowAndColumn = null; for(int i = startRow + 1; i < matrix.length; i++){ // for(int j = ) } return rowAndColumn; - } + }*/ } diff --git a/src/solver/specialCases/Special.java b/src/solver/specialCases/Special.java deleted file mode 100644 index b0c43fc..0000000 --- a/src/solver/specialCases/Special.java +++ /dev/null @@ -1,67 +0,0 @@ -package solver.specialCases; - -import java.util.ArrayDeque; -import java.util.Arrays; -import java.util.Deque; -import java.util.Stack; -import java.util.stream.Collectors; - -/** - * Created by DIMA, on 06.12.2018 - */ -public class Special { - public static Deque swapStack = new ArrayDeque<>(); - - public void addSwap(int oldColumn, int newColumn){ - Swap swap = new Swap(oldColumn, newColumn); - swapStack.addLast(swap); - } - - public static double[][] deleteRow (int row, double[][] matrix){ - double[][] trimMatrix = new double[matrix.length-1][matrix[row].length]; - for(int i = 0; i < row; i++){ - for (int j = 0; j < matrix[i].length; j ++){ - trimMatrix[i][j] = matrix[i][j]; - } - } - for(int i = row+1; i < matrix.length; i++){ - for (int j = 0; j < matrix[i].length; j++){ - trimMatrix[i-1][j] = matrix[i][j]; - } - } - return trimMatrix; - } - - public double[][] transformMatrix(int row, double[][] matrix){ - if(matrix[row][row] == 0){ - int newRow = Searcher.searchRowDown(0, 0, matrix); - if(newRow == -1){ - newRow = Searcher.searchColumnRight(0,0,matrix); - if(newRow == -1){ - if(matrix[row][matrix[row].length-1] != 0){ - // no solution - }else { - Special.deleteRow(0, matrix); - } - } - } - } - return null; - - - - } - - - public static void print(double matrix[][]){ - String s = Arrays.stream(matrix) - .map(i -> Arrays.stream(i).boxed() - .map(String::valueOf) - .collect(Collectors.joining(" "))) - .collect(Collectors.joining("\n")); - - System.out.println(s); - } - - -} diff --git a/src/solver/specialCases/SwapStore.java b/src/solver/specialCases/SwapStore.java new file mode 100644 index 0000000..8e36974 --- /dev/null +++ b/src/solver/specialCases/SwapStore.java @@ -0,0 +1,23 @@ +package solver.specialCases; + +import java.util.ArrayDeque; +import java.util.Arrays; +import java.util.Deque; +import java.util.Stack; +import java.util.stream.Collectors; + +/** + * Created by DIMA, on 06.12.2018 + */ +public class SwapStore { + public static Deque swapStack = new ArrayDeque<>(); + + public static void addSwap(int oldColumn, int newColumn){ + Swap swap = new Swap(oldColumn, newColumn); + swapStack.addLast(swap); + } + + + + +} diff --git a/src/solver/specialCases/Swapper.java b/src/solver/specialCases/Swapper.java index a850402..b4837b6 100644 --- a/src/solver/specialCases/Swapper.java +++ b/src/solver/specialCases/Swapper.java @@ -24,13 +24,9 @@ public static void swapRows(int oldRow, int newRow, double[][] matrix){ } private static void unSwapColumns(Swap swap, double[][] matrix){ - int sourceColumn = swap.getNewColumnsNumber(); - int targetColumn = swap.getOldColumnsNumber(); - for(int row = 0; row < matrix.length; row++){ - double tmp = matrix[row][sourceColumn]; - matrix[row][sourceColumn] = matrix[row][targetColumn]; - matrix[row][targetColumn] = tmp; - } + int oldColumn = swap.getNewColumnsNumber(); + int newColumn = swap.getOldColumnsNumber(); + swapColumns (oldColumn, newColumn, matrix); } public static void unSwapAllC(Deque swapDeque, double[][] matrix){ diff --git a/src/solver/tmpTests/CopyArr.java b/src/solver/tmpTests/CopyArr.java index ad17d8e..0165872 100644 --- a/src/solver/tmpTests/CopyArr.java +++ b/src/solver/tmpTests/CopyArr.java @@ -1,6 +1,7 @@ package solver.tmpTests; -import solver.specialCases.Special; +import solver.specialCases.Helper; +import solver.specialCases.SwapStore; import java.util.Arrays; @@ -14,10 +15,10 @@ public static void main(String[] args) { double[][] a3; a2 = Arrays.copyOf(a1, 2); - Special.print(a2); + Helper.print(a2); a3 = Arrays.copyOfRange(a1, 3, a1.length); - Special.print(a3); + Helper.print(a3); From 90214c885443cc60dff0d3dc1e824909db1b3576 Mon Sep 17 00:00:00 2001 From: dmifed Date: Thu, 17 Jan 2019 16:24:07 +0400 Subject: [PATCH 7/7] Linear Equations Solver Step5: Support Complex Number. 17.01.2019 16:20 --- in.txt | 9 +- out.txt | 2 +- src/solver/Answer.java | 45 +++++-- src/solver/Complex.java | 147 ++++++++++++++++++++++ src/solver/Main.java | 17 ++- src/solver/Matrix.java | 14 ++- src/solver/Solver.java | 94 +++++++------- src/solver/specialCases/Checker.java | 20 +-- src/solver/specialCases/Helper.java | 37 +++--- src/solver/specialCases/Searcher.java | 18 +-- src/solver/specialCases/Swapper.java | 14 ++- src/solver/specialCases/TesterResult.java | 26 ++++ src/solver/tmpTests/CopyArr.java | 4 +- src/solver/tmpTests/TestSplit.java | 78 ++++++++++++ 14 files changed, 409 insertions(+), 116 deletions(-) create mode 100644 src/solver/Complex.java create mode 100644 src/solver/specialCases/TesterResult.java create mode 100644 src/solver/tmpTests/TestSplit.java diff --git a/in.txt b/in.txt index 674a535..dc67031 100644 --- a/in.txt +++ b/in.txt @@ -1,5 +1,4 @@ -4 4 -0 0 0 0 -0 1 3 1 -4 0 6 0 -1 -1 1 15 +3 4 +1+2i -1.5-1.1i 2.12 91+5i +-1+3i 1.2+3.5i -3.3 1+15i +12.31 1.3-5i 12.3i -78.3i \ No newline at end of file diff --git a/out.txt b/out.txt index 74ef871..b4d7a2e 100644 --- a/out.txt +++ b/out.txt @@ -1 +1 @@ --9.6 -18.2 6.4 \ No newline at end of file +6.733353-22.997542i -1.797607+2.084049i 15.699386+7.396011i \ No newline at end of file diff --git a/src/solver/Answer.java b/src/solver/Answer.java index ca5af7f..5f78592 100644 --- a/src/solver/Answer.java +++ b/src/solver/Answer.java @@ -14,13 +14,16 @@ */ public class Answer { private String fileNameToWrite; + private List answer; - private List createAnswer(double[][] gaussJordanMatrix){ - List answer = new ArrayList<>(); + private List createAnswer(Complex[][] gaussJordanMatrix){ + answer = new ArrayList<>(); for(int i = 0; i < gaussJordanMatrix.length; i++){ - double x = gaussJordanMatrix[i][gaussJordanMatrix[i].length-1]; - x = new BigDecimal(x).setScale(6, BigDecimal.ROUND_HALF_UP).doubleValue(); - answer.add(x); + double xReal = gaussJordanMatrix[i][gaussJordanMatrix[i].length-1].getRealPart(); + double xImaginary = gaussJordanMatrix[i][gaussJordanMatrix[i].length-1].getImaginaryPart(); + xReal = new BigDecimal(xReal).setScale(6, BigDecimal.ROUND_HALF_UP).doubleValue(); + xImaginary = new BigDecimal(xImaginary).setScale(6, BigDecimal.ROUND_HALF_UP).doubleValue(); + answer.add(new Complex(xReal, xImaginary)); } return answer; } @@ -29,11 +32,28 @@ private List createAnswer(double[][] gaussJordanMatrix){ this.fileNameToWrite = fileNameToWrite; } - void writeAnswer(double[][] gaussJordanMatrix){ - List answer = createAnswer(gaussJordanMatrix); + void writeAnswer(Complex[][] gaussJordanMatrix){ + List answer = createAnswer(gaussJordanMatrix); try (FileWriter fileWriter = new FileWriter(fileNameToWrite)){ - String s = answer.stream().map(String::valueOf).collect(Collectors.joining(" ")); - fileWriter.write(s); + StringBuilder sb = new StringBuilder(); + for(Complex c : answer){ + if(c.getRealPart() == 0 && c.getImaginaryPart() == 0){ + sb.append(0).append(" "); + continue; + } + if(c.getRealPart() != 0){ + sb.append(c.getRealPart()); + } + if(c.getImaginaryPart() != 0){ + if(c.getImaginaryPart() > 0){ + sb.append("+"); + } + sb.append(c.getImaginaryPart()).append("i"); + } + sb.append(" "); + } + //String s = answer.stream().map(String::valueOf).collect(Collectors.joining(" ")); + fileWriter.write(sb.toString().trim()); fileWriter.flush(); }catch (IOException e){ System.out.println("Wrong fileOut, please check"); @@ -51,8 +71,7 @@ void writeAnswer(String s){ } } - - - - + public List getAnswer() { + return answer; + } } diff --git a/src/solver/Complex.java b/src/solver/Complex.java new file mode 100644 index 0000000..f7eafe3 --- /dev/null +++ b/src/solver/Complex.java @@ -0,0 +1,147 @@ +package solver; + +/** + * Created by DIMA, on 16.01.2019 + */ +public class Complex { + private double realPart; + private double imaginaryPart; + + public Complex(double realPart, double imaginaryPart) { + this.realPart = realPart; + this.imaginaryPart = imaginaryPart; + } + + public Complex(String item){ + String[] items = item.split("[-,+]"); + int len = items.length; + double real = 0; + double imaginary = 0; + switch (len){ + case 3: + String[] items1 = item.split("\\+"); + if(items1[0].endsWith("i")){ + // -real && -imaginary + real = Double.parseDouble(items[1]) * -1; + imaginary = Double.parseDouble(items[2].substring(0, items[2].length()-1)) * -1; + }else { + // -real && imaginary + real = Double.parseDouble(items[1]) * -1; + imaginary = Double.parseDouble(items[2].substring(0, items[2].length()-1)); + } + break; + case 2: + if(items[0].equals("")){ + // -real || -imaginary + if(items[1].endsWith("i")){ + // -imaginary + imaginary = Double.parseDouble(items[1].substring(0, items[1].length()-1)) * -1; + real = 0; + }else { + // -real + real = Double.parseDouble(items[1]) * -1; + imaginary = 0; + } + }else { + // real && imaginary + items1 = item.split("\\+"); + if(items1[0].endsWith("i")){ + // real && -imaginary + real = Double.parseDouble(items[0]); + imaginary = Double.parseDouble(items[1].substring(0, items[1].length()-1)) * -1; + }else { + // real && imaginary + real = Double.parseDouble(items[0]); + imaginary = Double.parseDouble(items[1].substring(0, items[1].length()-1)); + } + + } + break; + case 1: + if(items[0].endsWith("i")){ + // imaginary + imaginary = Double.parseDouble(items[0].substring(0, items[0].length()-1)); + real = 0; + }else { + // real + real = Double.parseDouble(items[0]); + imaginary = 0; + } + break; + + } + this.realPart = real; + this.imaginaryPart = imaginary; + } + + public double getRealPart() { + return realPart; + } + + public double getImaginaryPart() { + return imaginaryPart; + } + + @Override + public String toString() { + String s = ""; + if(realPart != 0){ + s += realPart; + } + if(imaginaryPart > 0 && realPart != 0){ + return s + "+" + imaginaryPart + "i"; + }else if(imaginaryPart > 0 && realPart == 0){ + return imaginaryPart + "i"; + }else if(imaginaryPart < 0){ + return s + imaginaryPart + "i"; + }else if(realPart !=0 ){ + return s; + }else { + return "0"; + } + } + + public Complex adding(Complex c){ + double realC = c.realPart; + double imaginaryC = c.imaginaryPart; + double realResult = realPart + realC; + double imaginaryResult = imaginaryPart + imaginaryC; + return new Complex(realResult, imaginaryResult); + } + + public Complex subtracting(Complex c){ + double realC = c.realPart; + double imaginaryC = c.imaginaryPart; + double realResult = realPart - realC; + double imaginaryResult = imaginaryPart - imaginaryC; + return new Complex(realResult, imaginaryResult); + } + + + + public Complex multiply(Complex c){ + double realC = c.realPart; + double imaginaryC = c.imaginaryPart; + double realResult = realPart*realC - imaginaryPart*imaginaryC; + double imaginaryResult = realPart*imaginaryC + imaginaryPart*realC; + return new Complex(realResult, imaginaryResult); + } + + private Complex conjugating(Complex c){ + double realC = c.realPart; + double imaginaryC = c.imaginaryPart; + double imaginaryCResult = imaginaryC * (-1); + return new Complex(realC, imaginaryCResult); + } + + Complex divide(Complex divisor){ + Complex conjugate = conjugating(divisor); + Complex newDivident = multiply(conjugate); + double newDivisor = divisor.realPart*divisor.realPart + divisor.imaginaryPart*divisor.imaginaryPart; + return new Complex(newDivident.realPart/newDivisor, newDivident.imaginaryPart/newDivisor); + } + + Complex changeSign(){ + return multiply(new Complex(-1, 0)); + } +} diff --git a/src/solver/Main.java b/src/solver/Main.java index f873d9a..7ea575f 100644 --- a/src/solver/Main.java +++ b/src/solver/Main.java @@ -1,5 +1,10 @@ package solver; +import solver.specialCases.Helper; +import solver.specialCases.TesterResult; + +import java.util.Arrays; + public class Main { private String fileNameSource; @@ -9,14 +14,21 @@ public class Main { private Answer answer; public static void main(String[] args) { + //X:\Programming\IdeaProjects\linear-equations-solver\in.txt Main m = new Main(); m.fileNameSource = args[0]; m.fileNameAnswer = args[1]; m.matrix = new Matrix(m.fileNameSource); m.solver = new Solver(m.matrix); m.answer = new Answer(m.fileNameAnswer); + Complex[][] origMatrix = new Complex[m.matrix.getMatrix().length][m.matrix.getMatrix()[0].length]; + for(int row = 0; row < origMatrix.length; row++){ + for(int column = 0; column < origMatrix[row].length; column++){ + origMatrix[row][column] = m.matrix.getMatrix()[row][column]; + } + } - double[][] gaussJordanMatrix = m.solver.calcGaussJordan(m.matrix.getMatrix()); + Complex[][] gaussJordanMatrix = m.solver.calcGaussJordan(m.matrix.getMatrix()); if(m.solver.noSolutions){ m.answer.writeAnswer("No Solution"); @@ -26,7 +38,10 @@ public static void main(String[] args) { m.answer.writeAnswer(gaussJordanMatrix); } + + //============================TESTS======================// + //TesterResult.testingResult(origMatrix, m.answer.getAnswer()); } } \ No newline at end of file diff --git a/src/solver/Matrix.java b/src/solver/Matrix.java index 86d1af2..4747e29 100644 --- a/src/solver/Matrix.java +++ b/src/solver/Matrix.java @@ -10,16 +10,18 @@ * Created by DIMA, on 03.12.2018 */ public class Matrix { - private double[][] matrix; + private Complex[][] matrix; Matrix(String fileName){ try (Scanner scanner = new Scanner(new FileInputStream(fileName))){ int rows = scanner.nextInt(); int columns = scanner.nextInt(); - matrix = new double[rows][columns]; + matrix = new Complex[rows][columns]; for(int i = 0; i < rows; i++){ for (int j = 0; j < columns; j++){ - matrix[i][j] = scanner.nextDouble(); + String item = scanner.next(); + + matrix[i][j] = new Complex(item); } } }catch (FileNotFoundException e){ @@ -28,16 +30,16 @@ public class Matrix { } } - @Override +/* @Override public String toString() { return Arrays.stream(matrix) .map(i -> Arrays.stream(i).boxed() .map(String::valueOf) .collect(Collectors.joining(" "))) .collect(Collectors.joining("\n")); - } + }*/ - public double[][] getMatrix() { + public Complex[][] getMatrix() { return matrix; } } diff --git a/src/solver/Solver.java b/src/solver/Solver.java index 6866be5..470eec1 100644 --- a/src/solver/Solver.java +++ b/src/solver/Solver.java @@ -8,29 +8,30 @@ class Solver { boolean noSolutions = false; boolean infinitySolutions = false; - double[][] matrix; + Complex[][] matrix; public Solver(Matrix m){ matrix = m.getMatrix(); } - private double[][] calcGaussian(double[][] matrix){ + private Complex[][] calcGaussian(Complex[][] matrix){ + Complex[][] gaussMatrix = matrix; // 1*x1 - int matrixSize = matrix.length; + int matrixSize = gaussMatrix.length; for (int row = 0; row < matrixSize; row++){ - if(!Checker.isAllZero(row, matrix)){ - if(!Checker.hasMainNumber(row, matrix)){ - int findedRow = Searcher.searchRowDown(row,matrix); + if(!Checker.isAllZero(row, gaussMatrix)){ + if(!Checker.hasMainNumber(row, gaussMatrix)){ + int findedRow = Searcher.searchRowDown(row, gaussMatrix); if(findedRow != -1){ - Swapper.swapRows(row, findedRow, matrix); + Swapper.swapRows(row, findedRow, gaussMatrix); }else { - int findedColumn = Searcher.searchColumnRight(row, matrix); + int findedColumn = Searcher.searchColumnRight(row, gaussMatrix); if (findedColumn != -1){ - Swapper.swapColumns(row, findedColumn, matrix); + Swapper.swapColumns(row, findedColumn, gaussMatrix); SwapStore.addSwap(row, findedColumn); }else { - if(!Checker.isZeroInRightColumn(row, matrix)){ + if(!Checker.isZeroInRightColumn(row, gaussMatrix)){ noSolutions = true; return null; }else { @@ -40,46 +41,33 @@ private double[][] calcGaussian(double[][] matrix){ } } }else { - matrix = deleteRow(row, matrix); + gaussMatrix = deleteRow(row, gaussMatrix); row--; matrixSize--; continue; } if(row != 0){ - nullingRowGauss(row, matrix); + gaussMatrix = nullingRowGauss(row, gaussMatrix); } if(!Checker.isAllZero(row, matrix)){ - divideRowToOne(row, matrix[row][row], matrix); + gaussMatrix = divideRowToOne(row, gaussMatrix[row][row], gaussMatrix); } } - if(Checker.checkToNoSolution(matrix)){ + if(Checker.checkToNoSolution(gaussMatrix)){ noSolutions = true; return null; } - //Helper.print(matrix); - Swapper.unSwapAllC(SwapStore.swapStack, matrix); - matrix = deleteZeroRows(matrix); - if(Checker.checkToNoSolution(matrix)){ + Swapper.unSwapAllC(SwapStore.swapStack, gaussMatrix); + gaussMatrix = deleteZeroRows(gaussMatrix); + if(Checker.checkToNoSolution(gaussMatrix)){ noSolutions = true; return null; } - return matrix; - } - - private void nullingRowGauss(int row, double[][] matrix){ - for(int column = 0; column < row; column++){ - double multifactorXi = matrix[row][column]; - // -multiFactorXi * matrix[column] + matrix[row] - for(int k = 0; k < matrix[row].length; k++){ - double oldValue = matrix[column][k]; - double newValue = -oldValue*multifactorXi + matrix[row][k]; - matrix[row][k] = newValue; - } - } + return gaussMatrix; } - double[][] calcGaussJordan(double[][] matrix){ - double[][] matrixGausJordan = calcGaussian(matrix); + Complex[][] calcGaussJordan(Complex[][] matrix){ + Complex[][] matrixGausJordan = calcGaussian(matrix); if(noSolutions || matrixGausJordan == null) return null; //from row last but one for (int row = matrixGausJordan.length - 2; row >= 0; row--){ @@ -88,11 +76,11 @@ private void nullingRowGauss(int row, double[][] matrix){ // 0 1 d f // 0 0 1 k for (int column = row + 1; column < matrixGausJordan.length; column++){ - double multifactorXi = matrixGausJordan[row][column]; + Complex multy = matrixGausJordan[row][column]; for(int k = 0; k < matrixGausJordan[row].length; k++){ - double oldValue = matrixGausJordan[column][k]; - double newValue = -oldValue*multifactorXi + matrixGausJordan[row][k]; - matrixGausJordan[row][k] = newValue; + Complex old = matrixGausJordan[column][k]; + Complex newItem = old.changeSign().multiply(multy).adding(matrixGausJordan[row][k]); + matrixGausJordan[row][k] = newItem; } } } @@ -103,17 +91,33 @@ private void nullingRowGauss(int row, double[][] matrix){ return matrixGausJordan; } - private void divideRowToOne(int row, double devide, double[][] matrix){ + private Complex[][] divideRowToOne(int row, Complex divider, Complex[][] matrix){ + Complex[][] dividedMatrix = matrix; //if(row >= matrix[0].lenght) do nothing - if(row < matrix[0].length){ - for(int column = 0; column < matrix[row].length; column++){ - double item = matrix[row][column]; - matrix[row][column] = item/devide; + if(row < dividedMatrix[0].length){ + for(int column = 0; column < dividedMatrix[row].length; column++){ + Complex item = dividedMatrix[row][column]; + Complex newItem = item.divide(divider); + dividedMatrix[row][column] = newItem; } } + return dividedMatrix; + } + + private Complex[][] nullingRowGauss(int row, Complex[][] matrix){ + + for(int column = 0; column < row; column++){ + Complex multy = matrix[row][column]; + for(int k = 0; k < matrix[row].length; k++){ + Complex old = matrix[column][k]; + Complex newItem = old.changeSign().multiply(multy).adding(matrix[row][k]); + matrix[row][k] = newItem; + } + } + return matrix; } - private double[][] deleteZeroRows(double[][] matrix){ + private Complex[][] deleteZeroRows(Complex[][] matrix){ int matrixSize = matrix.length; for(int row = 0; row < matrixSize; row++){ if(Checker.isAllZero(row, matrix)){ @@ -126,8 +130,8 @@ private double[][] deleteZeroRows(double[][] matrix){ return matrix; } - private static double[][] deleteRow (int row, double[][] matrix){ - double[][] trimMatrix = new double[matrix.length-1][matrix[row].length]; + private Complex[][] deleteRow (int row, Complex[][] matrix){ + Complex[][] trimMatrix = new Complex[matrix.length-1][matrix[row].length]; for(int i = 0; i < row; i++){ for (int j = 0; j < matrix[i].length; j ++){ trimMatrix[i][j] = matrix[i][j]; diff --git a/src/solver/specialCases/Checker.java b/src/solver/specialCases/Checker.java index cace7c5..503eea4 100644 --- a/src/solver/specialCases/Checker.java +++ b/src/solver/specialCases/Checker.java @@ -1,38 +1,40 @@ package solver.specialCases; +import solver.Complex; + /** * Created by DIMA, on 07.12.2018 */ public class Checker { static final double DELTA_DOUBLE = 0.000001; - public static boolean hasMainNumber(int row, double[][] matrix){ + public static boolean hasMainNumber(int row, Complex[][] matrix){ if (row >= matrix[row].length) return true; - return Math.abs(matrix[row][row]) > DELTA_DOUBLE; + return Math.abs(matrix[row][row].getRealPart()) > DELTA_DOUBLE || Math.abs(matrix[row][row].getImaginaryPart()) > DELTA_DOUBLE; } - public static boolean isZeroInRightColumn(int row, double[][] matrix){ - return Math.abs(matrix[row][matrix[row].length - 1]) > DELTA_DOUBLE; + public static boolean isZeroInRightColumn(int row, Complex[][] matrix){ + return Math.abs(matrix[row][matrix[row].length - 1].getRealPart()) > DELTA_DOUBLE || Math.abs(matrix[row][matrix[row].length - 1].getImaginaryPart()) > DELTA_DOUBLE; } - public static boolean isAllZero(int row, double[][] matrix){ + public static boolean isAllZero(int row, Complex[][] matrix){ for (int column = 0; column < matrix[row].length; column++){ - if(matrix[row][column] > DELTA_DOUBLE) return false; + if(Math.abs(matrix[row][column].getRealPart()) > DELTA_DOUBLE || Math.abs(matrix[row][column].getImaginaryPart()) > DELTA_DOUBLE) return false; } return true; } - public static boolean checkToNoSolution(double[][] matrix){ + public static boolean checkToNoSolution(Complex[][] matrix){ for(int row = 0; row < matrix.length; row++){ boolean zeroInLeftSide = true; //check left side for(int column = 0; column < matrix[0].length - 1; column ++){ - if(Math.abs(matrix[row][column]) > DELTA_DOUBLE){ + if(Math.abs(matrix[row][column].getRealPart()) > DELTA_DOUBLE || Math.abs(matrix[row][column].getImaginaryPart()) > DELTA_DOUBLE){ zeroInLeftSide = false; } } if(zeroInLeftSide){ - if(Math.abs(matrix[row][matrix[row].length - 1]) > DELTA_DOUBLE){ + if(Math.abs(matrix[row][matrix[row].length - 1].getRealPart()) > DELTA_DOUBLE || Math.abs(matrix[row][matrix[row].length - 1].getImaginaryPart()) > DELTA_DOUBLE){ return true; } } diff --git a/src/solver/specialCases/Helper.java b/src/solver/specialCases/Helper.java index 965d148..f4f09a3 100644 --- a/src/solver/specialCases/Helper.java +++ b/src/solver/specialCases/Helper.java @@ -1,5 +1,7 @@ package solver.specialCases; +import solver.Complex; + import java.util.Arrays; import java.util.stream.Collectors; @@ -7,25 +9,28 @@ * Created by DIMA, on 14.01.2019 */ public class Helper { - public static void print(double matrix[][]){ + public static void print(Complex matrix[][]){ System.out.println("Start print"); - String s = Arrays.stream(matrix) - .map(i -> Arrays.stream(i).boxed() - .map(String::valueOf) - .collect(Collectors.joining(" "))) - .collect(Collectors.joining("\n")); - - System.out.println(s); - System.out.println("End print"); - } - - public static void roundInMatrix(double[][] matrix){ - for(int i = 0; i < matrix.length; i++){ - for(int j = 0; j < matrix[i].length; j++){ - if(Math.abs(matrix[i][j]) < Checker.DELTA_DOUBLE){ - matrix[i][j] = 0; + StringBuilder sb = new StringBuilder(); + for(int row = 0; row < matrix.length; row++){ + for(int column = 0; column < matrix[row].length; column++){ + sb.append(matrix[row][column].getRealPart()); + double imaginary = matrix[row][column].getImaginaryPart(); + if(imaginary > 0){ + sb.append("+"); } + if(imaginary == 0){ + sb.append(" "); + }else { + sb.append(imaginary).append("i"); + sb.append(" "); + } + } + sb.append("\n"); } + System.out.println(sb.toString()); + System.out.println("End print"); } + } diff --git a/src/solver/specialCases/Searcher.java b/src/solver/specialCases/Searcher.java index c58b546..a14365e 100644 --- a/src/solver/specialCases/Searcher.java +++ b/src/solver/specialCases/Searcher.java @@ -1,32 +1,26 @@ package solver.specialCases; +import solver.Complex; + /** * Created by DIMA, on 10.12.2018 */ public class Searcher { - public static int searchRowDown(int startRow, double[][] matrix){ + public static int searchRowDown(int startRow, Complex[][] matrix){ for(int i = startRow + 1; i < matrix.length; i ++){ - if(Math.abs(matrix[i][startRow]) > Checker.DELTA_DOUBLE){ + if(Math.abs(matrix[i][startRow].getRealPart()) > Checker.DELTA_DOUBLE || Math.abs(matrix[i][startRow].getImaginaryPart()) > Checker.DELTA_DOUBLE){ return i; } } return -1; } - public static int searchColumnRight(int row, double[][] matrix){ + public static int searchColumnRight(int row, Complex[][] matrix){ for(int column = row + 1; column < matrix[row].length - 1; column++){ - if(Math.abs(matrix[row][column]) > Checker.DELTA_DOUBLE){ + if(Math.abs(matrix[row][column].getRealPart()) > Checker.DELTA_DOUBLE || Math.abs(matrix[row][column].getImaginaryPart()) > Checker.DELTA_DOUBLE){ return column; } } return -1; } - -/* public static int[][] searchInBottomLeftCorner(int startRow, int startColumn, double[][] matrix){ - int[][] rowAndColumn = null; - for(int i = startRow + 1; i < matrix.length; i++){ - // for(int j = ) - } - return rowAndColumn; - }*/ } diff --git a/src/solver/specialCases/Swapper.java b/src/solver/specialCases/Swapper.java index b4837b6..b13973c 100644 --- a/src/solver/specialCases/Swapper.java +++ b/src/solver/specialCases/Swapper.java @@ -1,5 +1,7 @@ package solver.specialCases; +import solver.Complex; + import java.util.Deque; /** @@ -7,29 +9,29 @@ */ public class Swapper { - public static void swapColumns (int oldColumns, int newColumns, double[][] matrix){ + public static void swapColumns (int oldColumns, int newColumns, Complex[][] matrix){ for (int row = 0; row < matrix.length; row++){ - double tmp = matrix[row][newColumns]; + Complex tmp = matrix[row][newColumns]; matrix[row][newColumns] = matrix[row][oldColumns]; matrix[row][oldColumns] = tmp; } } - public static void swapRows(int oldRow, int newRow, double[][] matrix){ + public static void swapRows(int oldRow, int newRow, Complex[][] matrix){ for(int column = 0; column < matrix[oldRow].length; column++){ - double tmp = matrix[newRow][column]; + Complex tmp = matrix[newRow][column]; matrix[newRow][column] = matrix[oldRow][column]; matrix[oldRow][column] = tmp; } } - private static void unSwapColumns(Swap swap, double[][] matrix){ + private static void unSwapColumns(Swap swap, Complex[][] matrix){ int oldColumn = swap.getNewColumnsNumber(); int newColumn = swap.getOldColumnsNumber(); swapColumns (oldColumn, newColumn, matrix); } - public static void unSwapAllC(Deque swapDeque, double[][] matrix){ + public static void unSwapAllC(Deque swapDeque, Complex[][] matrix){ Swap swap; while ((swap = swapDeque.pollLast()) != null){ unSwapColumns(swap, matrix); diff --git a/src/solver/specialCases/TesterResult.java b/src/solver/specialCases/TesterResult.java new file mode 100644 index 0000000..0f33e0e --- /dev/null +++ b/src/solver/specialCases/TesterResult.java @@ -0,0 +1,26 @@ +package solver.specialCases; + +import solver.Complex; + +import java.math.BigDecimal; +import java.util.List; + +/** + * Created by DIMA, on 17.01.2019 + */ +public class TesterResult { + public static void testingResult(Complex[][] matrix, List answer){ + for(int row = 0; row < matrix.length; row++){ + Complex resultRow = matrix[row][0].multiply(answer.get(0)); + for(int column = 1; column < matrix[0].length-1; column++){ + resultRow = matrix[row][column].multiply(answer.get(column)).adding(resultRow); + } + double xReal = resultRow.getRealPart(); + double xImaginary = resultRow.getImaginaryPart(); + xReal = new BigDecimal(xReal).setScale(5, BigDecimal.ROUND_HALF_UP).doubleValue(); + xImaginary = new BigDecimal(xImaginary).setScale(5, BigDecimal.ROUND_HALF_UP).doubleValue(); + resultRow = new Complex(xReal, xImaginary); + System.out.println(resultRow + " = " + matrix[row][matrix[0].length-1]); + } + } +} diff --git a/src/solver/tmpTests/CopyArr.java b/src/solver/tmpTests/CopyArr.java index 0165872..6933215 100644 --- a/src/solver/tmpTests/CopyArr.java +++ b/src/solver/tmpTests/CopyArr.java @@ -15,10 +15,10 @@ public static void main(String[] args) { double[][] a3; a2 = Arrays.copyOf(a1, 2); - Helper.print(a2); + //Helper.print(a2); a3 = Arrays.copyOfRange(a1, 3, a1.length); - Helper.print(a3); + //Helper.print(a3); diff --git a/src/solver/tmpTests/TestSplit.java b/src/solver/tmpTests/TestSplit.java new file mode 100644 index 0000000..6b7e314 --- /dev/null +++ b/src/solver/tmpTests/TestSplit.java @@ -0,0 +1,78 @@ +package solver.tmpTests; + +import solver.Complex; + +/** + * Created by DIMA, on 16.01.2019 + */ +public class TestSplit { + + private static Complex parseComplexString(String item){ + String[] items = item.split("[-,+]"); + int len = items.length; + double real = 0; + double imaginary = 0; + switch (len){ + case 3: + String[] items1 = item.split("\\+"); + if(items1[0].endsWith("i")){ + // -real && -imaginary + real = Double.parseDouble(items[1]) * -1; + imaginary = Double.parseDouble(items[2].substring(0, items[2].length()-1)) * -1; + }else { + // -real && imaginary + real = Double.parseDouble(items[1]) * -1; + imaginary = Double.parseDouble(items[2].substring(0, items[2].length()-1)); + } + break; + case 2: + if(items[0].equals("")){ + // -real || -imaginary + if(items[1].endsWith("i")){ + // -imaginary + imaginary = Double.parseDouble(items[1].substring(0, items[1].length()-1)) * -1; + real = 0; + }else { + // -real + real = Double.parseDouble(items[1]) * -1; + imaginary = 0; + } + }else { + // real && imaginary + items1 = item.split("\\+"); + if(items1[0].endsWith("i")){ + // real && -imaginary + real = Double.parseDouble(items[0]); + imaginary = Double.parseDouble(items[1].substring(0, items[1].length()-1)) * -1; + }else { + // real && imaginary + real = Double.parseDouble(items[0]); + imaginary = Double.parseDouble(items[1].substring(0, items[1].length()-1)); + } + + } + break; + case 1: + if(items[0].endsWith("i")){ + // imaginary + imaginary = Double.parseDouble(items[0].substring(0, items[0].length()-1)); + real = 0; + }else { + // real + real = Double.parseDouble(items[0]); + imaginary = 0; + } + break; + + } + return new Complex(real, imaginary); + } + + public static void main(String[] args) { + String[] items = {"1.5-1.1i", "-2.3i", "-1.6-2.6i", "-2.3", "5.6i", "5.6", "1.6+5.6i"}; + for(String item : items){ + System.out.println(parseComplexString(item)); + } + + } +}