From 3882bd6ab0316b0a0724a7e88bed1b65e9454d12 Mon Sep 17 00:00:00 2001 From: Angourisoft Date: Sat, 18 Jul 2020 14:43:07 +0300 Subject: [PATCH 1/3] Non-numeric Gaussian elimination determinant --- Sources/Towel/Constant.cs | 9 ++++- Sources/Towel/Mathematics/Matrix.cs | 59 +++++++++++++++++++++++++++-- Sources/Towel/Towel.xml | 12 ++++++ 3 files changed, 75 insertions(+), 5 deletions(-) diff --git a/Sources/Towel/Constant.cs b/Sources/Towel/Constant.cs index a4774ae5..b5df0181 100644 --- a/Sources/Towel/Constant.cs +++ b/Sources/Towel/Constant.cs @@ -1,5 +1,6 @@ using System; using System.Linq.Expressions; +using System.Reflection; using static Towel.Syntax; namespace Towel @@ -87,8 +88,12 @@ public static T ComputePi(Predicate predicate = null) } pi = Multiplication(Constant.Two, pi); } - pi = Maximum(pi, Constant.Three); - return pi; + + // 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.Three); + return pi; } internal static class AddMultiplyDivideAddImplementation diff --git a/Sources/Towel/Mathematics/Matrix.cs b/Sources/Towel/Mathematics/Matrix.cs index f6fbbebc..6b100a94 100644 --- a/Sources/Towel/Mathematics/Matrix.cs +++ b/Sources/Towel/Mathematics/Matrix.cs @@ -384,8 +384,7 @@ internal static void GetCofactor(Matrix a, Matrix temp, int p, int q, int #endregion - #region GetDeterminant Gaussian elimination - + // Used for determinants #region MatrixElementFraction /// /// Used to avoid issues when 1/2 + 1/2 = 0 + 0 = 0 instead of 1 for types, where division results in precision loss @@ -462,9 +461,40 @@ public MatrixElementFraction Abs() => new MatrixElementFraction(AbsoluteValue(Numerator), AbsoluteValue(Denominator)); public bool IsDividedByZero => Compare.Default(Denominator, Constant.Zero) == CompareResult.Equal; - } + + public override string ToString() + => $"{Numerator.ToString()} / {Denominator.ToString()}"; + } #endregion +#region GetDeterminant Gaussian elimination analytically + internal static T GetDeterminantNonNumericGaussian(Matrix matrix, int n) + { + if (n == 1) + return matrix.Get(0, 0); + + var elemMatrix = new Matrix>(n, n, + (x, y) => new MatrixElementFraction(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(Constant.One); + for (int i = 0; i < n; i++) + det *= elemMatrix.Get(i, i); + + return det.Value; + } + #endregion + + #region GetDeterminant Gaussian elimination + + + /// /// Reference: https://codereview.stackexchange.com/questions/204135/determinant-using-gauss-elimination /// @@ -1297,6 +1327,22 @@ public static T DeterminantGaussian(Matrix a) return GetDeterminantGaussian(a, a.Rows); } + /// Computes the determinant of a square matrix via Gaussian elimination + /// for elements which don't have less, greater operators implemented + /// + /// The matrix to compute the determinant of. + /// The computed determinant. + /// O((n^3 + 2n^−3) / 3) + public static T DeterminantNonNumericGaussian(Matrix 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); + } + /// Computes the determinant of a square matrix via Laplace's method. /// The matrix to compute the determinant of. /// The computed determinant. @@ -1332,6 +1378,13 @@ public T DeterminantGaussian() return DeterminantGaussian(this); } + /// Computes the determinant of a square matrix via Gaussian elimination. + /// The computed determinant. + public T DeterminantNonNumericGaussian() + { + return DeterminantNonNumericGaussian(this); + } + #endregion #region Trace diff --git a/Sources/Towel/Towel.xml b/Sources/Towel/Towel.xml index f65d388f..f16aec50 100644 --- a/Sources/Towel/Towel.xml +++ b/Sources/Towel/Towel.xml @@ -16885,6 +16885,14 @@ The computed determinant. O((n^3 + 2n^−3) / 3) + + Computes the determinant of a square matrix via Gaussian elimination + for elements which don't have less, greater operators implemented + + The matrix to compute the determinant of. + The computed determinant. + O((n^3 + 2n^−3) / 3) + Computes the determinant of a square matrix via Laplace's method. The matrix to compute the determinant of. @@ -16903,6 +16911,10 @@ Computes the determinant of a square matrix via Gaussian elimination. The computed determinant. + + Computes the determinant of a square matrix via Gaussian elimination. + The computed determinant. + Computes the trace of a square matrix. The matrix to compute the trace of. From 0b45464e47914d55efffedf0107f35ecdb717880 Mon Sep 17 00:00:00 2001 From: Angourisoft Date: Sat, 18 Jul 2020 15:25:15 +0300 Subject: [PATCH 2/3] Spaces -> tabs --- Sources/Towel/Constant.cs | 4 +- Sources/Towel/Mathematics/Matrix.cs | 74 ++++++++++++++--------------- 2 files changed, 39 insertions(+), 39 deletions(-) diff --git a/Sources/Towel/Constant.cs b/Sources/Towel/Constant.cs index b5df0181..49e253b8 100644 --- a/Sources/Towel/Constant.cs +++ b/Sources/Towel/Constant.cs @@ -92,8 +92,8 @@ public static T ComputePi(Predicate predicate = null) // 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.Three); - return pi; + pi = Maximum(pi, Constant.Three); + return pi; } internal static class AddMultiplyDivideAddImplementation diff --git a/Sources/Towel/Mathematics/Matrix.cs b/Sources/Towel/Mathematics/Matrix.cs index 6b100a94..cb3b2adc 100644 --- a/Sources/Towel/Mathematics/Matrix.cs +++ b/Sources/Towel/Mathematics/Matrix.cs @@ -384,7 +384,7 @@ internal static void GetCofactor(Matrix a, Matrix temp, int p, int q, int #endregion - // Used for determinants + // Used for determinants #region MatrixElementFraction /// /// Used to avoid issues when 1/2 + 1/2 = 0 + 0 = 0 instead of 1 for types, where division results in precision loss @@ -468,27 +468,27 @@ public override string ToString() #endregion #region GetDeterminant Gaussian elimination analytically - internal static T GetDeterminantNonNumericGaussian(Matrix matrix, int n) - { - if (n == 1) - return matrix.Get(0, 0); - - var elemMatrix = new Matrix>(n, n, - (x, y) => new MatrixElementFraction(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(Constant.One); - for (int i = 0; i < n; i++) - det *= elemMatrix.Get(i, i); - - return det.Value; - } + internal static T GetDeterminantNonNumericGaussian(Matrix matrix, int n) + { + if (n == 1) + return matrix.Get(0, 0); + + var elemMatrix = new Matrix>(n, n, + (x, y) => new MatrixElementFraction(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(Constant.One); + for (int i = 0; i < n; i++) + det *= elemMatrix.Get(i, i); + + return det.Value; + } #endregion #region GetDeterminant Gaussian elimination @@ -1327,21 +1327,21 @@ public static T DeterminantGaussian(Matrix a) return GetDeterminantGaussian(a, a.Rows); } - /// Computes the determinant of a square matrix via Gaussian elimination - /// for elements which don't have less, greater operators implemented - /// - /// The matrix to compute the determinant of. - /// The computed determinant. - /// O((n^3 + 2n^−3) / 3) - public static T DeterminantNonNumericGaussian(Matrix 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); - } + /// Computes the determinant of a square matrix via Gaussian elimination + /// for elements which don't have less, greater operators implemented + /// + /// The matrix to compute the determinant of. + /// The computed determinant. + /// O((n^3 + 2n^−3) / 3) + public static T DeterminantNonNumericGaussian(Matrix 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); + } /// Computes the determinant of a square matrix via Laplace's method. /// The matrix to compute the determinant of. From 3a2826d7a1115c8fceb75c6bc8ea039254735ac7 Mon Sep 17 00:00:00 2001 From: Angourisoft Date: Sat, 18 Jul 2020 15:27:31 +0300 Subject: [PATCH 3/3] Removed useless code & spaces -> tabs --- Sources/Towel/Mathematics/Matrix.cs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/Sources/Towel/Mathematics/Matrix.cs b/Sources/Towel/Mathematics/Matrix.cs index cb3b2adc..f18ce6e7 100644 --- a/Sources/Towel/Mathematics/Matrix.cs +++ b/Sources/Towel/Mathematics/Matrix.cs @@ -461,10 +461,7 @@ public MatrixElementFraction Abs() => new MatrixElementFraction(AbsoluteValue(Numerator), AbsoluteValue(Denominator)); public bool IsDividedByZero => Compare.Default(Denominator, Constant.Zero) == CompareResult.Equal; - - public override string ToString() - => $"{Numerator.ToString()} / {Denominator.ToString()}"; - } + } #endregion #region GetDeterminant Gaussian elimination analytically @@ -1380,10 +1377,10 @@ public T DeterminantGaussian() /// Computes the determinant of a square matrix via Gaussian elimination. /// The computed determinant. - public T DeterminantNonNumericGaussian() - { - return DeterminantNonNumericGaussian(this); - } + public T DeterminantNonNumericGaussian() + { + return DeterminantNonNumericGaussian(this); + } #endregion