Browse Source

fixed dimension check with tall matrices and thin qr

pull/84/head
Marcus Cuda 14 years ago
parent
commit
53679353bf
  1. 8
      src/Numerics/LinearAlgebra/Complex/Factorization/DenseQR.cs
  2. 8
      src/Numerics/LinearAlgebra/Complex32/Factorization/DenseQR.cs
  3. 8
      src/Numerics/LinearAlgebra/Double/Factorization/DenseQR.cs
  4. 8
      src/Numerics/LinearAlgebra/Single/Factorization/DenseQR.cs
  5. 76
      src/UnitTests/LinearAlgebraTests/Complex/Factorization/QRTests.cs
  6. 75
      src/UnitTests/LinearAlgebraTests/Complex32/Factorization/QRTests.cs
  7. 76
      src/UnitTests/LinearAlgebraTests/Double/Factorization/QRTests.cs
  8. 76
      src/UnitTests/LinearAlgebraTests/Single/Factorization/QRTests.cs

8
src/Numerics/LinearAlgebra/Complex/Factorization/DenseQR.cs

@ -121,7 +121,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
}
// The dimension compatibility conditions for X = A\B require the two matrices A and B to have the same number of rows
if (MatrixR.RowCount != input.RowCount)
if (MatrixQ.RowCount != input.RowCount)
{
throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension);
}
@ -144,7 +144,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
throw new NotSupportedException("Can only do QR factorization for dense matrices at the moment.");
}
Control.LinearAlgebraProvider.QRSolveFactored(((DenseMatrix)MatrixQ).Values, ((DenseMatrix)MatrixR).Values, MatrixR.RowCount, MatrixR.ColumnCount, Tau, dinput.Values, input.ColumnCount, dresult.Values, QrMethod);
Control.LinearAlgebraProvider.QRSolveFactored(((DenseMatrix)MatrixQ).Values, ((DenseMatrix)MatrixR).Values, MatrixQ.RowCount, MatrixR.ColumnCount, Tau, dinput.Values, input.ColumnCount, dresult.Values, QrMethod);
}
/// <summary>
@ -166,7 +166,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
// Ax=b where A is an m x n matrix
// Check that b is a column vector with m entries
if (MatrixR.RowCount != input.Count)
if (MatrixQ.RowCount != input.Count)
{
throw new ArgumentException(Resources.ArgumentVectorsSameLength);
}
@ -189,7 +189,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
throw new NotSupportedException("Can only do QR factorization for dense vectors at the moment.");
}
Control.LinearAlgebraProvider.QRSolveFactored(((DenseMatrix)MatrixQ).Values, ((DenseMatrix)MatrixR).Values, MatrixR.RowCount, MatrixR.ColumnCount, Tau, dinput.Values, 1, dresult.Values, QrMethod);
Control.LinearAlgebraProvider.QRSolveFactored(((DenseMatrix)MatrixQ).Values, ((DenseMatrix)MatrixR).Values, MatrixQ.RowCount, MatrixR.ColumnCount, Tau, dinput.Values, 1, dresult.Values, QrMethod);
}
}
}

8
src/Numerics/LinearAlgebra/Complex32/Factorization/DenseQR.cs

@ -121,7 +121,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
}
// The dimension compatibility conditions for X = A\B require the two matrices A and B to have the same number of rows
if (MatrixR.RowCount != input.RowCount)
if (MatrixQ.RowCount != input.RowCount)
{
throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension);
}
@ -144,7 +144,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
throw new NotSupportedException("Can only do QR factorization for dense matrices at the moment.");
}
Control.LinearAlgebraProvider.QRSolveFactored(((DenseMatrix)MatrixQ).Values, ((DenseMatrix)MatrixR).Values, MatrixR.RowCount, MatrixR.ColumnCount, Tau, dinput.Values, input.ColumnCount, dresult.Values, QrMethod);
Control.LinearAlgebraProvider.QRSolveFactored(((DenseMatrix)MatrixQ).Values, ((DenseMatrix)MatrixR).Values, MatrixQ.RowCount, MatrixR.ColumnCount, Tau, dinput.Values, input.ColumnCount, dresult.Values, QrMethod);
}
/// <summary>
@ -166,7 +166,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
// Ax=b where A is an m x n matrix
// Check that b is a column vector with m entries
if (MatrixR.RowCount != input.Count)
if (MatrixQ.RowCount != input.Count)
{
throw new ArgumentException(Resources.ArgumentVectorsSameLength);
}
@ -189,7 +189,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
throw new NotSupportedException("Can only do QR factorization for dense vectors at the moment.");
}
Control.LinearAlgebraProvider.QRSolveFactored(((DenseMatrix)MatrixQ).Values, ((DenseMatrix)MatrixR).Values, MatrixR.RowCount, MatrixR.ColumnCount, Tau, dinput.Values, 1, dresult.Values, QrMethod);
Control.LinearAlgebraProvider.QRSolveFactored(((DenseMatrix)MatrixQ).Values, ((DenseMatrix)MatrixR).Values, MatrixQ.RowCount, MatrixR.ColumnCount, Tau, dinput.Values, 1, dresult.Values, QrMethod);
}
}
}

