-
Notifications
You must be signed in to change notification settings - Fork 12
Module 3 LinearEquationSolver #8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| 3 | ||
| 1 1 2 9 | ||
| 2 4 -3 1 | ||
| 3 6 -5 0 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| 1 | ||
| 2 | ||
| 3 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,79 @@ | ||
| package solver; | ||
|
|
||
| import java.util.Arrays; | ||
| import java.util.InputMismatchException; | ||
| import java.util.Scanner; | ||
|
|
||
| public class AugmentedMatrix { | ||
| private Row[] matrix; | ||
|
|
||
| AugmentedMatrix(double[][] matrix) { | ||
| setMatrix(matrix); | ||
| } | ||
|
|
||
| AugmentedMatrix() {} | ||
|
|
||
| public void readMatrix(Scanner scanner) throws InputMismatchException { | ||
| int n = scanner.nextInt(); | ||
| int m = n+1; | ||
| matrix = new Row[n]; | ||
| for (int i = 0; i < n; i++) { | ||
| matrix[i] = new Row(m); | ||
| for (int j = 0; j < m; j++) { | ||
| this.set(i, j, scanner.nextDouble()); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| public void set(int i, int j, double value) { | ||
| matrix[i].set(j, value); | ||
| } | ||
|
|
||
| public double get(int i, int j) { | ||
| return matrix[i].get(j); | ||
| } | ||
|
|
||
| @Override | ||
| public String toString() { | ||
| StringBuilder sb = new StringBuilder(); | ||
| for(int i = 0; i < matrix.length; i++) { | ||
| sb.append(Arrays.toString(matrix[i].getRow())); | ||
| sb.append("\n"); | ||
| } | ||
| return sb.toString(); | ||
| } | ||
|
|
||
|
|
||
| public double[][] getMatrix() { | ||
| double[][] copy = new double[matrix.length][]; | ||
| for(int i = 0; i < matrix.length; i++) { | ||
| copy[i] = matrix[i].getRow(); | ||
| } | ||
| return copy; | ||
| } | ||
|
|
||
| public void setMatrix(double[][] matrix) { | ||
| this.matrix = new Row[matrix.length]; | ||
| for(int i = 0; i < matrix.length; i++) { | ||
| this.matrix[i] = new Row(matrix[i]); | ||
| } | ||
| } | ||
|
|
||
| public Row getRow(int index) { | ||
| return this.matrix[index]; | ||
| } | ||
|
|
||
| /** | ||
| * Get dimensions of Augmented matrix | ||
| * @return size()[0] - number of rows, size()[1] - number of columns | ||
| */ | ||
| public int[] size() { | ||
| int[] size = new int[2]; | ||
| size[0] = matrix.length; | ||
| // Consider that all rows have the same size, according to the class initialization | ||
| size[1] = matrix[0].size(); | ||
| return size; | ||
| } | ||
|
|
||
|
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,115 @@ | ||
| package solver; | ||
|
|
||
| import java.text.DecimalFormat; | ||
|
|
||
| public class LinearEquationSolver { | ||
| private AugmentedMatrix matrix; | ||
| private StringBuilder logs; | ||
| private double[] result; | ||
|
|
||
| LinearEquationSolver(AugmentedMatrix matrix) { | ||
| this.matrix = new AugmentedMatrix(matrix.getMatrix()); | ||
| this.logs = new StringBuilder(); | ||
| } | ||
|
|
||
| private void transformToUpperTriangularForm() { | ||
| Row currentRow; | ||
| int n = matrix.size()[0]; | ||
| for(int i = 0; i < n; i++) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Need space after "for" |
||
| currentRow = matrix.getRow(i); | ||
| normalizeRowsForTransforming(i, currentRow); | ||
| for(int j = i + 1; j < n; j++) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Need space after "for" |
||
| subtractRowsForTransforming(i,j,currentRow); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| private void transformToLowerTriangularForm() { | ||
| Row currentRow; | ||
| int n = matrix.size()[0]; | ||
| for(int i = n-1; i >= 0; i--) { | ||
| currentRow = matrix.getRow(i); | ||
| normalizeRowsForTransforming(i, currentRow); | ||
| for(int j = i-1; j >= 0; j--) { | ||
| subtractRowsForTransforming(i,j,currentRow); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| private void tranformToDiagonalForm() { | ||
| transformToUpperTriangularForm(); | ||
| transformToLowerTriangularForm(); | ||
| } | ||
|
|
||
| private void logMessage(String msg) { | ||
| logs.append(msg); | ||
| logs.append("\n"); | ||
| } | ||
|
|
||
| /** | ||
| * Devide every element of matrix[j] row by the element at position i, subtracts currentRow from matrix[j] | ||
| * and logs results | ||
| * (was originally created to move duplicating code from methods) | ||
| * @param i | ||
| * @param j | ||
| * @param currentRow | ||
| */ | ||
| private void subtractRowsForTransforming(int i, int j, Row currentRow) { | ||
| double coefficient = matrix.getRow(j).get(i); | ||
| if(coefficient != 1.0) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Need space after "if" |
||
| matrix.getRow(j).normalizeRow(i); | ||
| logMessage(String.format("R%d / %s - R%d -> R%d", j, new DecimalFormat("#.###").format(coefficient), i, j)); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So you are better off having static String variable with "#.###" |
||
| } else { | ||
| logMessage(String.format("R%d - R%d -> R%d", j, i, j)); | ||
| } | ||
| matrix.getRow(j).subtract(currentRow); | ||
| } | ||
|
|
||
| /** | ||
| * Divide every element of the row by the element at position `i` and logs results | ||
| * (was originally created to move duplicating code from methods) | ||
| * @param i index of the element at the row | ||
| * @param currentRow | ||
| */ | ||
| private void normalizeRowsForTransforming(int i, Row currentRow) { | ||
| double coefficient = currentRow.get(i); | ||
| if(coefficient != 1.0) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Need space after "if" |
||
| currentRow.normalizeRow(i); | ||
| logMessage(String.format("R%d / %s -> R%d", i, new DecimalFormat("#.###").format(coefficient), i)); | ||
| } | ||
| } | ||
|
|
||
| public String getLogs() { | ||
| return this.logs.toString(); | ||
| } | ||
|
|
||
| public double[] getResult() { | ||
| return result; | ||
| } | ||
|
|
||
| public String getResultString() { | ||
| StringBuilder sb = new StringBuilder(); | ||
| for(double coefficient: result) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Need space after "for" |
||
| sb.append(new DecimalFormat("#.####").format(coefficient)); | ||
| sb.append("\n"); | ||
| } | ||
| sb.deleteCharAt(sb.length()-1); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Need spaces after "sb.length()" and before "-1" |
||
| return sb.toString(); | ||
| } | ||
|
|
||
| public LinearEquationSolver solve() { | ||
| tranformToDiagonalForm(); | ||
| // Get coefficients of the last column | ||
| int n = this.matrix.size()[0]; | ||
| int m = this.matrix.size()[1]; | ||
| result = new double[n]; | ||
| for(int i = 0; i < n; i++) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Need space after "for" |
||
| result[i] = matrix.get(i, m-1); | ||
| } | ||
| return this; | ||
| } | ||
|
|
||
| public AugmentedMatrix getMatrix() { | ||
| return matrix; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,98 @@ | ||
| package solver; | ||
|
|
||
| import java.io.File; | ||
| import java.io.FileNotFoundException; | ||
| import java.io.FileWriter; | ||
| import java.io.IOException; | ||
| import java.util.InputMismatchException; | ||
| import java.util.Scanner; | ||
|
|
||
| public class Main { | ||
|
|
||
| static String getHelp() { | ||
| String helpMsg = "This program is intended to solve Linear Equations with any amount of variables using Gauss-Jordan Elimination. \n\n" + | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. User StringBuilder (of course the compiler will use StringBuilder automatically, but the usage of it is more look like Builder pattern). |
||
| "Options: " + | ||
| "\n\t * -in [pathToFile] reads file with the first number - number of equations and variables, and augmented matrix of linear equation" + | ||
| "\n\t * -out [pathToFile] writes results to the output file " + | ||
| "\n\t * -h shows help information " + | ||
| "\n\nExample: \njava Solver -in in.txt -out out.txt" + | ||
| "\n\nExample of in.txt:\n" + | ||
| "3\n" + | ||
| "1 1 2 9\n" + | ||
| "2 4 -3 1\n" + | ||
| "3 6 -5 0"; | ||
| return helpMsg; | ||
| } | ||
|
|
||
| /** | ||
| * Program should start with necessary options -in [pathToFileWithMatrix] and -out [pathToOutputFile] | ||
| * Example: > java Solver -in in.txt -out out.txt | ||
| * @param args | ||
| */ | ||
| public static void main(String[] args) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Method main is very big. If your method does two or three different things at a time then you should consider splitting the functionality of this method into other methods (single responsibility principle) and just try to make your methods as small as possible. |
||
| System.out.print("Hello world!"); | ||
| // Getting and handling console parameters | ||
| String inputFile=""; | ||
| String outputFile=""; | ||
| for(int i = 0; i < args.length; i++) { | ||
| try { | ||
| switch (args[i]) { | ||
| case "-in": | ||
| inputFile = args[i + 1]; | ||
| break; | ||
| case "-out": | ||
| outputFile = args[i + 1]; | ||
| break; | ||
| case "-h" : | ||
| System.out.println(getHelp()); | ||
| return; | ||
|
|
||
| } | ||
| } catch (ArrayIndexOutOfBoundsException e) { | ||
| System.err.println("Invalid command line options, use '-h' option to see help"); | ||
| return; | ||
| } | ||
| } | ||
|
|
||
| if(inputFile.isEmpty() || outputFile.isEmpty()) { | ||
| System.err.println("Invalid command line options, use '-h' option to see help"); | ||
| return; | ||
| } | ||
|
|
||
| System.out.println("Input File: " + inputFile + "\nOutput File: " + outputFile); | ||
|
|
||
| // Working with input file | ||
| File file = new File(inputFile); | ||
| AugmentedMatrix matrix = new AugmentedMatrix(); | ||
| try(Scanner fileScanner = new Scanner(file);) { | ||
| matrix.readMatrix(fileScanner); | ||
| } catch(FileNotFoundException e) { | ||
| System.out.println("File: " + file.getAbsolutePath() + " doesn't exist"); | ||
| return; | ||
| } catch (InputMismatchException e) { | ||
| System.err.println("Invalid structure of input file: " + file.getAbsolutePath()); | ||
| return; | ||
| } | ||
|
|
||
| // Input matrix output | ||
| System.out.println("Input matrix:"); | ||
| System.out.println(matrix); | ||
|
|
||
|
|
||
| // Solving equation | ||
| System.out.println("Start solving linear equation."); | ||
| LinearEquationSolver solver = new LinearEquationSolver(matrix); | ||
| String res = solver.solve().getResultString(); | ||
| System.out.println("Rows manipulation:"); | ||
| System.out.println(solver.getLogs()); | ||
|
|
||
| System.out.println("The solution is: (" + res.replaceAll("\n", ", ") + ")"); | ||
|
|
||
| // Output writing | ||
| try(FileWriter fileWriter = new FileWriter(outputFile)) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Need space after "try" |
||
| fileWriter.write(res); | ||
| System.out.println("Saved to " + outputFile); | ||
| } catch(IOException e) { | ||
| System.err.println("Result cannot be written to the output file, please try other output file"); | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,62 @@ | ||
| package solver; | ||
|
|
||
| import java.util.Arrays; | ||
|
|
||
| public class Row { | ||
| private double[] row; | ||
|
|
||
| Row(double[] row) { | ||
| setRow(row); | ||
| } | ||
|
|
||
| Row(int m) { | ||
| row = new double[m]; | ||
| } | ||
|
|
||
| Row normalizeRow(int index) { | ||
| try { | ||
| return divide(row[index]); | ||
| } catch (ArithmeticException e) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use the word "ignore" after the ArithmeticException keyword. |
||
| // Ignore | ||
| // Row cannot be normalized to the zero element | ||
| return this; | ||
| } | ||
| } | ||
|
|
||
| Row divide(double v) { | ||
| if(v == 0){ | ||
| throw new java.lang.ArithmeticException("Division by zero"); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you can simply write: throw new ArithmeticException("Division by zero"); |
||
| } | ||
| for(int i = 0; i < row.length; i++) { | ||
| row[i] = row[i] / v; | ||
| } | ||
| return this; | ||
| } | ||
|
|
||
| Row subtract(Row row) { | ||
| for(int i = 0; i < this.row.length; i++) { | ||
| this.row[i] = this.row[i] - row.get(i); | ||
| } | ||
| return this; | ||
| } | ||
|
|
||
| public double[] getRow() { | ||
| return Arrays.copyOf(row, row.length); | ||
| } | ||
|
|
||
| public void setRow(double[] row) { | ||
| this.row = Arrays.copyOf(row, row.length); | ||
| } | ||
|
|
||
| public void set(int j, double value) { | ||
| this.row[j] = value; | ||
| } | ||
|
|
||
| public double get(int j) { | ||
| return this.row[j]; | ||
| } | ||
|
|
||
| public int size() { | ||
| return this.row.length; | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Never use only one letter in the name. Variable should represent the value it was created for.