Skip to content
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

Non-numerical Gaussian elimination #56

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion Sources/Towel/Constant.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Linq.Expressions;
using System.Reflection;
using static Towel.Syntax;

namespace Towel
Expand Down Expand Up @@ -87,7 +88,11 @@ public static T ComputePi(Predicate<T> predicate = null)
}
pi = Multiplication(Constant<T>.Two, pi);
}
pi = Maximum(pi, Constant<T>.Three);

// this is necessary because user's classes may not contain <, >, etc. operators, but they shouldn't be required
// to define them to work with, say, matrices
if (!(typeof(T).GetMethod("op_GreaterThanOrEqual", BindingFlags.Static | BindingFlags.Public) is null) || typeof(T) == typeof(int))
pi = Maximum(pi, Constant<T>.Three);
return pi;
}

Expand Down
54 changes: 52 additions & 2 deletions Sources/Towel/Mathematics/Matrix.cs
Original file line number Diff line number Diff line change
Expand Up @@ -384,8 +384,7 @@ internal static void GetCofactor(Matrix<T> a, Matrix<T> temp, int p, int q, int

#endregion

#region GetDeterminant Gaussian elimination

// Used for determinants
#region MatrixElementFraction
/// <summary>
/// Used to avoid issues when 1/2 + 1/2 = 0 + 0 = 0 instead of 1 for types, where division results in precision loss
Expand Down Expand Up @@ -465,6 +464,34 @@ public MatrixElementFraction<T> Abs()
}
#endregion

#region GetDeterminant Gaussian elimination analytically
internal static T GetDeterminantNonNumericGaussian(Matrix<T> matrix, int n)
{
if (n == 1)
return matrix.Get(0, 0);

var elemMatrix = new Matrix<MatrixElementFraction<T>>(n, n,
(x, y) => new MatrixElementFraction<T>(matrix.Get(x, y)));
for (int k = 1; k < n; k++)
for (int j = k; j < n; j++)
{
var m = elemMatrix.Get(j, k - 1) / elemMatrix.Get(k - 1, k - 1);
for (int i = 0; i < n + 0; i++)
elemMatrix.Set(j, i, elemMatrix.Get(j, i) - m * elemMatrix.Get(k - 1, i));
}

var det = new MatrixElementFraction<T>(Constant<T>.One);
for (int i = 0; i < n; i++)
det *= elemMatrix.Get(i, i);

return det.Value;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There should be a check where det's Denominator is 0

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm but then it won't fully non-numeric. So if you take this method, you might want to add

if (det.IsDividedByZero)
    return Constant<T>.Zero;

}
#endregion

#region GetDeterminant Gaussian elimination



/// <summary>
/// Reference: https://codereview.stackexchange.com/questions/204135/determinant-using-gauss-elimination
/// </summary>
Expand Down Expand Up @@ -1297,6 +1324,22 @@ public static T DeterminantGaussian(Matrix<T> a)
return GetDeterminantGaussian(a, a.Rows);
}

/// <summary>Computes the determinant of a square matrix via Gaussian elimination
/// for elements which don't have less, greater operators implemented
/// </summary>
/// <param name="a">The matrix to compute the determinant of.</param>
/// <returns>The computed determinant.</returns>
/// <runtime>O((n^3 + 2n^−3) / 3)</runtime>
public static T DeterminantNonNumericGaussian(Matrix<T> a)
{
_ = a ?? throw new ArgumentNullException(nameof(a));
if (!a.IsSquare)
{
throw new MathematicsException("Argument invalid !(" + nameof(a) + "." + nameof(a.IsSquare) + ")");
}
return GetDeterminantNonNumericGaussian(a, a.Rows);
}

/// <summary>Computes the determinant of a square matrix via Laplace's method.</summary>
/// <param name="a">The matrix to compute the determinant of.</param>
/// <returns>The computed determinant.</returns>
Expand Down Expand Up @@ -1332,6 +1375,13 @@ public T DeterminantGaussian()
return DeterminantGaussian(this);
}

/// <summary>Computes the determinant of a square matrix via Gaussian elimination.</summary>
/// <returns>The computed determinant.</returns>
public T DeterminantNonNumericGaussian()
{
return DeterminantNonNumericGaussian(this);
}

#endregion

#region Trace
Expand Down
12 changes: 12 additions & 0 deletions Sources/Towel/Towel.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16885,6 +16885,14 @@
<returns>The computed determinant.</returns>
<runtime>O((n^3 + 2n^−3) / 3)</runtime>
</member>
<member name="M:Towel.Mathematics.Matrix`1.DeterminantNonNumericGaussian(Towel.Mathematics.Matrix{`0})">
<summary>Computes the determinant of a square matrix via Gaussian elimination
for elements which don't have less, greater operators implemented
</summary>
<param name="a">The matrix to compute the determinant of.</param>
<returns>The computed determinant.</returns>
<runtime>O((n^3 + 2n^−3) / 3)</runtime>
</member>
<member name="M:Towel.Mathematics.Matrix`1.DeterminantLaplace(Towel.Mathematics.Matrix{`0})">
<summary>Computes the determinant of a square matrix via Laplace's method.</summary>
<param name="a">The matrix to compute the determinant of.</param>
Expand All @@ -16903,6 +16911,10 @@
<summary>Computes the determinant of a square matrix via Gaussian elimination.</summary>
<returns>The computed determinant.</returns>
</member>
<member name="M:Towel.Mathematics.Matrix`1.DeterminantNonNumericGaussian">
<summary>Computes the determinant of a square matrix via Gaussian elimination.</summary>
<returns>The computed determinant.</returns>
</member>
<member name="M:Towel.Mathematics.Matrix`1.Trace(Towel.Mathematics.Matrix{`0})">
<summary>Computes the trace of a square matrix.</summary>
<param name="a">The matrix to compute the trace of.</param>
Expand Down