8
src/Numerics/LinearAlgebra/Double/Factorization/DenseQR.cs

@ -121,7 +121,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
}
// The dimension compatibility conditions for X = A\B require the two matrices A and B to have the same number of rows
if (MatrixR.RowCount != input.RowCount)
if (MatrixQ.RowCount != input.RowCount)
{
throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension);
}
@ -144,7 +144,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
throw new NotSupportedException("Can only do QR factorization for dense matrices at the moment.");
}
Control.LinearAlgebraProvider.QRSolveFactored(((DenseMatrix)MatrixQ).Values, ((DenseMatrix)MatrixR).Values, MatrixR.RowCount, MatrixR.ColumnCount, Tau, dinput.Values, input.ColumnCount, dresult.Values, QrMethod);
Control.LinearAlgebraProvider.QRSolveFactored(((DenseMatrix)MatrixQ).Values, ((DenseMatrix)MatrixR).Values, MatrixQ.RowCount, MatrixR.ColumnCount, Tau, dinput.Values, input.ColumnCount, dresult.Values, QrMethod);
}
/// <summary>
@ -166,7 +166,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
// Ax=b where A is an m x n matrix
// Check that b is a column vector with m entries
if (MatrixR.RowCount != input.Count)
if (MatrixQ.RowCount != input.Count)
{
throw new ArgumentException(Resources.ArgumentVectorsSameLength);
}
@ -189,7 +189,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
throw new NotSupportedException("Can only do QR factorization for dense vectors at the moment.");
}
Control.LinearAlgebraProvider.QRSolveFactored(((DenseMatrix)MatrixQ).Values, ((DenseMatrix)MatrixR).Values, MatrixR.RowCount, MatrixR.ColumnCount, Tau, dinput.Values, 1, dresult.Values, QrMethod);
Control.LinearAlgebraProvider.QRSolveFactored(((DenseMatrix)MatrixQ).Values, ((DenseMatrix)MatrixR).Values, MatrixQ.RowCount, MatrixR.ColumnCount, Tau, dinput.Values, 1, dresult.Values, QrMethod);
}
}
}

8
src/Numerics/LinearAlgebra/Single/Factorization/DenseQR.cs

@ -120,7 +120,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
}
// The dimension compatibility conditions for X = A\B require the two matrices A and B to have the same number of rows
if (MatrixR.RowCount != input.RowCount)
if (MatrixQ.RowCount != input.RowCount)
{
throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension);
}
@ -143,7 +143,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
throw new NotSupportedException("Can only do QR factorization for dense matrices at the moment.");
}
Control.LinearAlgebraProvider.QRSolveFactored(((DenseMatrix)MatrixQ).Values, ((DenseMatrix)MatrixR).Values, MatrixR.RowCount, MatrixR.ColumnCount, Tau, dinput.Values, input.ColumnCount, dresult.Values, QrMethod);
Control.LinearAlgebraProvider.QRSolveFactored(((DenseMatrix)MatrixQ).Values, ((DenseMatrix)MatrixR).Values, MatrixQ.RowCount, MatrixR.ColumnCount, Tau, dinput.Values, input.ColumnCount, dresult.Values, QrMethod);
}
/// <summary>
@ -165,7 +165,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
// Ax=b where A is an m x n matrix
// Check that b is a column vector with m entries
if (MatrixR.RowCount != input.Count)
if (MatrixQ.RowCount != input.Count)
{
throw new ArgumentException(Resources.ArgumentVectorsSameLength);
}
@ -188,7 +188,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
throw new NotSupportedException("Can only do QR factorization for dense vectors at the moment.");
}
Control.LinearAlgebraProvider.QRSolveFactored(((DenseMatrix)MatrixQ).Values, ((DenseMatrix)MatrixR).Values, MatrixR.RowCount, MatrixR.ColumnCount, Tau, dinput.Values, 1, dresult.Values, QrMethod);
Control.LinearAlgebraProvider.QRSolveFactored(((DenseMatrix)MatrixQ).Values, ((DenseMatrix)MatrixR).Values, MatrixQ.RowCount, MatrixR.ColumnCount, Tau, dinput.Values, 1, dresult.Values, QrMethod);
}
}
}

