Gauss-Jordan matrix inversion

Gauss-Jordan matrix inversion

Gauss-Jordan matrix inversion is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

Invert matrix   A   using Gauss-Jordan method.

A   being an   n by n   matrix.

C#

<lang csharp> using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;

namespace Rosetta {

```   internal class Vector
{
private double[] b;
```
```       internal Vector(int rows)
{
this.rows = rows;
b = new double[rows];
}
```
```       internal Vector(double[] initArray)
{
b = (double[])initArray.Clone();
rows = b.Length;
}
```
```       internal Vector Clone()
{
Vector v = new Vector(b);
return v;
}
```
```       internal double this[int row]
{
get { return b[row]; }
set { b[row] = value; }
}
```
```       internal void SwapRow(int r1, int r2)
{
if (r1 == r2) return;
double tmp = b[r1];
b[r1] = b[r2];
b[r2] = tmp;
}
```
```       internal double norm()
{
throw new NotImplementedException();
}
```
```       internal double norm(double[] weights)
{
double sum = 0;
for (int i = 0; i < rows; i++)
{
double d = b[i] * weights[i];
sum +=  d*d;
}
return Math.Sqrt(sum);
}
```
```       internal void print()
{
for (int i = 0; i < rows; i++)
Console.WriteLine(b[i]);
}
```
```       public static Vector operator-(Vector lhs, Vector rhs)
{
Vector v = new Vector(lhs.rows);
for (int i = 0; i < lhs.rows; i++)
v[i] = lhs[i] - rhs[i];
return v;
}
}
```
```   class Matrix
{
private double[] b;
```
```       internal Matrix(int rows, int cols)
{
this.rows = rows;
this.cols = cols;
b = new double[rows * cols];
}
```
```       internal Matrix(int size)
{
this.rows = size;
this.cols = size;
b = new double[rows * cols];
for (int i = 0; i < size; i++)
this[i, i] = 1;
}
```
```       internal Matrix(int rows, int cols, double[] initArray)
{
this.rows = rows;
this.cols = cols;
b = (double[])initArray.Clone();
if (b.Length != rows * cols) throw new Exception("bad init array");
}
```
```       internal double this[int row, int col]
{
get { return b[row * cols + col]; }
set { b[row * cols + col] = value; }
}
```
```       public static Vector operator*(Matrix lhs, Vector rhs)
{
if (lhs.cols != rhs.rows) throw new Exception("I can't multiply matrix by vector");
Vector v = new Vector(lhs.rows);
for (int i = 0; i < lhs.rows; i++)
{
double sum = 0;
for (int j = 0; j < rhs.rows; j++)
sum += lhs[i,j]*rhs[j];
v[i] = sum;
}
return v;
}
```
```       internal void SwapRow(int r1, int r2)
{
if (r1 == r2) return;
int firstR1 = r1 * cols;
int firstR2 = r2 * cols;
for (int i = 0; i < cols; i++)
{
double tmp = b[firstR1 + i];
b[firstR1 + i] = b[firstR2 + i];
b[firstR2 + i] = tmp;
}
}
```
```       internal Matrix Inv()
{
if (rows != cols) throw new Exception("rows != cols for Inv");
Matrix M = new Matrix(rows); //unitary
// do partial pivoting
for (int dia = 0; dia < cols; dia++)
{
int max_row = dia;
double max = this[dia, dia];
```
```               double tmp;
for (int row = dia + 1; row < rows; row++)
if ((tmp = Math.Abs(this[row, dia])) > max)
{
max_row = row;
max = tmp;
}
SwapRow(dia, max_row);
M.SwapRow(dia, max_row);
}
```
```           // change first matrix to diagonal; second matrix follows
for (int row = 0; row < rows; row++)
{
for (int r = 0; r < rows; r++)
if (r != row)
{
double ratio = this[r,row] / this[row,row];
for (int k = 0; k < cols; k++)
{
this[r, k] -= this[row, k] * ratio;
M[r, k] -= M[row, k] * ratio;
}
}
}
//reducing to unit matrix
for (int row = 0; row < rows; row++)
{
double ratio = this[row,row];
for (int col = 0; col < cols; col++)
{
this[row, col] = this[row, col] / ratio;
M[row, col] = M[row, col] / ratio;
}
}
return M;
}
```
```       internal void print()
{
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
Console.Write(this[i,j].ToString()+"  ");
Console.WriteLine();
}
}
}
```

} </lang> <lang csharp> using System;

namespace Rosetta {

```   class Program
{
static void Main(string[] args)
{
Matrix M = new Matrix(3, 3, new double[] { 1, 2, 3, 4, 1, 6, 7, 8, 9 });
M.Inv().print();
}
}
```

} </lang>

Output:
```
-0.8125  0.125  0.1875
0.125  -0.25  0.125
0.520833333333333  0.125  -0.145833333333333

```

Julia

Works with: Julia version 0.6

Built-in LAPACK-based linear solver uses partial-pivoted Gauss elimination): <lang julia>A = [1 2 3; 4 1 6; 7 8 9] @show I / A @show inv(A)</lang>

Native implementation: <lang julia>function gaussjordan(A::Matrix)

