diff --git a/.idea/misc.xml b/.idea/misc.xml
index a165cb3..cbb200f 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,6 +1,6 @@
-
+
\ No newline at end of file
diff --git a/.idea/project.iml b/.idea/project.iml
index 47baa8c..d34aa22 100644
--- a/.idea/project.iml
+++ b/.idea/project.iml
@@ -6,5 +6,14 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
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
diff --git a/out.txt b/out.txt
new file mode 100644
index 0000000..5f5fbe7
--- /dev/null
+++ b/out.txt
@@ -0,0 +1,3 @@
+1
+2
+3
\ No newline at end of file
diff --git a/src/solver/AugmentedMatrix.java b/src/solver/AugmentedMatrix.java
new file mode 100644
index 0000000..7254eb5
--- /dev/null
+++ b/src/solver/AugmentedMatrix.java
@@ -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;
+ }
+
+
+}
diff --git a/src/solver/LinearEquationSolver.java b/src/solver/LinearEquationSolver.java
new file mode 100644
index 0000000..7efca22
--- /dev/null
+++ b/src/solver/LinearEquationSolver.java
@@ -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++) {
+ currentRow = matrix.getRow(i);
+ normalizeRowsForTransforming(i, currentRow);
+ for(int j = i + 1; j < n; j++) {
+ 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) {
+ matrix.getRow(j).normalizeRow(i);
+ logMessage(String.format("R%d / %s - R%d -> R%d", j, new DecimalFormat("#.###").format(coefficient), i, j));
+ } 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) {
+ 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) {
+ sb.append(new DecimalFormat("#.####").format(coefficient));
+ sb.append("\n");
+ }
+ sb.deleteCharAt(sb.length()-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++) {
+ result[i] = matrix.get(i, m-1);
+ }
+ return this;
+ }
+
+ public AugmentedMatrix getMatrix() {
+ return matrix;
+ }
+}
diff --git a/src/solver/Main.java b/src/solver/Main.java
index 4404714..f8c115c 100644
--- a/src/solver/Main.java
+++ b/src/solver/Main.java
@@ -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" +
+ "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) {
- 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)) {
+ 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");
+ }
}
}
\ No newline at end of file
diff --git a/src/solver/Row.java b/src/solver/Row.java
new file mode 100644
index 0000000..e2d59a2
--- /dev/null
+++ b/src/solver/Row.java
@@ -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) {
+ // 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");
+ }
+ 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;
+ }
+}