76
src/UnitTests/LinearAlgebraTests/Complex/Factorization/QRTests.cs

@ -647,5 +647,81 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex.Factorization
}
}
}
/// <summary>
/// Can solve when using a tall matrix.
/// </summary>
/// <param name="method">The QR decomp method to use.</param>
[TestCase(QRMethod.Full)]
[TestCase(QRMethod.Thin)]
public void CanSolveForMatrixWithTallRandomMatrix(QRMethod method)
{
var matrixA = MatrixLoader.GenerateRandomDenseMatrix(20, 10);
var matrixACopy = matrixA.Clone();
var factorQR = matrixA.QR(method);
var matrixB = MatrixLoader.GenerateRandomDenseMatrix(20, 5);
var matrixX = factorQR.Solve(matrixB);
// The solution X row dimension is equal to the column dimension of A
Assert.AreEqual(matrixA.ColumnCount, matrixX.RowCount);
// The solution X has the same number of columns as B
Assert.AreEqual(matrixB.ColumnCount, matrixX.ColumnCount);
var test = (matrixA.ConjugateTranspose() * matrixA).Inverse() * matrixA.ConjugateTranspose() * matrixB;
for (var i = 0; i < matrixX.RowCount; i++)
{
for (var j = 0; j < matrixX.ColumnCount; j++)
{
AssertHelpers.AlmostEqual(test[i, j], matrixX[i, j], 9);
}
}
// Make sure A didn't change.
for (var i = 0; i < matrixA.RowCount; i++)
{
for (var j = 0; j < matrixA.ColumnCount; j++)
{
Assert.AreEqual(matrixACopy[i, j], matrixA[i, j]);
}
}
}
/// <summary>
/// Can solve when using a tall matrix.
/// </summary>
/// <param name="method">The QR decomp method to use.</param>
[TestCase(QRMethod.Full)]
[TestCase(QRMethod.Thin)]
public void CanSolveForVectorWithTallRandomMatrix(QRMethod method)
{
var matrixA = MatrixLoader.GenerateRandomDenseMatrix(20, 10);
var matrixACopy = matrixA.Clone();
var factorQR = matrixA.QR(method);
var vectorB = MatrixLoader.GenerateRandomDenseVector(20);
var vectorX = factorQR.Solve(vectorB);
// The solution x dimension is equal to the column dimension of A
Assert.AreEqual(matrixA.ColumnCount, vectorX.Count);
var test = (matrixA.ConjugateTranspose() * matrixA).Inverse() * matrixA.ConjugateTranspose()* vectorB;
for (var i = 0; i < vectorX.Count; i++)
{
AssertHelpers.AlmostEqual(test[i], vectorX[i], 9);
}
// Make sure A didn't change.
for (var i = 0; i < matrixA.RowCount; i++)
{
for (var j = 0; j < matrixA.ColumnCount; j++)
{
Assert.AreEqual(matrixACopy[i, j], matrixA[i, j]);
}
}
}
}
}

75
src/UnitTests/LinearAlgebraTests/Complex32/Factorization/QRTests.cs

