Browse Source

LA: Simplify Gram-Schmidt decomposition architecture

optimization-1
Christoph Ruegg 13 years ago
parent
commit
390cae2177
  1. 2
      src/Numerics/LinearAlgebra/Complex/DenseMatrix.cs
  2. 57
      src/Numerics/LinearAlgebra/Complex/Factorization/DenseGramSchmidt.cs
  3. 15
      src/Numerics/LinearAlgebra/Complex/Factorization/GramSchmidt.cs
  4. 69
      src/Numerics/LinearAlgebra/Complex/Factorization/UserGramSchmidt.cs
  5. 2
      src/Numerics/LinearAlgebra/Complex/Matrix.cs
  6. 2
      src/Numerics/LinearAlgebra/Complex32/DenseMatrix.cs
  7. 57
      src/Numerics/LinearAlgebra/Complex32/Factorization/DenseGramSchmidt.cs
  8. 15
      src/Numerics/LinearAlgebra/Complex32/Factorization/GramSchmidt.cs
  9. 69
      src/Numerics/LinearAlgebra/Complex32/Factorization/UserGramSchmidt.cs
  10. 2
      src/Numerics/LinearAlgebra/Complex32/Matrix.cs
  11. 2
      src/Numerics/LinearAlgebra/Double/DenseMatrix.cs
  12. 57
      src/Numerics/LinearAlgebra/Double/Factorization/DenseGramSchmidt.cs
  13. 16
      src/Numerics/LinearAlgebra/Double/Factorization/GramSchmidt.cs
  14. 67
      src/Numerics/LinearAlgebra/Double/Factorization/UserGramSchmidt.cs
  15. 2
      src/Numerics/LinearAlgebra/Double/Matrix.cs
  16. 11
      src/Numerics/LinearAlgebra/Factorization/GramSchmidt.cs
  17. 2
      src/Numerics/LinearAlgebra/Single/DenseMatrix.cs
  18. 57
      src/Numerics/LinearAlgebra/Single/Factorization/DenseGramSchmidt.cs
  19. 16
      src/Numerics/LinearAlgebra/Single/Factorization/GramSchmidt.cs
  20. 67
      src/Numerics/LinearAlgebra/Single/Factorization/UserGramSchmidt.cs
  21. 2
      src/Numerics/LinearAlgebra/Single/Matrix.cs
  22. 13
      src/UnitTests/LinearAlgebraTests/Complex/Factorization/GramSchmidtTests.cs
  23. 17
      src/UnitTests/LinearAlgebraTests/Complex/Factorization/UserGramSchmidtTests.cs
  24. 13
      src/UnitTests/LinearAlgebraTests/Complex32/Factorization/GramSchmidtTests.cs
  25. 19
      src/UnitTests/LinearAlgebraTests/Complex32/Factorization/UserGramSchmidtTests.cs
  26. 13
      src/UnitTests/LinearAlgebraTests/Double/Factorization/GramSchmidtTests.cs
  27. 18
      src/UnitTests/LinearAlgebraTests/Double/Factorization/UserGramSchmidtTests.cs
  28. 13
      src/UnitTests/LinearAlgebraTests/Single/Factorization/GramSchmidtTests.cs
  29. 18
      src/UnitTests/LinearAlgebraTests/Single/Factorization/UserGramSchmidtTests.cs

2
src/Numerics/LinearAlgebra/Complex/DenseMatrix.cs

@ -1026,7 +1026,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
public override GramSchmidt<Complex> GramSchmidt()
{
return new DenseGramSchmidt(this);
return DenseGramSchmidt.Create(this);
}
public override Svd<Complex> Svd(bool computeVectors)

57
src/Numerics/LinearAlgebra/Complex/Factorization/DenseGramSchmidt.cs

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2010 Math.NET
// Copyright (c) 2009-2013 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@ -28,10 +28,9 @@
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
using System;
using MathNet.Numerics.LinearAlgebra.Factorization;
using MathNet.Numerics.Properties;
using System;
using MathNet.Numerics.Providers.LinearAlgebra;
namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
{
@ -49,13 +48,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
/// <remarks>
/// The computation of the QR decomposition is done at construction time by modified Gram-Schmidt Orthogonalization.
/// </remarks>
public class DenseGramSchmidt : GramSchmidt
public sealed class DenseGramSchmidt : GramSchmidt
{
/// <summary>
/// used for QR solve
/// </summary>
private readonly ILinearAlgebraProvider _provider = new ManagedLinearAlgebraProvider();
/// <summary>
/// Initializes a new instance of the <see cref="DenseGramSchmidt"/> class. This object creates an unitary matrix
/// using the modified Gram-Schmidt method.
@ -64,21 +58,23 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
/// <exception cref="ArgumentNullException">If <paramref name="matrix"/> is <c>null</c>.</exception>
/// <exception cref="ArgumentException">If <paramref name="matrix"/> row count is less then column count</exception>
/// <exception cref="ArgumentException">If <paramref name="matrix"/> is rank deficient</exception>
public DenseGramSchmidt(DenseMatrix matrix)
public static DenseGramSchmidt Create(DenseMatrix matrix)
{
if (matrix == null)
{
throw new ArgumentNullException("matrix");
}
if (matrix.RowCount < matrix.ColumnCount)
{
throw Matrix.DimensionsDontMatch<ArgumentException>(matrix);
}
Q = matrix.Clone();
MatrixR = matrix.CreateMatrix(matrix.ColumnCount, matrix.ColumnCount);
Factorize(((DenseMatrix)Q).Values, Q.RowCount, Q.ColumnCount, ((DenseMatrix)MatrixR).Values);
var q = (DenseMatrix)matrix.Clone();
var r = new DenseMatrix(matrix.ColumnCount, matrix.ColumnCount);
Factorize(q.Values, q.RowCount, q.ColumnCount, r.Values);
return new DenseGramSchmidt(q, r);
}
DenseGramSchmidt(Matrix<Complex> q, Matrix<Complex> rFull)
: base(q, rFull)
{
}
/// <summary>
@ -138,17 +134,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
/// <param name="result">The left hand side <see cref="Matrix{T}"/>, <b>X</b>.</param>
public override void Solve(Matrix<Complex> input, Matrix<Complex> result)
{
// Check for proper arguments.
if (input == null)
{
throw new ArgumentNullException("input");
}
if (result == null)
{
throw new ArgumentNullException("result");
}
// The solution X should have the same number of columns as B
if (input.ColumnCount != result.ColumnCount)
{
@ -179,7 +164,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
throw new NotSupportedException("Can only do GramSchmidt factorization for dense matrices at the moment.");
}
_provider.QRSolveFactored(((DenseMatrix)Q).Values, ((DenseMatrix)MatrixR).Values, Q.RowCount, MatrixR.ColumnCount, null, dinput.Values, input.ColumnCount, dresult.Values, QRMethod.Thin);
Control.LinearAlgebraProvider.QRSolveFactored(((DenseMatrix)Q).Values, ((DenseMatrix)MatrixR).Values, Q.RowCount, MatrixR.ColumnCount, null, dinput.Values, input.ColumnCount, dresult.Values, QRMethod.Thin);
}
/// <summary>
@ -189,16 +174,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
/// <param name="result">The left hand side <see cref="Matrix{T}"/>, <b>x</b>.</param>
public override void Solve(Vector<Complex> input, Vector<Complex> result)
{
if (input == null)
{
throw new ArgumentNullException("input");
}
if (result == null)
{
throw new ArgumentNullException("result");
}
// Ax=b where A is an m x n matrix
// Check that b is a column vector with m entries
if (Q.RowCount != input.Count)
@ -224,7 +199,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
throw new NotSupportedException("Can only do GramSchmidt factorization for dense vectors at the moment.");
}
_provider.QRSolveFactored(((DenseMatrix)Q).Values, ((DenseMatrix)MatrixR).Values, Q.RowCount, MatrixR.ColumnCount, null, dinput.Values, 1, dresult.Values, QRMethod.Thin);
Control.LinearAlgebraProvider.QRSolveFactored(((DenseMatrix)Q).Values, ((DenseMatrix)MatrixR).Values, Q.RowCount, MatrixR.ColumnCount, null, dinput.Values, 1, dresult.Values, QRMethod.Thin);
}
}
}