```   size(A, 1) == size(A, 2) || throw(ArgumentError("A must be squared"))
n = size(A, 1)
M = [convert(Matrix{float(eltype(A))}, A) I]
i = 1
local tmp = Vector{eltype(M)}(2n)
# forward
while i ≤ n
if M[i, i] ≈ 0.0
local j = i + 1
while j ≤ n && M[j, i] ≈ 0.0
j += 1
end
if j ≤ n
tmp     .= M[i, :]
M[i, :] .= M[j, :]
M[j, :] .= tmp
else
throw(ArgumentError("matrix is singular, cannot compute the inverse"))
end
end
for j in (i + 1):n
M[j, :] .-= M[j, i] / M[i, i] .* M[i, :]
end
i += 1
end
i = n
# backward
while i ≥ 1
if M[i, i] ≈ 0.0
local j = i - 1
while j ≥ 1 && M[j, i] ≈ 0.0
j -= 1
end
if j ≥ 1
tmp     .= M[i, :]
M[i, :] .= M[j, :]
M[j, :] .= tmp
else
throw(ArgumentError("matrix is singular, cannot compute the inverse"))
end
end
for j in (i - 1):-1:1
M[j, :] .-= M[j, i] / M[i, i] .* M[i, :]
end
i -= 1
end
M ./= diag(M) # normalize
return M[:, n+1:2n]
```

end

@show gaussjordan(A) @assert gaussjordan(A) ≈ inv(A)

A = rand(10, 10) @assert gaussjordan(A) ≈ inv(A)</lang>

Output:
```I / A = [-0.8125 0.125 0.1875; 0.125 -0.25 0.125; 0.520833 0.125 -0.145833]
inv(A) = [-0.8125 0.125 0.1875; 0.125 -0.25 0.125; 0.520833 0.125 -0.145833]
gaussjordan(A) = [-0.8125 0.125 0.1875; 0.125 -0.25 0.125; 0.520833 0.125 -0.145833]```

Kotlin

This follows the description of Gauss-Jordan elimination in Wikipedia whereby the original square matrix is first augmented to the right by its identity matrix, its reduced row echelon form is then found and finally the identity matrix to the left is removed to leave the inverse of the original square matrix. <lang scala>// version 1.2.21

typealias Matrix = Array<DoubleArray>

fun Matrix.inverse(): Matrix {

```   val len = this.size
require(this.all { it.size == len }) { "Not a square matrix" }
val aug = Array(len) { DoubleArray(2 * len) }
for (i in 0 until len) {
for (j in 0 until len) aug[i][j] = this[i][j]
// augment by identity matrix to right
aug[i][i + len] = 1.0
}
aug.toReducedRowEchelonForm()
val inv = Array(len) { DoubleArray(len) }
// remove identity matrix to left
for (i in 0 until len) {
for (j in len until 2 * len) inv[i][j - len] = aug[i][j]
}
return inv
```

}

fun Matrix.toReducedRowEchelonForm() {

```   var lead = 0
val rowCount = this.size
val colCount = this[0].size
for (r in 0 until rowCount) {
var i = r
```
```       while (this[i][lead] == 0.0) {
i++
if (rowCount == i) {
i = r
}
}
```
```       val temp = this[i]
this[i] = this[r]
this[r] = temp
```
```       if (this[r][lead] != 0.0) {
for (j in 0 until colCount) this[r][j] /= div
}
```
```       for (k in 0 until rowCount) {
if (k != r) {
for (j in 0 until colCount) this[k][j] -= this[r][j] * mult
}
}
```
```       lead++
}
```

}

fun Matrix.printf(title: String) {

```   println(title)
val rowCount = this.size
val colCount = this[0].size
```
```   for (r in 0 until rowCount) {
for (c in 0 until colCount) {
if (this[r][c] == -0.0) this[r][c] = 0.0  // get rid of negative zeros
print("\${"% 10.6f".format(this[r][c])}  ")
}
println()
}
```
```   println()
```

}

fun main(args: Array<String>) {

```   val a = arrayOf(
doubleArrayOf(1.0, 2.0, 3.0),
doubleArrayOf(4.0, 1.0, 6.0),
doubleArrayOf(7.0, 8.0, 9.0)
)
a.inverse().printf("Inverse of A is :\n")
```
```   val b = arrayOf(
doubleArrayOf( 2.0, -1.0,  0.0),
doubleArrayOf(-1.0,  2.0, -1.0),
doubleArrayOf( 0.0, -1.0,  2.0)
)
b.inverse().printf("Inverse of B is :\n")
```

}</lang>

Output:
```Inverse of A is :

-0.812500    0.125000    0.187500
0.125000   -0.250000    0.125000
0.520833    0.125000   -0.145833

Inverse of B is :

0.750000    0.500000    0.250000
0.500000    1.000000    0.500000
0.250000    0.500000    0.750000
```

zkl

This uses GSL to invert a matrix via LU decomposition, not Gauss-Jordan. <lang zkl>var [const] GSL=Import.lib("zklGSL"); // libGSL (GNU Scientific Library) m:=GSL.Matrix(3,3).set(1,2,3, 4,1,6, 7,8,9); i:=m.invert(); i.format(10,4).println("\n"); (m*i).format(10,4).println();</lang>

Output:
```   -0.8125,    0.1250,    0.1875
0.1250,   -0.2500,    0.1250
0.5208,    0.1250,   -0.1458

1.0000,    0.0000,    0.0000
-0.0000,    1.0000,    0.0000
-0.0000,    0.0000,    1.0000
```

<lang zkl>m:=GSL.Matrix(3,3).set(2,-1,0, -1,2,-1, 0,-1,2); m.invert().format(10,4).println("\n");</lang>

Output:
```    0.7500,    0.5000,    0.2500
0.5000,    1.0000,    0.5000
0.2500,    0.5000,    0.7500
```