@ -656,5 +656,80 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex32.Factorization
}
}
}
/// <summary>
/// Can solve when using a tall matrix.
/// </summary>
/// <param name="method">The QR decomp method to use.</param>
[TestCase(QRMethod.Full)]
[TestCase(QRMethod.Thin)]
public void CanSolveForMatrixWithTallRandomMatrix(QRMethod method)
{
var matrixA = MatrixLoader.GenerateRandomDenseMatrix(20, 10);
var matrixACopy = matrixA.Clone();
var factorQR = matrixA.QR(method);
var matrixB = MatrixLoader.GenerateRandomDenseMatrix(20, 5);
var matrixX = factorQR.Solve(matrixB);
// The solution X row dimension is equal to the column dimension of A
Assert.AreEqual(matrixA.ColumnCount, matrixX.RowCount);
// The solution X has the same number of columns as B
Assert.AreEqual(matrixB.ColumnCount, matrixX.ColumnCount);
var test = (matrixA.ConjugateTranspose() * matrixA).Inverse() * matrixA.ConjugateTranspose() * matrixB;
for (var i = 0; i < matrixX.RowCount; i++)
{
for (var j = 0; j < matrixX.ColumnCount; j++)
{
AssertHelpers.AlmostEqual(test[i, j], matrixX[i, j], 4);
}
}
// Make sure A didn't change.
for (var i = 0; i < matrixA.RowCount; i++)
{
for (var j = 0; j < matrixA.ColumnCount; j++)
{
Assert.AreEqual(matrixACopy[i, j], matrixA[i, j]);
}
}
}
/// <summary>
/// Can solve when using a tall matrix.
/// </summary>
/// <param name="method">The QR decomp method to use.</param>
[TestCase(QRMethod.Full)]
[TestCase(QRMethod.Thin)]
public void CanSolveForVectorWithTallRandomMatrix(QRMethod method)
{
var matrixA = MatrixLoader.GenerateRandomDenseMatrix(20, 10);
var matrixACopy = matrixA.Clone();
var factorQR = matrixA.QR(method);
var vectorB = MatrixLoader.GenerateRandomDenseVector(20);
var vectorX = factorQR.Solve(vectorB);
// The solution x dimension is equal to the column dimension of A
Assert.AreEqual(matrixA.ColumnCount, vectorX.Count);
var test = (matrixA.ConjugateTranspose() * matrixA).Inverse() * matrixA.ConjugateTranspose() * vectorB;
for (var i = 0; i < vectorX.Count; i++)
{
AssertHelpers.AlmostEqual(test[i], vectorX[i], 4);
}
// Make sure A didn't change.
for (var i = 0; i < matrixA.RowCount; i++)
{
for (var j = 0; j < matrixA.ColumnCount; j++)
{
Assert.AreEqual(matrixACopy[i, j], matrixA[i, j]);
}
}
}
}
}

76
src/UnitTests/LinearAlgebraTests/Double/Factorization/QRTests.cs

@ -642,5 +642,81 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double.Factorization
}
}
}
/// <summary>
/// Can solve when using a tall matrix.
/// </summary>
/// <param name="method">The QR decomp method to use.</param>
[TestCase(QRMethod.Full)]
[TestCase(QRMethod.Thin)]
public void CanSolveForMatrixWithTallRandomMatrix(QRMethod method)
{
var matrixA = MatrixLoader.GenerateRandomDenseMatrix(20, 10);
var matrixACopy = matrixA.Clone();
var factorQR = matrixA.QR(method);
var matrixB = MatrixLoader.GenerateRandomDenseMatrix(20, 5);
var matrixX = factorQR.Solve(matrixB);
// The solution X row dimension is equal to the column dimension of A
Assert.AreEqual(matrixA.ColumnCount, matrixX.RowCount);
// The solution X has the same number of columns as B
Assert.AreEqual(matrixB.ColumnCount, matrixX.ColumnCount);
var test = (matrixA.Transpose() * matrixA).Inverse() * matrixA.Transpose() * matrixB;
for (var i = 0; i < matrixX.RowCount; i++)
{
for (var j = 0; j < matrixX.ColumnCount; j++)
{
AssertHelpers.AlmostEqual(test[i, j], matrixX[i, j], 9);
}
}
// Make sure A didn't change.
for (var i = 0; i < matrixA.RowCount; i++)
{
for (var j = 0; j < matrixA.ColumnCount; j++)
{
Assert.AreEqual(matrixACopy[i, j], matrixA[i, j]);
}
}
}
/// <summary>
/// Can solve when using a tall matrix.
/// </summary>
/// <param name="method">The QR decomp method to use.</param>
[TestCase(QRMethod.Full)]
[TestCase(QRMethod.Thin)]
public void CanSolveForVectorWithTallRandomMatrix(QRMethod method)
{
var matrixA = MatrixLoader.GenerateRandomDenseMatrix(20, 10);
var matrixACopy = matrixA.Clone();
var factorQR = matrixA.QR(method);
var vectorB = MatrixLoader.GenerateRandomDenseVector(20);
var vectorX = factorQR.Solve(vectorB);
// The solution x dimension is equal to the column dimension of A
Assert.AreEqual(matrixA.ColumnCount, vectorX.Count);
var test = (matrixA.Transpose() * matrixA).Inverse() * matrixA.Transpose() * vectorB;
for (var i = 0; i < vectorX.Count; i++)
{
AssertHelpers.AlmostEqual(test[i], vectorX[i], 9);
}
// Make sure A didn't change.
for (var i = 0; i < matrixA.RowCount; i++)
{
for (var j = 0; j < matrixA.ColumnCount; j++)
{
Assert.AreEqual(matrixACopy[i, j], matrixA[i, j]);
}
}
}
}
}