15
src/Numerics/LinearAlgebra/Complex/Factorization/GramSchmidt.cs

@ -3,7 +3,9 @@
// http://numerics.mathdotnet.com
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
// Copyright (c) 2009-2010 Math.NET
//
// Copyright (c) 2009-2013 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
@ -12,8 +14,10 @@
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
@ -24,12 +28,12 @@
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
using System;
using MathNet.Numerics.LinearAlgebra.Factorization;
using MathNet.Numerics.Properties;
namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
{
using System;
using Properties;
#if NOSYSNUMERICS
using Complex = Numerics.Complex;
@ -46,6 +50,11 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
/// </remarks>
public abstract class GramSchmidt : GramSchmidt<Complex>
{
protected GramSchmidt(Matrix<Complex> q, Matrix<Complex> rFull)
: base(q, rFull)
{
}
/// <summary>
/// Gets the absolute determinant value of the matrix for which the QR matrix was computed.
/// </summary>

69
src/Numerics/LinearAlgebra/Complex/Factorization/UserGramSchmidt.cs

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2010 Math.NET
// Copyright (c) 2009-2013 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@ -28,8 +28,8 @@
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
using MathNet.Numerics.Properties;
using System;
using MathNet.Numerics.Properties;
namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
{
@ -47,7 +47,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
/// <remarks>
/// The computation of the QR decomposition is done at construction time by modified Gram-Schmidt Orthogonalization.
/// </remarks>
public class UserGramSchmidt : GramSchmidt
public sealed class UserGramSchmidt : GramSchmidt
{
/// <summary>
/// Initializes a new instance of the <see cref="UserGramSchmidt"/> class. This object creates an unitary matrix
@ -57,51 +57,53 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
/// <exception cref="ArgumentNullException">If <paramref name="matrix"/> is <c>null</c>.</exception>
/// <exception cref="ArgumentException">If <paramref name="matrix"/> row count is less then column count</exception>
/// <exception cref="ArgumentException">If <paramref name="matrix"/> is rank deficient</exception>
public UserGramSchmidt(Matrix<Complex> matrix)
public static UserGramSchmidt Create(Matrix<Complex> matrix)
{
if (matrix == null)
{
throw new ArgumentNullException("matrix");
}
if (matrix.RowCount < matrix.ColumnCount)
{
throw Matrix.DimensionsDontMatch<ArgumentException>(matrix);
}
Q = matrix.Clone();
MatrixR = matrix.CreateMatrix(matrix.ColumnCount, matrix.ColumnCount);
var q = matrix.Clone();
var r = matrix.CreateMatrix(matrix.ColumnCount, matrix.ColumnCount);
for (var k = 0; k < Q.ColumnCount; k++)
for (var k = 0; k < q.ColumnCount; k++)
{
var norm = Q.Column(k).L2Norm();
var norm = q.Column(k).L2Norm();
if (norm == 0.0)
{
throw new ArgumentException(Resources.ArgumentMatrixNotRankDeficient);
}
MatrixR.At(k, k, norm);
for (var i = 0; i < Q.RowCount; i++)
r.At(k, k, norm);
for (var i = 0; i < q.RowCount; i++)
{
Q.At(i, k, Q.At(i, k) / norm);
q.At(i, k, q.At(i, k) / norm);
}
for (var j = k + 1; j < Q.ColumnCount; j++)
for (var j = k + 1; j < q.ColumnCount; j++)
{
var dot = Complex.Zero;
for (int i = 0; i < Q.RowCount; i++)
for (int i = 0; i < q.RowCount; i++)
{
dot += Q.Column(k)[i].Conjugate() * Q.Column(j)[i];
dot += q.Column(k)[i].Conjugate() * q.Column(j)[i];
}
MatrixR.At(k, j, dot);
for (var i = 0; i < Q.RowCount; i++)
r.At(k, j, dot);
for (var i = 0; i < q.RowCount; i++)
{
var value = Q.At(i, j) - (Q.At(i, k) * dot);
Q.At(i, j, value);
var value = q.At(i, j) - (q.At(i, k) * dot);
q.At(i, j, value);
}
}
}
return new UserGramSchmidt(q, r);
}
UserGramSchmidt(Matrix<Complex> q, Matrix<Complex> rFull)
: base(q, rFull)
{
}
/// <summary>
@ -111,17 +113,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
/// <param name="result">The left hand side <see cref="Matrix{T}"/>, <b>X</b>.</param>
public override void Solve(Matrix<Complex> input, Matrix<Complex> result)
{
// Check for proper arguments.
if (input == null)
{
throw new ArgumentNullException("input");
}
if (result == null)
{
throw new ArgumentNullException("result");
}
// The solution X should have the same number of columns as B
if (input.ColumnCount != result.ColumnCount)
{
@ -196,16 +187,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
/// <param name="result">The left hand side <see cref="Matrix{T}"/>, <b>x</b>.</param>
public override void Solve(Vector<Complex> input, Vector<Complex> result)
{
if (input == null)
{
throw new ArgumentNullException("input");
}
if (result == null)
{
throw new ArgumentNullException("result");
}
// Ax=b where A is an m x n matrix
// Check that b is a column vector with m entries
if (Q.RowCount != input.Count)

2
src/Numerics/LinearAlgebra/Complex/Matrix.cs

@ -475,7 +475,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
public override GramSchmidt<Complex> GramSchmidt()
{
return new UserGramSchmidt(this);
return UserGramSchmidt.Create(this);
}
public override Svd<Complex> Svd(bool computeVectors)

2
src/Numerics/LinearAlgebra/Complex32/DenseMatrix.cs

@ -1021,7 +1021,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
public override GramSchmidt<Complex32> GramSchmidt()
{
return new DenseGramSchmidt(this);
return DenseGramSchmidt.Create(this);
}
public override Svd<Complex32> Svd(bool computeVectors)

57
src/Numerics/LinearAlgebra/Complex32/Factorization/DenseGramSchmidt.cs

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2010 Math.NET
// Copyright (c) 2009-2013 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@ -28,10 +28,9 @@
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
using System;
using MathNet.Numerics.LinearAlgebra.Factorization;
using MathNet.Numerics.Properties;
using System;
using MathNet.Numerics.Providers.LinearAlgebra;
namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
{
@ -44,13 +43,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
/// <remarks>
/// The computation of the QR decomposition is done at construction time by modified Gram-Schmidt Orthogonalization.
/// </remarks>
public class DenseGramSchmidt : GramSchmidt
public sealed class DenseGramSchmidt : GramSchmidt
{
/// <summary>
/// used for QR solve
/// </summary>
private readonly ILinearAlgebraProvider _provider = new ManagedLinearAlgebraProvider();
/// <summary>
/// Initializes a new instance of the <see cref="DenseGramSchmidt"/> class. This object creates an unitary matrix
/// using the modified Gram-Schmidt method.
@ -59,21 +53,23 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
/// <exception cref="ArgumentNullException">If <paramref name="matrix"/> is <c>null</c>.</exception>
/// <exception cref="ArgumentException">If <paramref name="matrix"/> row count is less then column count</exception>
/// <exception cref="ArgumentException">If <paramref name="matrix"/> is rank deficient</exception>
public DenseGramSchmidt(DenseMatrix matrix)
public static DenseGramSchmidt Create(DenseMatrix matrix)
{
if (matrix == null)
{
throw new ArgumentNullException("matrix");
}
if (matrix.RowCount < matrix.ColumnCount)
{
throw Matrix.DimensionsDontMatch<ArgumentException>(matrix);
}
Q = matrix.Clone();
MatrixR = matrix.CreateMatrix(matrix.ColumnCount, matrix.ColumnCount);
Factorize(((DenseMatrix)Q).Values, Q.RowCount, Q.ColumnCount, ((DenseMatrix)MatrixR).Values);
var q = (DenseMatrix)matrix.Clone();
var r = new DenseMatrix(matrix.ColumnCount, matrix.ColumnCount);
Factorize(q.Values, q.RowCount, q.ColumnCount, r.Values);
return new DenseGramSchmidt(q, r);
}
DenseGramSchmidt(Matrix<Complex32> q, Matrix<Complex32> rFull)
: base(q, rFull)
{
}
/// <summary>
@ -133,17 +129,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
/// <param name="result">The left hand side <see cref="Matrix{T}"/>, <b>X</b>.</param>
public override void Solve(Matrix<Complex32> input, Matrix<Complex32> result)
{
// Check for proper arguments.
if (input == null)
{
throw new ArgumentNullException("input");
}
if (result == null)
{
throw new ArgumentNullException("result");
}
// The solution X should have the same number of columns as B
if (input.ColumnCount != result.ColumnCount)
{
@ -174,7 +159,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
throw new NotSupportedException("Can only do GramSchmidt factorization for dense matrices at the moment.");
}
_provider.QRSolveFactored(((DenseMatrix)Q).Values, ((DenseMatrix)MatrixR).Values, Q.RowCount, MatrixR.ColumnCount, null, dinput.Values, input.ColumnCount, dresult.Values, QRMethod.Thin);
Control.LinearAlgebraProvider.QRSolveFactored(((DenseMatrix)Q).Values, ((DenseMatrix)MatrixR).Values, Q.RowCount, MatrixR.ColumnCount, null, dinput.Values, input.ColumnCount, dresult.Values, QRMethod.Thin);
}
/// <summary>
@ -184,16 +169,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
/// <param name="result">The left hand side <see cref="Matrix{T}"/>, <b>x</b>.</param>
public override void Solve(Vector<Complex32> input, Vector<Complex32> result)
{
if (input == null)
{
throw new ArgumentNullException("input");
}
if (result == null)
{
throw new ArgumentNullException("result");
}
// Ax=b where A is an m x n matrix
// Check that b is a column vector with m entries
if (Q.RowCount != input.Count)
@ -219,7 +194,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
throw new NotSupportedException("Can only do GramSchmidt factorization for dense vectors at the moment.");
}
_provider.QRSolveFactored(((DenseMatrix)Q).Values, ((DenseMatrix)MatrixR).Values, Q.RowCount, MatrixR.ColumnCount, null, dinput.Values, 1, dresult.Values, QRMethod.Thin);
Control.LinearAlgebraProvider.QRSolveFactored(((DenseMatrix)Q).Values, ((DenseMatrix)MatrixR).Values, Q.RowCount, MatrixR.ColumnCount, null, dinput.Values, 1, dresult.Values, QRMethod.Thin);
}
}
}

15
src/Numerics/LinearAlgebra/Complex32/Factorization/GramSchmidt.cs

@ -3,7 +3,9 @@
// http://numerics.mathdotnet.com
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
// Copyright (c) 2009-2010 Math.NET
//
// Copyright (c) 2009-2013 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
@ -12,8 +14,10 @@
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
@ -24,13 +28,13 @@
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
using System;
using MathNet.Numerics.LinearAlgebra.Factorization;
using MathNet.Numerics.Properties;
namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
{
using System;
using Numerics;
using Properties;
/// <summary>
/// <para>A class which encapsulates the functionality of the QR decomposition Modified Gram-Schmidt Orthogonalization.</para>
@ -41,6 +45,11 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
/// </remarks>
public abstract class GramSchmidt : GramSchmidt<Complex32>
{
protected GramSchmidt(Matrix<Complex32> q, Matrix<Complex32> rFull)
: base(q, rFull)
{
}
/// <summary>
/// Gets the absolute determinant value of the matrix for which the QR matrix was computed.
/// </summary>

69
src/Numerics/LinearAlgebra/Complex32/Factorization/UserGramSchmidt.cs

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2010 Math.NET
// Copyright (c) 2009-2013 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@ -28,8 +28,8 @@
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
using MathNet.Numerics.Properties;
using System;
using MathNet.Numerics.Properties;
namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
{
@ -42,7 +42,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
/// <remarks>
/// The computation of the QR decomposition is done at construction time by modified Gram-Schmidt Orthogonalization.
/// </remarks>
public class UserGramSchmidt : GramSchmidt
public sealed class UserGramSchmidt : GramSchmidt
{
/// <summary>
/// Initializes a new instance of the <see cref="UserGramSchmidt"/> class. This object creates an unitary matrix
@ -52,51 +52,53 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
/// <exception cref="ArgumentNullException">If <paramref name="matrix"/> is <c>null</c>.</exception>
/// <exception cref="ArgumentException">If <paramref name="matrix"/> row count is less then column count</exception>
/// <exception cref="ArgumentException">If <paramref name="matrix"/> is rank deficient</exception>
public UserGramSchmidt(Matrix<Complex32> matrix)
public static UserGramSchmidt Create(Matrix<Complex32> matrix)
{
if (matrix == null)
{
throw new ArgumentNullException("matrix");
}
if (matrix.RowCount < matrix.ColumnCount)
{
throw Matrix.DimensionsDontMatch<ArgumentException>(matrix);
}
Q = matrix.Clone();
MatrixR = matrix.CreateMatrix(matrix.ColumnCount, matrix.ColumnCount);
var q = matrix.Clone();
var r = matrix.CreateMatrix(matrix.ColumnCount, matrix.ColumnCount);
for (var k = 0; k < Q.ColumnCount; k++)
for (var k = 0; k < q.ColumnCount; k++)
{
var norm = Q.Column(k).L2Norm().Real;
var norm = q.Column(k).L2Norm().Real;
if (norm == 0.0f)
{
throw new ArgumentException(Resources.ArgumentMatrixNotRankDeficient);
}
MatrixR.At(k, k, norm);
for (var i = 0; i < Q.RowCount; i++)
r.At(k, k, norm);
for (var i = 0; i < q.RowCount; i++)
{
Q.At(i, k, Q.At(i, k) / norm);
q.At(i, k, q.At(i, k) / norm);
}
for (var j = k + 1; j < Q.ColumnCount; j++)
for (var j = k + 1; j < q.ColumnCount; j++)
{
var dot = Complex32.Zero;
for (int i = 0; i < Q.RowCount; i++)
for (int i = 0; i < q.RowCount; i++)
{
dot += Q.Column(k)[i].Conjugate() * Q.Column(j)[i];
dot += q.Column(k)[i].Conjugate() * q.Column(j)[i];
}
MatrixR.At(k, j, dot);
for (var i = 0; i < Q.RowCount; i++)
r.At(k, j, dot);
for (var i = 0; i < q.RowCount; i++)
{
var value = Q.At(i, j) - (Q.At(i, k) * dot);
Q.At(i, j, value);
var value = q.At(i, j) - (q.At(i, k) * dot);
q.At(i, j, value);
}
}
}
return new UserGramSchmidt(q, r);
}
UserGramSchmidt(Matrix<Complex32> q, Matrix<Complex32> rFull)
: base(q, rFull)
{
}
/// <summary>
@ -106,17 +108,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
/// <param name="result">The left hand side <see cref="Matrix{T}"/>, <b>X</b>.</param>
public override void Solve(Matrix<Complex32> input, Matrix<Complex32> result)
{
// Check for proper arguments.
if (input == null)
{
throw new ArgumentNullException("input");
}
if (result == null)
{
throw new ArgumentNullException("result");
}
// The solution X should have the same number of columns as B
if (input.ColumnCount != result.ColumnCount)
{
@ -191,16 +182,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
/// <param name="result">The left hand side <see cref="Matrix{T}"/>, <b>x</b>.</param>
public override void Solve(Vector<Complex32> input, Vector<Complex32> result)
{
if (input == null)
{
throw new ArgumentNullException("input");
}
if (result == null)
{
throw new ArgumentNullException("result");
}
// Ax=b where A is an m x n matrix
// Check that b is a column vector with m entries
if (Q.RowCount != input.Count)

2
src/Numerics/LinearAlgebra/Complex32/Matrix.cs

@ -470,7 +470,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
public override GramSchmidt<Complex32> GramSchmidt()
{
return new UserGramSchmidt(this);
return UserGramSchmidt.Create(this);
}
public override Svd<Complex32> Svd(bool computeVectors)

2
src/Numerics/LinearAlgebra/Double/DenseMatrix.cs

@ -1052,7 +1052,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
public override GramSchmidt<double> GramSchmidt()
{
return new DenseGramSchmidt(this);
return DenseGramSchmidt.Create(this);
}
public override Svd<double> Svd(bool computeVectors)

57
src/Numerics/LinearAlgebra/Double/Factorization/DenseGramSchmidt.cs

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2010 Math.NET
// Copyright (c) 2009-2013 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@ -28,10 +28,9 @@
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
using System;
using MathNet.Numerics.LinearAlgebra.Factorization;
using MathNet.Numerics.Properties;
using System;
using MathNet.Numerics.Providers.LinearAlgebra;
namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
{
@ -42,13 +41,8 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
/// <remarks>
/// The computation of the QR decomposition is done at construction time by modified Gram-Schmidt Orthogonalization.
/// </remarks>
public class DenseGramSchmidt : GramSchmidt
public sealed class DenseGramSchmidt : GramSchmidt
{
/// <summary>
/// used for QR solve
/// </summary>
private readonly ILinearAlgebraProvider _provider = new ManagedLinearAlgebraProvider();
/// <summary>
/// Initializes a new instance of the <see cref="DenseGramSchmidt"/> class. This object creates an orthogonal matrix
/// using the modified Gram-Schmidt method.
@ -57,21 +51,23 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
/// <exception cref="ArgumentNullException">If <paramref name="matrix"/> is <c>null</c>.</exception>
/// <exception cref="ArgumentException">If <paramref name="matrix"/> row count is less then column count</exception>
/// <exception cref="ArgumentException">If <paramref name="matrix"/> is rank deficient</exception>
public DenseGramSchmidt(DenseMatrix matrix)
public static DenseGramSchmidt Create(DenseMatrix matrix)
{
if (matrix == null)
{
throw new ArgumentNullException("matrix");
}
if (matrix.RowCount < matrix.ColumnCount)
{
throw Matrix.DimensionsDontMatch<ArgumentException>(matrix);
}
Q = matrix.Clone();
MatrixR = matrix.CreateMatrix(matrix.ColumnCount, matrix.ColumnCount);
Factorize(((DenseMatrix)Q).Values, Q.RowCount, Q.ColumnCount, ((DenseMatrix)MatrixR).Values);
var q = (DenseMatrix)matrix.Clone();
var r = new DenseMatrix(matrix.ColumnCount, matrix.ColumnCount);
Factorize(q.Values, q.RowCount, q.ColumnCount, r.Values);
return new DenseGramSchmidt(q, r);
}
DenseGramSchmidt(Matrix<double> q, Matrix<double> rFull)
: base(q, rFull)
{
}
/// <summary>
@ -131,17 +127,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
/// <param name="result">The left hand side <see cref="Matrix{T}"/>, <b>X</b>.</param>
public override void Solve(Matrix<double> input, Matrix<double> result)
{
// Check for proper arguments.
if (input == null)
{
throw new ArgumentNullException("input");
}
if (result == null)
{
throw new ArgumentNullException("result");
}
// The solution X should have the same number of columns as B
if (input.ColumnCount != result.ColumnCount)
{
@ -172,7 +157,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
throw new NotSupportedException("Can only do GramSchmidt factorization for dense matrices at the moment.");
}
_provider.QRSolveFactored(((DenseMatrix)Q).Values, ((DenseMatrix)MatrixR).Values, Q.RowCount, MatrixR.ColumnCount, null, dinput.Values, input.ColumnCount, dresult.Values, QRMethod.Thin);
Control.LinearAlgebraProvider.QRSolveFactored(((DenseMatrix)Q).Values, ((DenseMatrix)MatrixR).Values, Q.RowCount, MatrixR.ColumnCount, null, dinput.Values, input.ColumnCount, dresult.Values, QRMethod.Thin);
}
/// <summary>
@ -182,16 +167,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
/// <param name="result">The left hand side <see cref="Matrix{T}"/>, <b>x</b>.</param>
public override void Solve(Vector<double> input, Vector<double> result)
{
if (input == null)
{
throw new ArgumentNullException("input");
}
if (result == null)
{
throw new ArgumentNullException("result");
}
// Ax=b where A is an m x n matrix
// Check that b is a column vector with m entries
if (Q.RowCount != input.Count)
@ -217,7 +192,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
throw new NotSupportedException("Can only do GramSchmidt factorization for dense vectors at the moment.");
}
_provider.QRSolveFactored(((DenseMatrix)Q).Values, ((DenseMatrix)MatrixR).Values, Q.RowCount, MatrixR.ColumnCount, null, dinput.Values, 1, dresult.Values, QRMethod.Thin);
Control.LinearAlgebraProvider.QRSolveFactored(((DenseMatrix)Q).Values, ((DenseMatrix)MatrixR).Values, Q.RowCount, MatrixR.ColumnCount, null, dinput.Values, 1, dresult.Values, QRMethod.Thin);
}
}
}

16
src/Numerics/LinearAlgebra/Double/Factorization/GramSchmidt.cs

@ -3,7 +3,9 @@
// http://numerics.mathdotnet.com
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
// Copyright (c) 2009-2010 Math.NET
//
// Copyright (c) 2009-2013 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
@ -12,8 +14,10 @@
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
@ -24,13 +28,12 @@
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
using System;
using MathNet.Numerics.LinearAlgebra.Factorization;
using MathNet.Numerics.Properties;
namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
{
using System;
using Properties;
/// <summary>
/// <para>A class which encapsulates the functionality of the QR decomposition Modified Gram-Schmidt Orthogonalization.</para>
/// <para>Any real square matrix A may be decomposed as A = QR where Q is an orthogonal mxn matrix and R is an nxn upper triangular matrix.</para>
@ -40,6 +43,11 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
/// </remarks>
public abstract class GramSchmidt : GramSchmidt<double>
{
protected GramSchmidt(Matrix<double> q, Matrix<double> rFull)
: base(q,rFull)
{
}
/// <summary>
/// Gets the absolute determinant value of the matrix for which the QR matrix was computed.
/// </summary>

67
src/Numerics/LinearAlgebra/Double/Factorization/UserGramSchmidt.cs

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2010 Math.NET
// Copyright (c) 2009-2013 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@ -28,8 +28,8 @@
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
using MathNet.Numerics.Properties;
using System;
using MathNet.Numerics.Properties;
namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
{
@ -40,7 +40,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
/// <remarks>
/// The computation of the QR decomposition is done at construction time by modified Gram-Schmidt Orthogonalization.
/// </remarks>
public class UserGramSchmidt : GramSchmidt
public sealed class UserGramSchmidt : GramSchmidt
{
/// <summary>
/// Initializes a new instance of the <see cref="UserGramSchmidt"/> class. This object creates an orthogonal matrix
@ -50,46 +50,48 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
/// <exception cref="ArgumentNullException">If <paramref name="matrix"/> is <c>null</c>.</exception>
/// <exception cref="ArgumentException">If <paramref name="matrix"/> row count is less then column count</exception>
/// <exception cref="ArgumentException">If <paramref name="matrix"/> is rank deficient</exception>
public UserGramSchmidt(Matrix<double> matrix)
public static UserGramSchmidt Create(Matrix<double> matrix)
{
if (matrix == null)
{
throw new ArgumentNullException("matrix");
}
if (matrix.RowCount < matrix.ColumnCount)
{
throw Matrix.DimensionsDontMatch<ArgumentException>(matrix);
}
Q = matrix.Clone();
MatrixR = matrix.CreateMatrix(matrix.ColumnCount, matrix.ColumnCount);
var q = matrix.Clone();
var r = matrix.CreateMatrix(matrix.ColumnCount, matrix.ColumnCount);
for (var k = 0; k < Q.ColumnCount; k++)
for (var k = 0; k < q.ColumnCount; k++)
{
var norm = Q.Column(k).L2Norm();
var norm = q.Column(k).L2Norm();
if (norm == 0.0)
{
throw new ArgumentException(Resources.ArgumentMatrixNotRankDeficient);
}
MatrixR.At(k, k, norm);
for (var i = 0; i < Q.RowCount; i++)
r.At(k, k, norm);
for (var i = 0; i < q.RowCount; i++)
{
Q.At(i, k, Q.At(i, k) / norm);
q.At(i, k, q.At(i, k) / norm);
}
for (var j = k + 1; j < Q.ColumnCount; j++)
for (var j = k + 1; j < q.ColumnCount; j++)
{
var dot = Q.Column(k).DotProduct(Q.Column(j));
MatrixR.At(k, j, dot);
for (var i = 0; i < Q.RowCount; i++)
var dot = q.Column(k).DotProduct(q.Column(j));
r.At(k, j, dot);
for (var i = 0; i < q.RowCount; i++)
{
var value = Q.At(i, j) - (Q.At(i, k) * dot);
Q.At(i, j, value);
var value = q.At(i, j) - (q.At(i, k) * dot);
q.At(i, j, value);
}
}
}
return new UserGramSchmidt(q, r);
}
UserGramSchmidt(Matrix<double> q, Matrix<double> rFull)
: base(q, rFull)
{
}
/// <summary>
@ -99,17 +101,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
/// <param name="result">The left hand side <see cref="Matrix{T}"/>, <b>X</b>.</param>
public override void Solve(Matrix<double> input, Matrix<double> result)
{
// Check for proper arguments.
if (input == null)
{
throw new ArgumentNullException("input");
}
if (result == null)
{
throw new ArgumentNullException("result");
}
// The solution X should have the same number of columns as B
if (input.ColumnCount != result.ColumnCount)
{
@ -184,16 +175,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
/// <param name="result">The left hand side <see cref="Matrix{T}"/>, <b>x</b>.</param>
public override void Solve(Vector<double> input, Vector<double> result)
{
if (input == null)
{
throw new ArgumentNullException("input");
}
if (result == null)
{
throw new ArgumentNullException("result");
}
// Ax=b where A is an m x n matrix
// Check that b is a column vector with m entries
if (Q.RowCount != input.Count)

2
src/Numerics/LinearAlgebra/Double/Matrix.cs

@ -476,7 +476,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
public override GramSchmidt<double> GramSchmidt()
{
return new UserGramSchmidt(this);
return UserGramSchmidt.Create(this);
}
public override Svd<double> Svd(bool computeVectors)

11
src/Numerics/LinearAlgebra/Factorization/GramSchmidt.cs

@ -3,7 +3,9 @@
// http://numerics.mathdotnet.com
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
// Copyright (c) 2009-2010 Math.NET
//
// Copyright (c) 2009-2013 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
@ -12,8 +14,10 @@
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
@ -39,5 +43,10 @@ namespace MathNet.Numerics.LinearAlgebra.Factorization
public abstract class GramSchmidt<T> : QR<T>
where T : struct, IEquatable<T>, IFormattable
{
protected GramSchmidt(Matrix<T> q, Matrix<T> rFull)
{
Q = q;
MatrixR = rFull;
}
}
}

2
src/Numerics/LinearAlgebra/Single/DenseMatrix.cs

@ -1052,7 +1052,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
public override GramSchmidt<float> GramSchmidt()
{
return new DenseGramSchmidt(this);
return DenseGramSchmidt.Create(this);
}
public override Svd<float> Svd(bool computeVectors)

57
src/Numerics/LinearAlgebra/Single/Factorization/DenseGramSchmidt.cs

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2010 Math.NET
// Copyright (c) 2009-2013 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@ -28,10 +28,9 @@
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
using System;
using MathNet.Numerics.LinearAlgebra.Factorization;
using MathNet.Numerics.Properties;
using System;
using MathNet.Numerics.Providers.LinearAlgebra;
namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
{
@ -42,13 +41,8 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
/// <remarks>
/// The computation of the QR decomposition is done at construction time by modified Gram-Schmidt Orthogonalization.
/// </remarks>
public class DenseGramSchmidt : GramSchmidt
public sealed class DenseGramSchmidt : GramSchmidt
{
/// <summary>
/// used for QR solve
/// </summary>
private readonly ILinearAlgebraProvider _provider = new ManagedLinearAlgebraProvider();
/// <summary>
/// Initializes a new instance of the <see cref="DenseGramSchmidt"/> class. This object creates an orthogonal matrix
/// using the modified Gram-Schmidt method.
@ -57,21 +51,23 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
/// <exception cref="ArgumentNullException">If <paramref name="matrix"/> is <c>null</c>.</exception>
/// <exception cref="ArgumentException">If <paramref name="matrix"/> row count is less then column count</exception>
/// <exception cref="ArgumentException">If <paramref name="matrix"/> is rank deficient</exception>
public DenseGramSchmidt(DenseMatrix matrix)
public static DenseGramSchmidt Create(DenseMatrix matrix)
{
if (matrix == null)
{
throw new ArgumentNullException("matrix");
}
if (matrix.RowCount < matrix.ColumnCount)
{
throw Matrix.DimensionsDontMatch<ArgumentException>(matrix);
}
Q = matrix.Clone();
MatrixR = matrix.CreateMatrix(matrix.ColumnCount, matrix.ColumnCount);
Factorize(((DenseMatrix)Q).Values, Q.RowCount, Q.ColumnCount, ((DenseMatrix)MatrixR).Values);
var q = (DenseMatrix)matrix.Clone();
var r = new DenseMatrix(matrix.ColumnCount, matrix.ColumnCount);
Factorize(q.Values, q.RowCount, q.ColumnCount, r.Values);
return new DenseGramSchmidt(q, r);
}
DenseGramSchmidt(Matrix<float> q, Matrix<float> rFull)
: base(q, rFull)
{
}
/// <summary>
@ -131,17 +127,6 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
/// <param name="result">The left hand side <see cref="Matrix{T}"/>, <b>X</b>.</param>
public override void Solve(Matrix<float> input, Matrix<float> result)
{
// Check for proper arguments.
if (input == null)
{
throw new ArgumentNullException("input");
}
if (result == null)
{
throw new ArgumentNullException("result");
}
// The solution X should have the same number of columns as B
if (input.ColumnCount != result.ColumnCount)
{
@ -172,7 +157,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
throw new NotSupportedException("Can only do GramSchmidt factorization for dense matrices at the moment.");
}
_provider.QRSolveFactored(((DenseMatrix)Q).Values, ((DenseMatrix)MatrixR).Values, Q.RowCount, MatrixR.ColumnCount, null, dinput.Values, input.ColumnCount, dresult.Values, QRMethod.Thin);
Control.LinearAlgebraProvider.QRSolveFactored(((DenseMatrix)Q).Values, ((DenseMatrix)MatrixR).Values, Q.RowCount, MatrixR.ColumnCount, null, dinput.Values, input.ColumnCount, dresult.Values, QRMethod.Thin);
}
/// <summary>
@ -182,16 +167,6 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
/// <param name="result">The left hand side <see cref="Matrix{T}"/>, <b>x</b>.</param>
public override void Solve(Vector<float> input, Vector<float> result)
{
if (input == null)
{
throw new ArgumentNullException("input");
}
if (result == null)
{
throw new ArgumentNullException("result");
}
// Ax=b where A is an m x n matrix
// Check that b is a column vector with m entries
if (Q.RowCount != input.Count)
@ -217,7 +192,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
throw new NotSupportedException("Can only do GramSchmidt factorization for dense vectors at the moment.");
}
_provider.QRSolveFactored(((DenseMatrix)Q).Values, ((DenseMatrix)MatrixR).Values, Q.RowCount, MatrixR.ColumnCount, null, dinput.Values, 1, dresult.Values, QRMethod.Thin);
Control.LinearAlgebraProvider.QRSolveFactored(((DenseMatrix)Q).Values, ((DenseMatrix)MatrixR).Values, Q.RowCount, MatrixR.ColumnCount, null, dinput.Values, 1, dresult.Values, QRMethod.Thin);
}
}
}

16
src/Numerics/LinearAlgebra/Single/Factorization/GramSchmidt.cs

@ -3,7 +3,9 @@
// http://numerics.mathdotnet.com
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
// Copyright (c) 2009-2010 Math.NET
//
// Copyright (c) 2009-2013 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
@ -12,8 +14,10 @@
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
@ -24,13 +28,12 @@
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
using System;
using MathNet.Numerics.LinearAlgebra.Factorization;
using MathNet.Numerics.Properties;
namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
{
using System;
using Properties;
/// <summary>
/// <para>A class which encapsulates the functionality of the QR decomposition Modified Gram-Schmidt Orthogonalization.</para>
/// <para>Any real square matrix A may be decomposed as A = QR where Q is an orthogonal mxn matrix and R is an nxn upper triangular matrix.</para>
@ -40,6 +43,11 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
/// </remarks>
public abstract class GramSchmidt : GramSchmidt<float>
{
protected GramSchmidt(Matrix<float> q, Matrix<float> rFull)
: base(q, rFull)
{
}
/// <summary>
/// Gets the absolute determinant value of the matrix for which the QR matrix was computed.
/// </summary>

67
src/Numerics/LinearAlgebra/Single/Factorization/UserGramSchmidt.cs

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2010 Math.NET
// Copyright (c) 2009-2013 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@ -28,8 +28,8 @@
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
using MathNet.Numerics.Properties;
using System;
using MathNet.Numerics.Properties;
namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
{
@ -40,7 +40,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
/// <remarks>
/// The computation of the QR decomposition is done at construction time by modified Gram-Schmidt Orthogonalization.
/// </remarks>
public class UserGramSchmidt : GramSchmidt
public sealed class UserGramSchmidt : GramSchmidt
{
/// <summary>
/// Initializes a new instance of the <see cref="UserGramSchmidt"/> class. This object creates an orthogonal matrix
@ -50,46 +50,48 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
/// <exception cref="ArgumentNullException">If <paramref name="matrix"/> is <c>null</c>.</exception>
/// <exception cref="ArgumentException">If <paramref name="matrix"/> row count is less then column count</exception>
/// <exception cref="ArgumentException">If <paramref name="matrix"/> is rank deficient</exception>
public UserGramSchmidt(Matrix<float> matrix)
public static UserGramSchmidt Create(Matrix<float> matrix)
{
if (matrix == null)
{
throw new ArgumentNullException("matrix");
}
if (matrix.RowCount < matrix.ColumnCount)
{
throw Matrix.DimensionsDontMatch<ArgumentException>(matrix);
}
Q = matrix.Clone();
MatrixR = matrix.CreateMatrix(matrix.ColumnCount, matrix.ColumnCount);
var q = matrix.Clone();
var r = matrix.CreateMatrix(matrix.ColumnCount, matrix.ColumnCount);
for (var k = 0; k < Q.ColumnCount; k++)
for (var k = 0; k < q.ColumnCount; k++)
{
var norm = Q.Column(k).L2Norm();
var norm = q.Column(k).L2Norm();
if (norm == 0.0)
{
throw new ArgumentException(Resources.ArgumentMatrixNotRankDeficient);
}
MatrixR.At(k, k, norm);
for (var i = 0; i < Q.RowCount; i++)
r.At(k, k, norm);
for (var i = 0; i < q.RowCount; i++)
{
Q.At(i, k, Q.At(i, k) / norm);
q.At(i, k, q.At(i, k) / norm);
}
for (var j = k + 1; j < Q.ColumnCount; j++)
for (var j = k + 1; j < q.ColumnCount; j++)
{
var dot = Q.Column(k).DotProduct(Q.Column(j));
MatrixR.At(k, j, dot);
for (var i = 0; i < Q.RowCount; i++)
var dot = q.Column(k).DotProduct(q.Column(j));
r.At(k, j, dot);
for (var i = 0; i < q.RowCount; i++)
{
var value = Q.At(i, j) - (Q.At(i, k) * dot);
Q.At(i, j, value);
var value = q.At(i, j) - (q.At(i, k) * dot);
q.At(i, j, value);
}
}
}
return new UserGramSchmidt(q, r);
}
UserGramSchmidt(Matrix<float> q, Matrix<float> rFull)
: base(q, rFull)
{
}
/// <summary>
@ -99,17 +101,6 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
/// <param name="result">The left hand side <see cref="Matrix{T}"/>, <b>X</b>.</param>
public override void Solve(Matrix<float> input, Matrix<float> result)
{
// Check for proper arguments.
if (input == null)
{
throw new ArgumentNullException("input");
}
if (result == null)
{
throw new ArgumentNullException("result");
}
// The solution X should have the same number of columns as B
if (input.ColumnCount != result.ColumnCount)
{
@ -184,16 +175,6 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
/// <param name="result">The left hand side <see cref="Matrix{T}"/>, <b>x</b>.</param>
public override void Solve(Vector<float> input, Vector<float> result)
{
if (input == null)
{
throw new ArgumentNullException("input");
}
if (result == null)
{
throw new ArgumentNullException("result");
}
// Ax=b where A is an m x n matrix
// Check that b is a column vector with m entries
if (Q.RowCount != input.Count)

2
src/Numerics/LinearAlgebra/Single/Matrix.cs

@ -476,7 +476,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
public override GramSchmidt<float> GramSchmidt()
{
return new UserGramSchmidt(this);
return UserGramSchmidt.Create(this);
}
public override Svd<float> Svd(bool computeVectors)

13
src/UnitTests/LinearAlgebraTests/Complex/Factorization/GramSchmidtTests.cs

@ -24,10 +24,10 @@
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
using System;
using MathNet.Numerics.LinearAlgebra.Complex;
using MathNet.Numerics.LinearAlgebra.Complex.Factorization;
using NUnit.Framework;
using System;
namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex.Factorization
{
@ -38,22 +38,13 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex.Factorization
/// </summary>
public class GramSchmidtTests
{
/// <summary>
/// Constructor with <c>null</c> throws <c>ArgumentNullException</c>.
/// </summary>
[Test]
public void ConstructorNullThrowsArgumentNullException()
{
Assert.Throws<ArgumentNullException>(() => new DenseGramSchmidt(null));
}
/// <summary>
/// Constructor with wide matrix throws <c>ArgumentException</c>.
/// </summary>
[Test]
public void ConstructorWideMatrixThrowsInvalidMatrixOperationException()
{
Assert.Throws<ArgumentException>(() => new DenseGramSchmidt(new DenseMatrix(3, 4)));
Assert.Throws<ArgumentException>(() => DenseGramSchmidt.Create(new DenseMatrix(3, 4)));
}
/// <summary>

17
src/UnitTests/LinearAlgebraTests/Complex/Factorization/UserGramSchmidtTests.cs

@ -24,33 +24,26 @@
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
using System;
using MathNet.Numerics.LinearAlgebra.Complex.Factorization;
using NUnit.Framework;
namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex.Factorization
{
using System;
using System.Numerics;
using LinearAlgebra.Complex.Factorization;
using NUnit.Framework;
/// <summary>
/// GramSchmidt factorization tests for a user matrix.
/// </summary>
public class UserGramSchmidtTests
{
/// <summary>
/// Constructor with <c>null</c> throws <c>ArgumentNullException</c>.
/// </summary>
public void ConstructorNullThrowsArgumentNullException()
{
Assert.Throws<ArgumentNullException>(() => new UserGramSchmidt(null));
}
/// <summary>
/// Constructor with wide matrix throws <c>ArgumentException</c>.
/// </summary>
[Test]
public void ConstructorWideMatrixThrowsInvalidMatrixOperationException()
{
Assert.Throws<ArgumentException>(() => new UserGramSchmidt(new UserDefinedMatrix(3, 4)));
Assert.Throws<ArgumentException>(() => UserGramSchmidt.Create(new UserDefinedMatrix(3, 4)));
}
/// <summary>

13
src/UnitTests/LinearAlgebraTests/Complex32/Factorization/GramSchmidtTests.cs

@ -24,10 +24,10 @@
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
using System;
using MathNet.Numerics.LinearAlgebra.Complex32;
using MathNet.Numerics.LinearAlgebra.Complex32.Factorization;
using NUnit.Framework;
using System;
namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex32.Factorization
{
@ -38,22 +38,13 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex32.Factorization
/// </summary>
public class GramSchmidtTests
{
/// <summary>
/// Constructor with <c>null</c> throws <c>ArgumentNullException</c>.
/// </summary>
[Test]
public void ConstructorNullThrowsArgumentNullException()
{
Assert.Throws<ArgumentNullException>(() => new DenseGramSchmidt(null));
}
/// <summary>
/// Constructor with wide matrix throws <c>ArgumentException</c>.
/// </summary>
[Test]
public void ConstructorWideMatrixThrowsInvalidMatrixOperationException()
{
Assert.Throws<ArgumentException>(() => new DenseGramSchmidt(new DenseMatrix(3, 4)));
Assert.Throws<ArgumentException>(() => DenseGramSchmidt.Create(new DenseMatrix(3, 4)));
}
/// <summary>

19
src/UnitTests/LinearAlgebraTests/Complex32/Factorization/UserGramSchmidtTests.cs

@ -24,33 +24,26 @@
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
using System;
using MathNet.Numerics.LinearAlgebra.Complex32.Factorization;
using NUnit.Framework;
namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex32.Factorization
{
using System;
using LinearAlgebra.Complex32.Factorization;
using NUnit.Framework;
using Complex32 = Numerics.Complex32;
using Numerics;
/// <summary>
/// GramSchmidt factorization tests for a user matrix.
/// </summary>
public class UserGramSchmidtTests
{
/// <summary>
/// Constructor with <c>null</c> throws <c>ArgumentNullException</c>.
/// </summary>
public void ConstructorNullThrowsArgumentNullException()
{
Assert.Throws<ArgumentNullException>(() => new UserGramSchmidt(null));
}
/// <summary>
/// Constructor with wide matrix throws <c>ArgumentException</c>.
/// </summary>
[Test]
public void ConstructorWideMatrixThrowsInvalidMatrixOperationException()
{
Assert.Throws<ArgumentException>(() => new UserGramSchmidt(new UserDefinedMatrix(3, 4)));
Assert.Throws<ArgumentException>(() => UserGramSchmidt.Create(new UserDefinedMatrix(3, 4)));
}
/// <summary>

13
src/UnitTests/LinearAlgebraTests/Double/Factorization/GramSchmidtTests.cs

@ -24,10 +24,10 @@
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
using System;
using MathNet.Numerics.LinearAlgebra.Double;
using MathNet.Numerics.LinearAlgebra.Double.Factorization;
using NUnit.Framework;
using System;
namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double.Factorization
{
@ -36,22 +36,13 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double.Factorization
/// </summary>
public class GramSchmidtTests
{
/// <summary>
/// Constructor with <c>null</c> throws <c>ArgumentNullException</c>.
/// </summary>
[Test]
public void ConstructorNullThrowsArgumentNullException()
{
Assert.Throws<ArgumentNullException>(() => new DenseGramSchmidt(null));
}
/// <summary>
/// Constructor with wide matrix throws <c>ArgumentException</c>.
/// </summary>
[Test]
public void ConstructorWideMatrixThrowsInvalidMatrixOperationException()
{
Assert.Throws<ArgumentException>(() => new DenseGramSchmidt(new DenseMatrix(3, 4)));
Assert.Throws<ArgumentException>(() => DenseGramSchmidt.Create(new DenseMatrix(3, 4)));
}
/// <summary>

18
src/UnitTests/LinearAlgebraTests/Double/Factorization/UserGramSchmidtTests.cs

@ -24,32 +24,24 @@
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
using System;
using MathNet.Numerics.LinearAlgebra.Double.Factorization;
using NUnit.Framework;
namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double.Factorization
{
using System;
using LinearAlgebra.Double.Factorization;
using NUnit.Framework;
/// <summary>
/// GramSchmidt factorization tests for a user matrix.
/// </summary>
public class UserGramSchmidtTests
{
/// <summary>
/// Constructor with <c>null</c> throws <c>ArgumentNullException</c>.
/// </summary>
public void ConstructorNullThrowsArgumentNullException()
{
Assert.Throws<ArgumentNullException>(() => new UserGramSchmidt(null));
}
/// <summary>
/// Constructor with wide matrix throws <c>ArgumentException</c>.
/// </summary>
[Test]
public void ConstructorWideMatrixThrowsInvalidMatrixOperationException()
{
Assert.Throws<ArgumentException>(() => new UserGramSchmidt(new UserDefinedMatrix(3, 4)));
Assert.Throws<ArgumentException>(() => UserGramSchmidt.Create(new UserDefinedMatrix(3, 4)));
}
/// <summary>

13
src/UnitTests/LinearAlgebraTests/Single/Factorization/GramSchmidtTests.cs

@ -24,10 +24,10 @@
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
using System;
using MathNet.Numerics.LinearAlgebra.Single;
using MathNet.Numerics.LinearAlgebra.Single.Factorization;
using NUnit.Framework;
using System;
namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Single.Factorization
{
@ -36,22 +36,13 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Single.Factorization
/// </summary>
public class GramSchmidtTests
{
/// <summary>
/// Constructor with <c>null</c> throws <c>ArgumentNullException</c>.
/// </summary>
[Test]
public void ConstructorNullThrowsArgumentNullException()
{
Assert.Throws<ArgumentNullException>(() => new DenseGramSchmidt(null));
}
/// <summary>
/// Constructor with wide matrix throws <c>ArgumentException</c>.
/// </summary>
[Test]
public void ConstructorWideMatrixThrowsInvalidMatrixOperationException()
{
Assert.Throws<ArgumentException>(() => new DenseGramSchmidt(new DenseMatrix(3, 4)));
Assert.Throws<ArgumentException>(() => DenseGramSchmidt.Create(new DenseMatrix(3, 4)));
}
/// <summary>

18
src/UnitTests/LinearAlgebraTests/Single/Factorization/UserGramSchmidtTests.cs

@ -24,32 +24,24 @@
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
using System;
using MathNet.Numerics.LinearAlgebra.Single.Factorization;
using NUnit.Framework;
namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Single.Factorization
{
using System;
using LinearAlgebra.Single.Factorization;
using NUnit.Framework;
/// <summary>
/// GramSchmidt factorization tests for a user matrix.
/// </summary>
public class UserGramSchmidtTests
{
/// <summary>
/// Constructor with <c>null</c> throws <c>ArgumentNullException</c>.
/// </summary>
public void ConstructorNullThrowsArgumentNullException()
{
Assert.Throws<ArgumentNullException>(() => new UserGramSchmidt(null));
}
/// <summary>
/// Constructor with wide matrix throws <c>ArgumentException</c>.
/// </summary>
[Test]
public void ConstructorWideMatrixThrowsInvalidMatrixOperationException()
{
Assert.Throws<ArgumentException>(() => new UserGramSchmidt(new UserDefinedMatrix(3, 4)));
Assert.Throws<ArgumentException>(() => UserGramSchmidt.Create(new UserDefinedMatrix(3, 4)));
}
/// <summary>

Loading…
Cancel
Save