Skip to content

Instantly share code, notes, and snippets.

@holubv
Last active May 14, 2018 20:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save holubv/bdf97620093612f7997b1a847d4549ad to your computer and use it in GitHub Desktop.
Save holubv/bdf97620093612f7997b1a847d4549ad to your computer and use it in GitHub Desktop.
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