76
src/UnitTests/LinearAlgebraTests/Single/Factorization/QRTests.cs

@ -643,5 +643,81 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Single.Factorization
}
}
}
/// <summary>
/// Can solve when using a tall matrix.
/// </summary>
/// <param name="method">The QR decomp method to use.</param>
[TestCase(QRMethod.Full)]
[TestCase(QRMethod.Thin)]
public void CanSolveForMatrixWithTallRandomMatrix(QRMethod method)
{
var matrixA = MatrixLoader.GenerateRandomDenseMatrix(20, 10);
var matrixACopy = matrixA.Clone();
var factorQR = matrixA.QR(method);
var matrixB = MatrixLoader.GenerateRandomDenseMatrix(20, 5);
var matrixX = factorQR.Solve(matrixB);
// The solution X row dimension is equal to the column dimension of A
Assert.AreEqual(matrixA.ColumnCount, matrixX.RowCount);
// The solution X has the same number of columns as B
Assert.AreEqual(matrixB.ColumnCount, matrixX.ColumnCount);
var test = (matrixA.Transpose() * matrixA).Inverse() * matrixA.Transpose() * matrixB;
for (var i = 0; i < matrixX.RowCount; i++)
{
for (var j = 0; j < matrixX.ColumnCount; j++)
{
AssertHelpers.AlmostEqual(test[i, j], matrixX[i, j], 4);
}
}
// Make sure A didn't change.
for (var i = 0; i < matrixA.RowCount; i++)
{
for (var j = 0; j < matrixA.ColumnCount; j++)
{
Assert.AreEqual(matrixACopy[i, j], matrixA[i, j]);
}
}
}
/// <summary>
/// Can solve when using a tall matrix.
/// </summary>
/// <param name="method">The QR decomp method to use.</param>
[TestCase(QRMethod.Full)]
[TestCase(QRMethod.Thin)]
public void CanSolveForVectorWithTallRandomMatrix(QRMethod method)
{
var matrixA = MatrixLoader.GenerateRandomDenseMatrix(20, 10);
var matrixACopy = matrixA.Clone();
var factorQR = matrixA.QR(method);
var vectorB = MatrixLoader.GenerateRandomDenseVector(20);
var vectorX = factorQR.Solve(vectorB);
// The solution x dimension is equal to the column dimension of A
Assert.AreEqual(matrixA.ColumnCount, vectorX.Count);
var test = (matrixA.Transpose() * matrixA).Inverse() * matrixA.Transpose() * vectorB;
for (var i = 0; i < vectorX.Count; i++)
{
AssertHelpers.AlmostEqual(test[i], vectorX[i], 4);
}
// Make sure A didn't change.
for (var i = 0; i < matrixA.RowCount; i++)
{
for (var j = 0; j < matrixA.ColumnCount; j++)
{
Assert.AreEqual(matrixACopy[i, j], matrixA[i, j]);
}
}
}
}
}

Loading…
Cancel
Save