Last active
May 14, 2018 20:53
-
-
Save holubv/bdf97620093612f7997b1a847d4549ad to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.gmail.holubvojtech.consoleapps.gauss; | |
public class Matrix { | |
private double[][] mat; //double [y][x] | |
private int cols; //max x | |
private int rows; //max y | |
public Matrix(double[][] mat) { | |
this.mat = mat; | |
this.cols = mat[0].length; | |
this.rows = mat.length; | |
} | |
public static void main(String[] args) { | |
// 2x + y - z = 8 | |
// -3x - y + 2z = -11 | |
// -2x + y + 2z = -3 | |
Matrix m = new Matrix(new double[][]{ | |
{2, 1, -1}, | |
{-3, -1, 2}, | |
{-2, 1, 2}, | |
}); | |
Matrix aug = new Matrix(new double[][]{ | |
{8}, | |
{-11}, | |
{-3}, | |
}); | |
System.out.println(m.eliminate(aug)); | |
//2.0, | |
//3.0, | |
//-1.0, | |
System.out.println(m.inverse()); | |
//4.0, 3.0, -1.0, | |
//-2.0, -2.0, 1.0, | |
//5.0, 4.0, -1.0, | |
} | |
public Row row(int y) { | |
return new Row(y); | |
} | |
public Matrix identity() { | |
if (cols != rows) { | |
throw new IllegalArgumentException("source matrix is not square matrix"); | |
} | |
double[][] identity = new double[rows][cols]; | |
for (int x = 0; x < cols; x++) { | |
identity[x][x] = 1; | |
} | |
return new Matrix(identity); | |
} | |
public Matrix inverse() { | |
return this.eliminate(this.identity()); | |
} | |
public Matrix eliminate(Matrix m) { | |
Matrix matrix = this.augment(m); | |
for (int y = 0; y < this.rows; y++) { | |
double diagonal = matrix.mat[y][y]; | |
if (diagonal == 0) { | |
//zero on diagonal, swap rows | |
for (int i = y + 1; i < this.rows; i++) { | |
if (matrix.mat[i][i] != 0) { | |
matrix.swapRows(y, i); | |
diagonal = matrix.mat[y][y]; //update | |
break; | |
} | |
} | |
if (diagonal == 0) { | |
System.out.println(matrix); | |
if (matrix.row(y).isZero()) { | |
//whole augmented matrix row is zero | |
throw new IllegalArgumentException("infinite solutions"); | |
} | |
if (matrix.subMatrix(0, y, this.cols, 1).row(0).isZero()) { | |
//only the left part of augmented matrix is zero | |
throw new IllegalArgumentException("no solutions"); | |
} | |
throw new Error("unreachable"); | |
} | |
} | |
Row curr = matrix.row(y); | |
for (int i = y + 1; i < this.rows; i++) { | |
double k = matrix.mat[i][y]; | |
matrix.row(i).add(curr.copy().multiply(-(k / diagonal))); | |
} | |
curr.multiply(1 / diagonal); | |
} | |
//System.out.println(matrix); | |
for (int y = this.rows - 1; y >= 0; y--) { | |
double diagonal = matrix.mat[y][y]; | |
Row curr = matrix.row(y); | |
for (int i = y - 1; i >= 0; i--) { | |
double k = matrix.mat[i][y]; | |
matrix.row(i).add(curr.copy().multiply(-(k / diagonal))); | |
} | |
} | |
return matrix.subMatrix(this.cols, 0, m.cols, this.rows); | |
} | |
public Matrix augment(Matrix right) { | |
if (this.rows != right.rows) { | |
throw new IllegalArgumentException("cannot augment matrix"); | |
} | |
double mat[][] = new double[this.rows][this.cols + right.cols]; | |
for (int y = 0; y < this.rows; y++) { | |
int tx = 0; | |
for (int x = 0; x < this.cols; x++, tx++) { | |
mat[y][tx] = this.mat[y][x]; | |
} | |
for (int x = 0; x < right.cols; x++, tx++) { | |
mat[y][tx] = right.mat[y][x]; | |
} | |
} | |
return new Matrix(mat); | |
} | |
public Matrix subMatrix(int srcX, int srcY, int cols, int rows) { | |
double[][] mat = new double[rows][cols]; | |
for (int j = 0; j < rows; j++, srcY++) { | |
int x = srcX; | |
for (int i = 0; i < cols; i++, x++) { | |
mat[j][i] = this.mat[srcY][x]; | |
} | |
} | |
return new Matrix(mat); | |
} | |
public Matrix swapRows(int y1, int y2) { | |
double[] tmp = mat[y1]; | |
mat[y1] = mat[y2]; | |
mat[y2] = tmp; | |
return this; | |
} | |
@Override | |
public String toString() { | |
StringBuilder sb = new StringBuilder(); | |
for (int y = 0; y < rows; y++) { | |
for (int x = 0; x < cols; x++) { | |
sb.append(mat[y][x]).append(", "); | |
} | |
sb.append("\n"); | |
} | |
return sb.toString(); | |
} | |
public class Row { | |
private int y; | |
private double[] row; | |
private Row(int y) { | |
this.y = y; | |
this.row = mat[y]; | |
} | |
public Row copy() { | |
Row copy = new Row(y); | |
copy.row = new double[cols]; | |
System.arraycopy(this.row, 0, copy.row, 0, cols); | |
return copy; | |
} | |
public Row multiply(double k) { | |
for (int x = 0; x < cols; x++) { | |
this.row[x] *= k; | |
} | |
return this; | |
} | |
public Row add(Row row) { | |
for (int x = 0; x < cols; x++) { | |
this.row[x] += row.row[x]; | |
} | |
return this; | |
} | |
public boolean isZero() { | |
for (int x = 0; x < cols; x++) { | |
if (this.row[x] != 0) { | |
return false; | |
} | |
} | |
return true; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment