Browse Source

LA: slightly reworked EVD unit tests

provider
Christoph Ruegg 13 years ago
parent
commit
04d36411d5
  1. 8
      src/Numerics/LinearAlgebra/Factorization/Evd.cs
  2. 155
      src/UnitTests/AssertHelpers.cs
  3. 374
      src/UnitTests/LinearAlgebraTests/Complex/Factorization/EvdTests.cs
  4. 195
      src/UnitTests/LinearAlgebraTests/Complex/Factorization/UserEvdTests.cs
  5. 371
      src/UnitTests/LinearAlgebraTests/Complex32/Factorization/EvdTests.cs
  6. 185
      src/UnitTests/LinearAlgebraTests/Complex32/Factorization/UserEvdTests.cs
  7. 373
      src/UnitTests/LinearAlgebraTests/Double/Factorization/EvdTests.cs
  8. 195
      src/UnitTests/LinearAlgebraTests/Double/Factorization/UserEvdTests.cs
  9. 361
      src/UnitTests/LinearAlgebraTests/Single/Factorization/EvdTests.cs
  10. 195
      src/UnitTests/LinearAlgebraTests/Single/Factorization/UserEvdTests.cs

8
src/Numerics/LinearAlgebra/Factorization/Evd.cs

@ -103,7 +103,7 @@ namespace MathNet.Numerics.LinearAlgebra.Factorization
public Matrix<T> D { get; private set; } public Matrix<T> D { get; private set; }
/// <summary> /// <summary>
/// Solves a system of linear equations, <b>AX = B</b>, with A SVD factorized. /// Solves a system of linear equations, <b>AX = B</b>, with A EVD factorized.
/// </summary> /// </summary>
/// <param name="input">The right hand side <see cref="Matrix{T}"/>, <b>B</b>.</param> /// <param name="input">The right hand side <see cref="Matrix{T}"/>, <b>B</b>.</param>
/// <returns>The left hand side <see cref="Matrix{T}"/>, <b>X</b>.</returns> /// <returns>The left hand side <see cref="Matrix{T}"/>, <b>X</b>.</returns>
@ -115,14 +115,14 @@ namespace MathNet.Numerics.LinearAlgebra.Factorization
} }
/// <summary> /// <summary>
/// Solves a system of linear equations, <b>AX = B</b>, with A SVD factorized. /// Solves a system of linear equations, <b>AX = B</b>, with A EVD factorized.
/// </summary> /// </summary>
/// <param name="input">The right hand side <see cref="Matrix{T}"/>, <b>B</b>.</param> /// <param name="input">The right hand side <see cref="Matrix{T}"/>, <b>B</b>.</param>
/// <param name="result">The left hand side <see cref="Matrix{T}"/>, <b>X</b>.</param> /// <param name="result">The left hand side <see cref="Matrix{T}"/>, <b>X</b>.</param>
public abstract void Solve(Matrix<T> input, Matrix<T> result); public abstract void Solve(Matrix<T> input, Matrix<T> result);
/// <summary> /// <summary>
/// Solves a system of linear equations, <b>Ax = b</b>, with A SVD factorized. /// Solves a system of linear equations, <b>Ax = b</b>, with A EVD factorized.
/// </summary> /// </summary>
/// <param name="input">The right hand side vector, <b>b</b>.</param> /// <param name="input">The right hand side vector, <b>b</b>.</param>
/// <returns>The left hand side <see cref="Vector{T}"/>, <b>x</b>.</returns> /// <returns>The left hand side <see cref="Vector{T}"/>, <b>x</b>.</returns>
@ -134,7 +134,7 @@ namespace MathNet.Numerics.LinearAlgebra.Factorization
} }
/// <summary> /// <summary>
/// Solves a system of linear equations, <b>Ax = b</b>, with A SVD factorized. /// Solves a system of linear equations, <b>Ax = b</b>, with A EVD factorized.
/// </summary> /// </summary>
/// <param name="input">The right hand side vector, <b>b</b>.</param> /// <param name="input">The right hand side vector, <b>b</b>.</param>
/// <param name="result">The left hand side <see cref="Matrix{T}"/>, <b>x</b>.</param> /// <param name="result">The left hand side <see cref="Matrix{T}"/>, <b>x</b>.</param>

155
src/UnitTests/AssertHelpers.cs

@ -25,6 +25,7 @@
// </copyright> // </copyright>
using System.Collections.Generic; using System.Collections.Generic;
using MathNet.Numerics.LinearAlgebra;
using NUnit.Framework; using NUnit.Framework;
namespace MathNet.Numerics.UnitTests namespace MathNet.Numerics.UnitTests
@ -38,7 +39,7 @@ namespace MathNet.Numerics.UnitTests
/// <summary> /// <summary>
/// A class which includes some assertion helper methods particularly for numerical code. /// A class which includes some assertion helper methods particularly for numerical code.
/// </summary> /// </summary>
internal class AssertHelpers internal static class AssertHelpers
{ {
public static void AlmostEqual(Complex expected, Complex actual) public static void AlmostEqual(Complex expected, Complex actual)
{ {
@ -269,5 +270,157 @@ namespace MathNet.Numerics.UnitTests
} }
} }
} }
public static void AlmostEqual(Matrix<double> expected, Matrix<double> actual, int decimalPlaces)
{
if (expected.ColumnCount != actual.ColumnCount || expected.RowCount != actual.RowCount)
{
Assert.Fail("Matrix dimensions mismatch. Expected: {0}; Actual: {1}", expected.ToTypeString(), actual.ToTypeString());
}
for (var i = 0; i < expected.RowCount; i++)
{
for (var j = 0; j < expected.ColumnCount; j++)
{
if (!actual.At(i, j).AlmostEqual(expected.At(i, j), decimalPlaces))
{
Assert.Fail("Not equal within {0} places. Expected:{1}; Actual:{2}", decimalPlaces, expected.At(i, j), actual.At(i, j));
}
}
}
}
public static void AlmostEqual(Matrix<float> expected, Matrix<float> actual, int decimalPlaces)
{
if (expected.ColumnCount != actual.ColumnCount || expected.RowCount != actual.RowCount)
{
Assert.Fail("Matrix dimensions mismatch. Expected: {0}; Actual: {1}", expected.ToTypeString(), actual.ToTypeString());
}
for (var i = 0; i < expected.RowCount; i++)
{
for (var j = 0; j < expected.ColumnCount; j++)
{
if (!actual.At(i, j).AlmostEqual(expected.At(i, j), decimalPlaces))
{
Assert.Fail("Not equal within {0} places. Expected:{1}; Actual:{2}", decimalPlaces, expected.At(i, j), actual.At(i, j));
}
}
}
}
public static void AlmostEqual(Matrix<Complex> expected, Matrix<Complex> actual, int decimalPlaces)
{
if (expected.ColumnCount != actual.ColumnCount || expected.RowCount != actual.RowCount)
{
Assert.Fail("Matrix dimensions mismatch. Expected: {0}; Actual: {1}", expected.ToTypeString(), actual.ToTypeString());
}
for (var i = 0; i < expected.RowCount; i++)
{
for (var j = 0; j < expected.ColumnCount; j++)
{
if (!actual.At(i, j).AlmostEqual(expected.At(i, j), decimalPlaces))
{
Assert.Fail("Not equal within {0} places. Expected:{1}; Actual:{2}", decimalPlaces, expected.At(i, j), actual.At(i, j));
}
}
}
}
public static void AlmostEqual(Matrix<Complex32> expected, Matrix<Complex32> actual, int decimalPlaces)
{
if (expected.ColumnCount != actual.ColumnCount || expected.RowCount != actual.RowCount)
{
Assert.Fail("Matrix dimensions mismatch. Expected: {0}; Actual: {1}", expected.ToTypeString(), actual.ToTypeString());
}
for (var i = 0; i < expected.RowCount; i++)
{
for (var j = 0; j < expected.ColumnCount; j++)
{
if (!actual.At(i, j).AlmostEqual(expected.At(i, j), decimalPlaces))
{
Assert.Fail("Not equal within {0} places. Expected:{1}; Actual:{2}", decimalPlaces, expected.At(i, j), actual.At(i, j));
}
}
}
}
public static void AlmostEqualRelative(Matrix<double> expected, Matrix<double> actual, int decimalPlaces)
{
if (expected.ColumnCount != actual.ColumnCount || expected.RowCount != actual.RowCount)
{
Assert.Fail("Matrix dimensions mismatch. Expected: {0}; Actual: {1}", expected.ToTypeString(), actual.ToTypeString());
}
for (var i = 0; i < expected.RowCount; i++)
{
for (var j = 0; j < expected.ColumnCount; j++)
{
if (!actual.At(i, j).AlmostEqualRelative(expected.At(i, j), decimalPlaces))
{
Assert.Fail("Not equal within {0} relative places. Expected:{1}; Actual:{2}", decimalPlaces, expected.At(i, j), actual.At(i, j));
}
}
}
}
public static void AlmostEqualRelative(Matrix<float> expected, Matrix<float> actual, int decimalPlaces)
{
if (expected.ColumnCount != actual.ColumnCount || expected.RowCount != actual.RowCount)
{
Assert.Fail("Matrix dimensions mismatch. Expected: {0}; Actual: {1}", expected.ToTypeString(), actual.ToTypeString());
}
for (var i = 0; i < expected.RowCount; i++)
{
for (var j = 0; j < expected.ColumnCount; j++)
{
if (!actual.At(i, j).AlmostEqualRelative(expected.At(i, j), decimalPlaces))
{
Assert.Fail("Not equal within {0} relative places. Expected:{1}; Actual:{2}", decimalPlaces, expected.At(i, j), actual.At(i, j));
}
}
}
}
public static void AlmostEqualRelative(Matrix<Complex> expected, Matrix<Complex> actual, int decimalPlaces)
{
if (expected.ColumnCount != actual.ColumnCount || expected.RowCount != actual.RowCount)
{
Assert.Fail("Matrix dimensions mismatch. Expected: {0}; Actual: {1}", expected.ToTypeString(), actual.ToTypeString());
}
for (var i = 0; i < expected.RowCount; i++)
{
for (var j = 0; j < expected.ColumnCount; j++)
{
if (!actual.At(i, j).AlmostEqualRelative(expected.At(i, j), decimalPlaces))
{
Assert.Fail("Not equal within {0} relative places. Expected:{1}; Actual:{2}", decimalPlaces, expected.At(i, j), actual.At(i, j));
}
}
}
}
public static void AlmostEqualRelative(Matrix<Complex32> expected, Matrix<Complex32> actual, int decimalPlaces)
{
if (expected.ColumnCount != actual.ColumnCount || expected.RowCount != actual.RowCount)
{
Assert.Fail("Matrix dimensions mismatch. Expected: {0}; Actual: {1}", expected.ToTypeString(), actual.ToTypeString());
}
for (var i = 0; i < expected.RowCount; i++)
{
for (var j = 0; j < expected.ColumnCount; j++)
{
if (!actual.At(i, j).AlmostEqualRelative(expected.At(i, j), decimalPlaces))
{
Assert.Fail("Not equal within {0} relative places. Expected:{1}; Actual:{2}", decimalPlaces, expected.At(i, j), actual.At(i, j));
}
}
}
}
} }
} }

374
src/UnitTests/LinearAlgebraTests/Complex/Factorization/EvdTests.cs

@ -3,7 +3,9 @@
// http://numerics.mathdotnet.com // http://numerics.mathdotnet.com
// http://github.com/mathnet/mathnet-numerics // http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com // http://mathnetnumerics.codeplex.com
// Copyright (c) 2009-2010 Math.NET //
// Copyright (c) 2009-2014 Math.NET
//
// Permission is hereby granted, free of charge, to any person // Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation // obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without // files (the "Software"), to deal in the Software without
@ -12,8 +14,10 @@
// copies of the Software, and to permit persons to whom the // copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following // Software is furnished to do so, subject to the following
// conditions: // conditions:
//
// The above copyright notice and this permission notice shall be // The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software. // included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
@ -42,26 +46,19 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex.Factorization
[TestFixture, Category("LAFactorization")] [TestFixture, Category("LAFactorization")]
public class EvdTests public class EvdTests
{ {
/// <summary> [Test]
/// Can factorize identity matrix. public void CanFactorizeIdentityMatrix([Values(1, 10, 100)] int order)
/// </summary>
/// <param name="order">Matrix order.</param>
[TestCase(1)]
[TestCase(10)]
[TestCase(100)]
public void CanFactorizeIdentity(int order)
{ {
var matrixI = DenseMatrix.CreateIdentity(order); var matrix = Matrix<Complex>.Build.DenseIdentity(order);
var factorEvd = matrixI.Evd(); var factorEvd = matrix.Evd();
var eigenValues = factorEvd.EigenValues; var eigenValues = factorEvd.EigenValues;
var eigenVectors = factorEvd.EigenVectors; var eigenVectors = factorEvd.EigenVectors;
var d = factorEvd.D; var d = factorEvd.D;
Assert.AreEqual(matrixI.RowCount, eigenVectors.RowCount); Assert.AreEqual(matrix.RowCount, eigenVectors.RowCount);
Assert.AreEqual(matrixI.RowCount, eigenVectors.ColumnCount); Assert.AreEqual(matrix.RowCount, eigenVectors.ColumnCount);
Assert.AreEqual(matrix.ColumnCount, d.RowCount);
Assert.AreEqual(matrixI.ColumnCount, d.RowCount); Assert.AreEqual(matrix.ColumnCount, d.ColumnCount);
Assert.AreEqual(matrixI.ColumnCount, d.ColumnCount);
for (var i = 0; i < eigenValues.Count; i++) for (var i = 0; i < eigenValues.Count; i++)
{ {
@ -69,126 +66,75 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex.Factorization
} }
} }
/// <summary> [Test]
/// Can factorize a random square matrix. public void CanFactorizeRandomSquareMatrix([Values(1, 2, 5, 10, 50, 100)] int order)
/// </summary>
/// <param name="order">Matrix order.</param>
[TestCase(1)]
[TestCase(2)]
[TestCase(5)]
[TestCase(10)]
[TestCase(50)]
[TestCase(100)]
public void CanFactorizeRandomMatrix(int order)
{ {
var matrixA = Matrix<Complex>.Build.Random(order, order, 1); var A = Matrix<Complex>.Build.Random(order, order, 1);
var factorEvd = matrixA.Evd(); var factorEvd = A.Evd();
var eigenVectors = factorEvd.EigenVectors; var V = factorEvd.EigenVectors;
var λ = factorEvd.D;
Assert.AreEqual(order, eigenVectors.RowCount);
Assert.AreEqual(order, eigenVectors.ColumnCount); Assert.AreEqual(order, V.RowCount);
Assert.AreEqual(order, V.ColumnCount);
Assert.AreEqual(order, factorEvd.D.RowCount); Assert.AreEqual(order, λ.RowCount);
Assert.AreEqual(order, factorEvd.D.ColumnCount); Assert.AreEqual(order, λ.ColumnCount);
// Make sure the A*V = λ*V // Verify A*V = λ*V
var matrixAv = matrixA * eigenVectors; var Av = A * V;
var matrixLv = eigenVectors * factorEvd.D; var Lv = V * λ;
AssertHelpers.AlmostEqual(Av, Lv, 10);
for (var i = 0; i < matrixAv.RowCount; i++) AssertHelpers.AlmostEqualRelative(Av, Lv, 8);
{
for (var j = 0; j < matrixAv.ColumnCount; j++)
{
AssertHelpers.AlmostEqualRelative(matrixAv[i, j], matrixLv[i, j], 7);
}
}
} }
/// <summary>
/// Can factorize a symmetric random square matrix.
/// </summary> <param name="order">Matrix order.</param>
[Test] [Test]
[TestCase(1)] public void CanFactorizeRandomSymmetricMatrix([Values(1, 2, 5, 10, 50, 100)] int order)
[TestCase(2)]
[TestCase(5)]
[TestCase(10)]
[TestCase(50)]
[TestCase(100)]
public void CanFactorizeRandomSymmetricMatrix(int order)
{ {
var matrixA = Matrix<Complex>.Build.RandomPositiveDefinite(order, 1); var A = Matrix<Complex>.Build.RandomPositiveDefinite(order, 1);
MatrixHelpers.ForceConjugateSymmetric(matrixA); MatrixHelpers.ForceConjugateSymmetric(A);
var factorEvd = matrixA.Evd(); var factorEvd = A.Evd();
var eigenVectors = factorEvd.EigenVectors; var V = factorEvd.EigenVectors;
var d = factorEvd.D; var λ = factorEvd.D;
Assert.AreEqual(order, eigenVectors.RowCount); Assert.AreEqual(order, V.RowCount);
Assert.AreEqual(order, eigenVectors.ColumnCount); Assert.AreEqual(order, V.ColumnCount);
Assert.AreEqual(order, λ.RowCount);
Assert.AreEqual(order, d.RowCount); Assert.AreEqual(order, λ.ColumnCount);
Assert.AreEqual(order, d.ColumnCount);
// Verify A = V*λ*VT
// Make sure the A = V*λ*VT var matrix = V*λ*V.ConjugateTranspose();
var matrix = eigenVectors * d * eigenVectors.ConjugateTranspose(); AssertHelpers.AlmostEqual(matrix, A, 10);
AssertHelpers.AlmostEqualRelative(matrix, A, 10);
for (var i = 0; i < matrix.RowCount; i++)
{
for (var j = 0; j < matrix.ColumnCount; j++)
{
AssertHelpers.AlmostEqualRelative(matrix[i, j], matrixA[i, j], 7);
}
}
} }
/// <summary> [Test]
/// Can check rank of square matrix. public void CanCheckRankSquare([Values(10, 50, 100)] int order)
/// </summary>
/// <param name="order">Matrix order.</param>
[TestCase(10)]
[TestCase(50)]
[TestCase(100)]
public void CanCheckRankSquare(int order)
{ {
var matrixA = Matrix<Complex>.Build.Random(order, order, 1); var A = Matrix<Complex>.Build.Random(order, order, 1);
var factorEvd = matrixA.Evd(); Assert.AreEqual(A.Evd().Rank, order);
Assert.AreEqual(factorEvd.Rank, order);
} }
/// <summary> [Test]
/// Can check rank of square singular matrix. public void CanCheckRankOfSquareSingular([Values(10, 50, 100)] int order)
/// </summary>
/// <param name="order">Matrix order.</param>
[TestCase(10)]
[TestCase(50)]
[TestCase(100)]
public void CanCheckRankOfSquareSingular(int order)
{ {
var matrixA = new DenseMatrix(order, order); var A = new DenseMatrix(order, order);
matrixA[0, 0] = 1; A[0, 0] = 1;
matrixA[order - 1, order - 1] = 1; A[order - 1, order - 1] = 1;
for (var i = 1; i < order - 1; i++) for (var i = 1; i < order - 1; i++)
{ {
matrixA[i, i - 1] = 1; A[i, i - 1] = 1;
matrixA[i, i + 1] = 1; A[i, i + 1] = 1;
matrixA[i - 1, i] = 1; A[i - 1, i] = 1;
matrixA[i + 1, i] = 1; A[i + 1, i] = 1;
} }
var factorEvd = matrixA.Evd(); var factorEvd = A.Evd();
Assert.AreEqual(factorEvd.Determinant, Complex.Zero); Assert.AreEqual(factorEvd.Determinant, Complex.Zero);
Assert.AreEqual(factorEvd.Rank, order - 1); Assert.AreEqual(factorEvd.Rank, order - 1);
} }
/// <summary> [Test]
/// Identity determinant is one. public void IdentityDeterminantIsOne([Values(1, 10, 100)] int order)
/// </summary>
/// <param name="order">Matrix order.</param>
[TestCase(1)]
[TestCase(10)]
[TestCase(100)]
public void IdentityDeterminantIsOne(int order)
{ {
var matrixI = DenseMatrix.CreateIdentity(order); var matrixI = DenseMatrix.CreateIdentity(order);
var factorEvd = matrixI.Evd(); var factorEvd = matrixI.Evd();
@ -200,40 +146,26 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex.Factorization
/// </summary> /// </summary>
/// <param name="order">Matrix order.</param> /// <param name="order">Matrix order.</param>
[Test] [Test]
[TestCase(1)] public void CanSolveForRandomVectorAndSymmetricMatrix([Values(1, 2, 5, 10, 50, 100)] int order)
[TestCase(2)]
[TestCase(5)]
[TestCase(10)]
[TestCase(50)]
[TestCase(100)]
public void CanSolveForRandomVectorAndSymmetricMatrix(int order)
{ {
var matrixA = Matrix<Complex>.Build.RandomPositiveDefinite(order, 1); var A = Matrix<Complex>.Build.RandomPositiveDefinite(order, 1);
MatrixHelpers.ForceConjugateSymmetric(matrixA); MatrixHelpers.ForceConjugateSymmetric(A);
var matrixACopy = matrixA.Clone(); var ACopy = A.Clone();
var factorEvd = matrixA.Evd(); var evd = A.Evd();
var vectorb = Vector<Complex>.Build.Random(order, 1); var b = Vector<Complex>.Build.Random(order, 2);
var resultx = factorEvd.Solve(vectorb); var bCopy = b.Clone();
Assert.AreEqual(matrixA.ColumnCount, resultx.Count); var x = evd.Solve(b);
var matrixBReconstruct = matrixA * resultx; var bReconstruct = A * x;
// Check the reconstruction. // Check the reconstruction.
for (var i = 0; i < vectorb.Count; i++) AssertHelpers.ListAlmostEqual(b, bReconstruct, 9);
{
AssertHelpers.AlmostEqual(vectorb[i], matrixBReconstruct[i], 10);
}
// Make sure A didn't change. // Make sure A/B didn't change.
for (var i = 0; i < matrixA.RowCount; i++) AssertHelpers.AlmostEqual(ACopy, A, 14);
{ AssertHelpers.ListAlmostEqual(bCopy, b, 14);
for (var j = 0; j < matrixA.ColumnCount; j++)
{
Assert.AreEqual(matrixACopy[i, j], matrixA[i, j]);
}
}
} }
/// <summary> /// <summary>
@ -241,47 +173,33 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex.Factorization
/// </summary> /// </summary>
/// <param name="order">Matrix order.</param> /// <param name="order">Matrix order.</param>
[Test] [Test]
[TestCase(1)] public void CanSolveForRandomMatrixAndSymmetricMatrix([Values(1, 2, 5, 10, 50, 100)] int order)
[TestCase(2)]
[TestCase(5)]
[TestCase(10)]
[TestCase(50)]
[TestCase(100)]
public void CanSolveForRandomMatrixAndSymmetricMatrix(int order)
{ {
var matrixA = Matrix<Complex>.Build.RandomPositiveDefinite(order, 1);
MatrixHelpers.ForceConjugateSymmetric(matrixA);
var matrixACopy = matrixA.Clone();
var factorEvd = matrixA.Evd();
var matrixB = Matrix<Complex>.Build.Random(order, order, 1); var A = Matrix<Complex>.Build.RandomPositiveDefinite(order, 1);
var matrixX = factorEvd.Solve(matrixB); MatrixHelpers.ForceConjugateSymmetric(A);
var ACopy = A.Clone();
var evd = A.Evd();
var B = Matrix<Complex>.Build.Random(order, order, 2);
var BCopy = B.Clone();
var X = evd.Solve(B);
// The solution X row dimension is equal to the column dimension of A // The solution X row dimension is equal to the column dimension of A
Assert.AreEqual(matrixA.ColumnCount, matrixX.RowCount); Assert.AreEqual(A.ColumnCount, X.RowCount);
// The solution X has the same number of columns as B // The solution X has the same number of columns as B
Assert.AreEqual(matrixB.ColumnCount, matrixX.ColumnCount); Assert.AreEqual(B.ColumnCount, X.ColumnCount);
var matrixBReconstruct = matrixA * matrixX; var BReconstruct = A * X;
// Check the reconstruction. // Check the reconstruction.
for (var i = 0; i < matrixB.RowCount; i++) AssertHelpers.AlmostEqual(B, BReconstruct, 9);
{
for (var j = 0; j < matrixB.ColumnCount; j++)
{
AssertHelpers.AlmostEqual(matrixB[i, j], matrixBReconstruct[i, j], 10);
}
}
// Make sure A didn't change. // Make sure A/B didn't change.
for (var i = 0; i < matrixA.RowCount; i++) AssertHelpers.AlmostEqual(ACopy, A, 14);
{ AssertHelpers.AlmostEqual(BCopy, B, 14);
for (var j = 0; j < matrixA.ColumnCount; j++)
{
Assert.AreEqual(matrixACopy[i, j], matrixA[i, j]);
}
}
} }
/// <summary> /// <summary>
@ -289,45 +207,27 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex.Factorization
/// </summary> /// </summary>
/// <param name="order">Matrix order.</param> /// <param name="order">Matrix order.</param>
[Test] [Test]
[TestCase(1)] public void CanSolveForRandomVectorAndSymmetricMatrixWhenResultVectorGiven([Values(1, 2, 5, 10, 50, 100)] int order)
[TestCase(2)]
[TestCase(5)]
[TestCase(10)]
[TestCase(50)]
[TestCase(100)]
public void CanSolveForRandomVectorAndSymmetricMatrixWhenResultVectorGiven(int order)
{ {
var matrixA = Matrix<Complex>.Build.RandomPositiveDefinite(order, 1); var A = Matrix<Complex>.Build.RandomPositiveDefinite(order, 1);
MatrixHelpers.ForceConjugateSymmetric(matrixA); MatrixHelpers.ForceConjugateSymmetric(A);
var matrixACopy = matrixA.Clone(); var ACopy = A.Clone();
var factorEvd = matrixA.Evd(); var evd = A.Evd();
var vectorb = Vector<Complex>.Build.Random(order, 1);
var vectorbCopy = vectorb.Clone();
var resultx = new DenseVector(order);
factorEvd.Solve(vectorb, resultx);
var matrixBReconstruct = matrixA * resultx; var b = Vector<Complex>.Build.Random(order, 2);
var bCopy = b.Clone();
// Check the reconstruction. var x = new DenseVector(order);
for (var i = 0; i < vectorb.Count; i++) evd.Solve(b, x);
{
AssertHelpers.AlmostEqual(vectorb[i], matrixBReconstruct[i], 10);
}
// Make sure A didn't change. var bReconstruct = A * x;
for (var i = 0; i < matrixA.RowCount; i++)
{
for (var j = 0; j < matrixA.ColumnCount; j++)
{
Assert.AreEqual(matrixACopy[i, j], matrixA[i, j]);
}
}
// Make sure b didn't change. // Check the reconstruction.
for (var i = 0; i < vectorb.Count; i++) AssertHelpers.ListAlmostEqual(b, bReconstruct, 9);
{
Assert.AreEqual(vectorbCopy[i], vectorb[i]); // Make sure A/B didn't change.
} AssertHelpers.AlmostEqual(ACopy, A, 14);
AssertHelpers.ListAlmostEqual(bCopy, b, 14);
} }
/// <summary> /// <summary>
@ -335,59 +235,33 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex.Factorization
/// </summary> /// </summary>
/// <param name="order">Matrix order.</param> /// <param name="order">Matrix order.</param>
[Test] [Test]
[TestCase(1)] public void CanSolveForRandomMatrixAndSymmetricMatrixWhenResultMatrixGiven([Values(1, 2, 5, 10, 50, 100)] int order)
[TestCase(2)]
[TestCase(5)]
[TestCase(10)]
[TestCase(50)]
[TestCase(100)]
public void CanSolveForRandomMatrixAndSymmetricMatrixWhenResultMatrixGiven(int order)
{ {
var matrixA = Matrix<Complex>.Build.RandomPositiveDefinite(order, 1); var A = Matrix<Complex>.Build.RandomPositiveDefinite(order, 1);
MatrixHelpers.ForceConjugateSymmetric(matrixA); MatrixHelpers.ForceConjugateSymmetric(A);
var matrixACopy = matrixA.Clone(); var ACopy = A.Clone();
var factorEvd = matrixA.Evd(); var evd = A.Evd();
var matrixB = Matrix<Complex>.Build.Random(order, order, 1); var B = Matrix<Complex>.Build.Random(order, order, 2);
var matrixBCopy = matrixB.Clone(); var BCopy = B.Clone();
var matrixX = new DenseMatrix(order, order); var X = new DenseMatrix(order, order);
factorEvd.Solve(matrixB, matrixX); evd.Solve(B, X);
// The solution X row dimension is equal to the column dimension of A // The solution X row dimension is equal to the column dimension of A
Assert.AreEqual(matrixA.ColumnCount, matrixX.RowCount); Assert.AreEqual(A.ColumnCount, X.RowCount);
// The solution X has the same number of columns as B // The solution X has the same number of columns as B
Assert.AreEqual(matrixB.ColumnCount, matrixX.ColumnCount); Assert.AreEqual(B.ColumnCount, X.ColumnCount);
var matrixBReconstruct = matrixA * matrixX; var BReconstruct = A * X;
// Check the reconstruction. // Check the reconstruction.
for (var i = 0; i < matrixB.RowCount; i++) AssertHelpers.AlmostEqual(B, BReconstruct, 9);
{
for (var j = 0; j < matrixB.ColumnCount; j++)
{
AssertHelpers.AlmostEqual(matrixB[i, j], matrixBReconstruct[i, j], 10);
}
}
// 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]);
}
}
// Make sure B didn't change. // Make sure A/B didn't change.
for (var i = 0; i < matrixB.RowCount; i++) AssertHelpers.AlmostEqual(ACopy, A, 14);
{ AssertHelpers.AlmostEqual(BCopy, B, 14);
for (var j = 0; j < matrixB.ColumnCount; j++)
{
Assert.AreEqual(matrixBCopy[i, j], matrixB[i, j]);
}
}
} }
} }
} }

195
src/UnitTests/LinearAlgebraTests/Complex/Factorization/UserEvdTests.cs

@ -198,187 +198,122 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex.Factorization
/// Can solve a system of linear equations for a random vector and symmetric matrix (Ax=b). /// Can solve a system of linear equations for a random vector and symmetric matrix (Ax=b).
/// </summary> /// </summary>
/// <param name="order">Matrix order.</param> /// <param name="order">Matrix order.</param>
[TestCase(1)] [Test]
[TestCase(2)] public void CanSolveForRandomVectorAndSymmetricMatrix([Values(1, 2, 5, 10, 50, 100)] int order)
[TestCase(5)]
[TestCase(10)]
[TestCase(50)]
[TestCase(100)]
public void CanSolveForRandomVectorAndSymmetricMatrix(int order)
{ {
var matrixA = new UserDefinedMatrix(Matrix<Complex>.Build.RandomPositiveDefinite(order, 1).ToArray()); var A = new UserDefinedMatrix(Matrix<Complex>.Build.RandomPositiveDefinite(order, 1).ToArray());
var matrixACopy = matrixA.Clone(); MatrixHelpers.ForceConjugateSymmetric(A);
var factorEvd = matrixA.Evd(); var ACopy = A.Clone();
var evd = A.Evd();
var vectorb = new UserDefinedVector(Vector<Complex>.Build.Random(order, 1).ToArray()); var b = new UserDefinedVector(Vector<Complex>.Build.Random(order, 1).ToArray());
var resultx = factorEvd.Solve(vectorb); var bCopy = b.Clone();
Assert.AreEqual(matrixA.ColumnCount, resultx.Count); var x = evd.Solve(b);
var matrixBReconstruct = matrixA * resultx; var bReconstruct = A * x;
// Check the reconstruction. // Check the reconstruction.
for (var i = 0; i < vectorb.Count; i++) AssertHelpers.AlmostEqual(b, bReconstruct, 9);
{
AssertHelpers.AlmostEqual(vectorb[i], matrixBReconstruct[i], 10);
}
// Make sure A didn't change. // Make sure A/B didn't change.
for (var i = 0; i < matrixA.RowCount; i++) AssertHelpers.AlmostEqual(ACopy, A, 14);
{ AssertHelpers.AlmostEqual(bCopy, b, 14);
for (var j = 0; j < matrixA.ColumnCount; j++)
{
Assert.AreEqual(matrixACopy[i, j], matrixA[i, j]);
}
}
} }
/// <summary> /// <summary>
/// Can solve a system of linear equations for a random matrix and symmetric matrix (AX=B). /// Can solve a system of linear equations for a random matrix and symmetric matrix (AX=B).
/// </summary> /// </summary>
/// <param name="order">Matrix order.</param> /// <param name="order">Matrix order.</param>
[TestCase(1)] [Test]
[TestCase(2)] public void CanSolveForRandomMatrixAndSymmetricMatrix([Values(1, 2, 5, 10, 50, 100)] int order)
[TestCase(5)]
[TestCase(10)]
[TestCase(50)]
[TestCase(100)]
public void CanSolveForRandomMatrixAndSymmetricMatrix(int order)
{ {
var matrixA = new UserDefinedMatrix(Matrix<Complex>.Build.RandomPositiveDefinite(order, 1).ToArray()); var A = new UserDefinedMatrix(Matrix<Complex>.Build.RandomPositiveDefinite(order, 1).ToArray());
var matrixACopy = matrixA.Clone(); MatrixHelpers.ForceConjugateSymmetric(A);
var factorEvd = matrixA.Evd(); var ACopy = A.Clone();
var evd = A.Evd();
var B = new UserDefinedMatrix(Matrix<Complex>.Build.Random(order, order, 1).ToArray());
var BCopy = B.Clone();
var matrixB = new UserDefinedMatrix(Matrix<Complex>.Build.Random(order, order, 1).ToArray()); var X = evd.Solve(B);
var matrixX = factorEvd.Solve(matrixB);
// The solution X row dimension is equal to the column dimension of A // The solution X row dimension is equal to the column dimension of A
Assert.AreEqual(matrixA.ColumnCount, matrixX.RowCount); Assert.AreEqual(A.ColumnCount, X.RowCount);
// The solution X has the same number of columns as B // The solution X has the same number of columns as B
Assert.AreEqual(matrixB.ColumnCount, matrixX.ColumnCount); Assert.AreEqual(B.ColumnCount, X.ColumnCount);
var matrixBReconstruct = matrixA * matrixX; var BReconstruct = A * X;
// Check the reconstruction. // Check the reconstruction.
for (var i = 0; i < matrixB.RowCount; i++) AssertHelpers.AlmostEqual(B, BReconstruct, 9);
{
for (var j = 0; j < matrixB.ColumnCount; j++)
{
AssertHelpers.AlmostEqual(matrixB[i, j], matrixBReconstruct[i, j], 10);
}
}
// Make sure A didn't change. // Make sure A/B didn't change.
for (var i = 0; i < matrixA.RowCount; i++) AssertHelpers.AlmostEqual(ACopy, A, 14);
{ AssertHelpers.AlmostEqual(BCopy, B, 14);
for (var j = 0; j < matrixA.ColumnCount; j++)
{
Assert.AreEqual(matrixACopy[i, j], matrixA[i, j]);
}
}
} }
/// <summary> /// <summary>
/// Can solve a system of linear equations for a random vector and symmetric matrix (Ax=b) into a result matrix. /// Can solve a system of linear equations for a random vector and symmetric matrix (Ax=b) into a result matrix.
/// </summary> /// </summary>
/// <param name="order">Matrix order.</param> /// <param name="order">Matrix order.</param>
[TestCase(1)] [Test]
[TestCase(2)] public void CanSolveForRandomVectorAndSymmetricMatrixWhenResultVectorGiven([Values(1, 2, 5, 10, 50, 100)] int order)
[TestCase(5)]
[TestCase(10)]
[TestCase(50)]
[TestCase(100)]
public void CanSolveForRandomVectorAndSymmetricMatrixWhenResultVectorGiven(int order)
{ {
var matrixA = new UserDefinedMatrix(Matrix<Complex>.Build.RandomPositiveDefinite(order, 1).ToArray()); var A = new UserDefinedMatrix(Matrix<Complex>.Build.RandomPositiveDefinite(order, 1).ToArray());
var matrixACopy = matrixA.Clone(); MatrixHelpers.ForceConjugateSymmetric(A);
var factorEvd = matrixA.Evd(); var ACopy = A.Clone();
var vectorb = new UserDefinedVector(Vector<Complex>.Build.Random(order, 1).ToArray()); var evd = A.Evd();
var vectorbCopy = vectorb.Clone();
var resultx = new UserDefinedVector(order);
factorEvd.Solve(vectorb, resultx);
var matrixBReconstruct = matrixA * resultx; var b = new UserDefinedVector(Vector<Complex>.Build.Random(order, 1).ToArray());
var bCopy = b.Clone();
// Check the reconstruction. var x = new UserDefinedVector(order);
for (var i = 0; i < vectorb.Count; i++) evd.Solve(b, x);
{
AssertHelpers.AlmostEqual(vectorb[i], matrixBReconstruct[i], 10);
}
// Make sure A didn't change. var bReconstruct = A * x;
for (var i = 0; i < matrixA.RowCount; i++)
{
for (var j = 0; j < matrixA.ColumnCount; j++)
{
Assert.AreEqual(matrixACopy[i, j], matrixA[i, j]);
}
}
// Make sure b didn't change. // Check the reconstruction.
for (var i = 0; i < vectorb.Count; i++) AssertHelpers.AlmostEqual(b, bReconstruct, 9);
{
Assert.AreEqual(vectorbCopy[i], vectorb[i]); // Make sure A/B didn't change.
} AssertHelpers.AlmostEqual(ACopy, A, 14);
AssertHelpers.AlmostEqual(bCopy, b, 14);
} }
/// <summary> /// <summary>
/// Can solve a system of linear equations for a random matrix and symmetric matrix (AX=B) into result matrix. /// Can solve a system of linear equations for a random matrix and symmetric matrix (AX=B) into result matrix.
/// </summary> /// </summary>
/// <param name="order">Matrix order.</param> /// <param name="order">Matrix order.</param>
[TestCase(1)] [Test]
[TestCase(2)] public void CanSolveForRandomMatrixAndSymmetricMatrixWhenResultMatrixGiven([Values(1, 2, 5, 10, 50, 100)] int order)
[TestCase(5)]
[TestCase(10)]
[TestCase(50)]
[TestCase(100)]
public void CanSolveForRandomMatrixAndSymmetricMatrixWhenResultMatrixGiven(int order)
{ {
var matrixA = new UserDefinedMatrix(Matrix<Complex>.Build.RandomPositiveDefinite(order, 1).ToArray()); var A = new UserDefinedMatrix(Matrix<Complex>.Build.RandomPositiveDefinite(order, 1).ToArray());
var matrixACopy = matrixA.Clone(); MatrixHelpers.ForceConjugateSymmetric(A);
var factorEvd = matrixA.Evd(); var ACopy = A.Clone();
var evd = A.Evd();
var matrixB = new UserDefinedMatrix(Matrix<Complex>.Build.Random(order, order, 1).ToArray()); var B = new UserDefinedMatrix(Matrix<Complex>.Build.Random(order, order, 1).ToArray());
var matrixBCopy = matrixB.Clone(); var BCopy = B.Clone();
var matrixX = new UserDefinedMatrix(order, order); var X = new UserDefinedMatrix(order, order);
factorEvd.Solve(matrixB, matrixX); evd.Solve(B, X);
// The solution X row dimension is equal to the column dimension of A // The solution X row dimension is equal to the column dimension of A
Assert.AreEqual(matrixA.ColumnCount, matrixX.RowCount); Assert.AreEqual(A.ColumnCount, X.RowCount);
// The solution X has the same number of columns as B // The solution X has the same number of columns as B
Assert.AreEqual(matrixB.ColumnCount, matrixX.ColumnCount); Assert.AreEqual(B.ColumnCount, X.ColumnCount);
var matrixBReconstruct = matrixA * matrixX; var BReconstruct = A * X;
// Check the reconstruction. // Check the reconstruction.
for (var i = 0; i < matrixB.RowCount; i++) AssertHelpers.AlmostEqual(B, BReconstruct, 9);
{
for (var j = 0; j < matrixB.ColumnCount; j++)
{
AssertHelpers.AlmostEqual(matrixB[i, j], matrixBReconstruct[i, j], 10);
}
}
// Make sure A didn't change. // Make sure A/B didn't change.
for (var i = 0; i < matrixA.RowCount; i++) AssertHelpers.AlmostEqual(ACopy, A, 14);
{ AssertHelpers.AlmostEqual(BCopy, B, 14);
for (var j = 0; j < matrixA.ColumnCount; j++)
{
Assert.AreEqual(matrixACopy[i, j], matrixA[i, j]);
}
}
// Make sure B didn't change.
for (var i = 0; i < matrixB.RowCount; i++)
{
for (var j = 0; j < matrixB.ColumnCount; j++)
{
Assert.AreEqual(matrixBCopy[i, j], matrixB[i, j]);
}
}
} }
} }
} }

371
src/UnitTests/LinearAlgebraTests/Complex32/Factorization/EvdTests.cs

@ -3,7 +3,9 @@
// http://numerics.mathdotnet.com // http://numerics.mathdotnet.com
// http://github.com/mathnet/mathnet-numerics // http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com // http://mathnetnumerics.codeplex.com
// Copyright (c) 2009-2010 Math.NET //
// Copyright (c) 2009-2014 Math.NET
//
// Permission is hereby granted, free of charge, to any person // Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation // obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without // files (the "Software"), to deal in the Software without
@ -12,8 +14,10 @@
// copies of the Software, and to permit persons to whom the // copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following // Software is furnished to do so, subject to the following
// conditions: // conditions:
//
// The above copyright notice and this permission notice shall be // The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software. // included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
@ -44,149 +48,94 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex32.Factorization
[TestFixture, Category("LAFactorization")] [TestFixture, Category("LAFactorization")]
public class EvdTests public class EvdTests
{ {
/// <summary> [Test]
/// Can factorize identity matrix. public void CanFactorizeIdentityMatrix([Values(1, 10, 100)] int order)
/// </summary>
/// <param name="order">Matrix order.</param>
[TestCase(1)]
[TestCase(10)]
[TestCase(100)]
public void CanFactorizeIdentity(int order)
{ {
var matrixI = DenseMatrix.CreateIdentity(order); var matrix = Matrix<Complex32>.Build.DenseIdentity(order);
var factorEvd = matrixI.Evd(); var factorEvd = matrix.Evd();
var eigenValues = factorEvd.EigenValues; var eigenValues = factorEvd.EigenValues;
var eigenVectors = factorEvd.EigenVectors; var eigenVectors = factorEvd.EigenVectors;
var d = factorEvd.D; var d = factorEvd.D;
Assert.AreEqual(matrixI.RowCount, eigenVectors.RowCount); Assert.AreEqual(matrix.RowCount, eigenVectors.RowCount);
Assert.AreEqual(matrixI.RowCount, eigenVectors.ColumnCount); Assert.AreEqual(matrix.RowCount, eigenVectors.ColumnCount);
Assert.AreEqual(matrix.ColumnCount, d.RowCount);
Assert.AreEqual(matrixI.ColumnCount, d.RowCount); Assert.AreEqual(matrix.ColumnCount, d.ColumnCount);
Assert.AreEqual(matrixI.ColumnCount, d.ColumnCount);
for (var i = 0; i < factorEvd.EigenValues.Count; i++) for (var i = 0; i < eigenValues.Count; i++)
{ {
Assert.AreEqual(Complex.One, eigenValues[i]); Assert.AreEqual(Complex.One, eigenValues[i]);
} }
} }
/// <summary> [Test]
/// Can factorize a random square matrix. public void CanFactorizeRandomSquareMatrix([Values(1, 2, 5, 10, 50, 100)] int order)
/// </summary>
/// <param name="order">Matrix order.</param>
[TestCase(1)]
[TestCase(2)]
[TestCase(5)]
[TestCase(10)]
[TestCase(50)]
[TestCase(100)]
public void CanFactorizeRandomMatrix(int order)
{ {
var matrixA = Matrix<Complex32>.Build.Random(order, order, 1); var A = Matrix<Complex32>.Build.Random(order, order, 1);
var factorEvd = matrixA.Evd(); var factorEvd = A.Evd();
var eigenVectors = factorEvd.EigenVectors; var V = factorEvd.EigenVectors;
var d = factorEvd.D; var λ = factorEvd.D;
Assert.AreEqual(order, eigenVectors.RowCount); Assert.AreEqual(order, V.RowCount);
Assert.AreEqual(order, eigenVectors.ColumnCount); Assert.AreEqual(order, V.ColumnCount);
Assert.AreEqual(order, λ.RowCount);
Assert.AreEqual(order, d.RowCount); Assert.AreEqual(order, λ.ColumnCount);
Assert.AreEqual(order, d.ColumnCount);
// Verify A*V = λ*V
// Make sure the A*V = λ*V var Av = A * V;
var matrixAv = matrixA * eigenVectors; var Lv = V * λ;
var matrixLv = eigenVectors * factorEvd.D; AssertHelpers.AlmostEqual(Av, Lv, 4);
for (var i = 0; i < matrixAv.RowCount; i++)
{
for (var j = 0; j < matrixAv.ColumnCount; j++)
{
Assert.AreEqual(matrixAv[i, j].Real, matrixLv[i, j].Real, 1e-3f);
Assert.AreEqual(matrixAv[i, j].Imaginary, matrixLv[i, j].Imaginary, 1e-3f);
}
}
} }
/// <summary>
/// Can factorize a symmetric random square matrix.
/// </summary> <param name="order">Matrix order.</param>
[Test] [Test]
public void CanFactorizeRandomSymmetricMatrix([Values(1, 2, 5, 10)] int order) public void CanFactorizeRandomSymmetricMatrix([Values(1, 2, 5, 10, 50, 100)] int order)
{ {
var matrixA = Matrix<Complex32>.Build.RandomPositiveDefinite(order, 1); var A = Matrix<Complex32>.Build.RandomPositiveDefinite(order, 1);
MatrixHelpers.ForceConjugateSymmetric(matrixA); MatrixHelpers.ForceConjugateSymmetric(A);
var factorEvd = matrixA.Evd(); var factorEvd = A.Evd();
var eigenVectors = factorEvd.EigenVectors; var V = factorEvd.EigenVectors;
var d = factorEvd.D; var λ = factorEvd.D;
Assert.AreEqual(order, eigenVectors.RowCount); Assert.AreEqual(order, V.RowCount);
Assert.AreEqual(order, eigenVectors.ColumnCount); Assert.AreEqual(order, V.ColumnCount);
Assert.AreEqual(order, λ.RowCount);
Assert.AreEqual(order, d.RowCount); Assert.AreEqual(order, λ.ColumnCount);
Assert.AreEqual(order, d.ColumnCount);
// Verify A = V*λ*VT
// Make sure the A = V*λ*VT var matrix = V*λ*V.ConjugateTranspose();
var matrix = eigenVectors * d * eigenVectors.ConjugateTranspose(); AssertHelpers.AlmostEqual(matrix, A, 3);
AssertHelpers.AlmostEqualRelative(matrix, A, 1);
for (var i = 0; i < matrix.RowCount; i++)
{
for (var j = 0; j < matrix.ColumnCount; j++)
{
AssertHelpers.AlmostEqual(matrix[i, j], matrixA[i, j], 3);
}
}
} }
/// <summary> [Test]
/// Can check rank of square matrix. public void CanCheckRankSquare([Values(10, 50, 100)] int order)
/// </summary>
/// <param name="order">Matrix order.</param>
[TestCase(10)]
[TestCase(50)]
[TestCase(100)]
public void CanCheckRankSquare(int order)
{ {
var matrixA = Matrix<Complex32>.Build.Random(order, order, 1); var A = Matrix<Complex32>.Build.Random(order, order, 1);
var factorEvd = matrixA.Evd(); Assert.AreEqual(A.Evd().Rank, order);
Assert.AreEqual(factorEvd.Rank, order);
} }
/// <summary> [Test]
/// Can check rank of square singular matrix. public void CanCheckRankOfSquareSingular([Values(10, 50, 100)] int order)
/// </summary>
/// <param name="order">Matrix order.</param>
[TestCase(10)]
[TestCase(50)]
[TestCase(100)]
public void CanCheckRankOfSquareSingular(int order)
{ {
var matrixA = new DenseMatrix(order, order); var A = new DenseMatrix(order, order);
matrixA[0, 0] = 1; A[0, 0] = 1;
matrixA[order - 1, order - 1] = 1; A[order - 1, order - 1] = 1;
for (var i = 1; i < order - 1; i++) for (var i = 1; i < order - 1; i++)
{ {
matrixA[i, i - 1] = 1; A[i, i - 1] = 1;
matrixA[i, i + 1] = 1; A[i, i + 1] = 1;
matrixA[i - 1, i] = 1; A[i - 1, i] = 1;
matrixA[i + 1, i] = 1; A[i + 1, i] = 1;
} }
var factorEvd = matrixA.Evd(); var factorEvd = A.Evd();
Assert.AreEqual(factorEvd.Determinant, Complex32.Zero); Assert.AreEqual(factorEvd.Determinant, Complex32.Zero);
Assert.AreEqual(factorEvd.Rank, order - 1); Assert.AreEqual(factorEvd.Rank, order - 1);
} }
/// <summary> [Test]
/// Identity determinant is one. public void IdentityDeterminantIsOne([Values(1, 10, 100)] int order)
/// </summary>
/// <param name="order">Matrix order.</param>
[TestCase(1)]
[TestCase(10)]
[TestCase(100)]
public void IdentityDeterminantIsOne(int order)
{ {
var matrixI = DenseMatrix.CreateIdentity(order); var matrixI = DenseMatrix.CreateIdentity(order);
var factorEvd = matrixI.Evd(); var factorEvd = matrixI.Evd();
@ -198,40 +147,26 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex32.Factorization
/// </summary> /// </summary>
/// <param name="order">Matrix order.</param> /// <param name="order">Matrix order.</param>
[Test] [Test]
[TestCase(1)] public void CanSolveForRandomVectorAndSymmetricMatrix([Values(1, 2, 5, 10, 50, 100)] int order)
[TestCase(2)]
[TestCase(5)]
[TestCase(10)]
[TestCase(50)]
public void CanSolveForRandomVectorAndSymmetricMatrix(int order)
{ {
var matrixA = Matrix<Complex32>.Build.RandomPositiveDefinite(order, 1); var A = Matrix<Complex32>.Build.RandomPositiveDefinite(order, 1);
MatrixHelpers.ForceConjugateSymmetric(matrixA); MatrixHelpers.ForceConjugateSymmetric(A);
var matrixACopy = matrixA.Clone(); var ACopy = A.Clone();
var factorEvd = matrixA.Evd(); var evd = A.Evd();
var vectorb = Vector<Complex32>.Build.Random(order, 1); var b = Vector<Complex32>.Build.Random(order, 2);
var resultx = factorEvd.Solve(vectorb); var bCopy = b.Clone();
Assert.AreEqual(matrixA.ColumnCount, resultx.Count); var x = evd.Solve(b);
var matrixBReconstruct = matrixA * resultx; var bReconstruct = A * x;
// Check the reconstruction. // Check the reconstruction.
for (var i = 0; i < vectorb.Count; i++) AssertHelpers.ListAlmostEqual(b, bReconstruct, 2);
{
Assert.AreEqual(vectorb[i].Real, matrixBReconstruct[i].Real, 1e-2f);
Assert.AreEqual(vectorb[i].Imaginary, matrixBReconstruct[i].Imaginary, 1e-2f);
}
// Make sure A didn't change. // Make sure A/B didn't change.
for (var i = 0; i < matrixA.RowCount; i++) AssertHelpers.AlmostEqual(ACopy, A, 14);
{ AssertHelpers.ListAlmostEqual(bCopy, b, 14);
for (var j = 0; j < matrixA.ColumnCount; j++)
{
Assert.AreEqual(matrixACopy[i, j], matrixA[i, j]);
}
}
} }
/// <summary> /// <summary>
@ -239,47 +174,32 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex32.Factorization
/// </summary> /// </summary>
/// <param name="order">Matrix order.</param> /// <param name="order">Matrix order.</param>
[Test] [Test]
[TestCase(1)] public void CanSolveForRandomMatrixAndSymmetricMatrix([Values(1, 2, 5, 10, 50, 100)] int order)
[TestCase(2)]
[TestCase(5)]
[TestCase(10)]
[TestCase(50)]
public void CanSolveForRandomMatrixAndSymmetricMatrix(int order)
{ {
var matrixA = Matrix<Complex32>.Build.RandomPositiveDefinite(order, 1); var A = Matrix<Complex32>.Build.RandomPositiveDefinite(order, 1);
MatrixHelpers.ForceConjugateSymmetric(matrixA); MatrixHelpers.ForceConjugateSymmetric(A);
var matrixACopy = matrixA.Clone(); var ACopy = A.Clone();
var factorEvd = matrixA.Evd(); var evd = A.Evd();
var B = Matrix<Complex32>.Build.Random(order, order, 2);
var BCopy = B.Clone();
var matrixB = Matrix<Complex32>.Build.Random(order, order, 1); var X = evd.Solve(B);
var matrixX = factorEvd.Solve(matrixB);
// The solution X row dimension is equal to the column dimension of A // The solution X row dimension is equal to the column dimension of A
Assert.AreEqual(matrixA.ColumnCount, matrixX.RowCount); Assert.AreEqual(A.ColumnCount, X.RowCount);
// The solution X has the same number of columns as B // The solution X has the same number of columns as B
Assert.AreEqual(matrixB.ColumnCount, matrixX.ColumnCount); Assert.AreEqual(B.ColumnCount, X.ColumnCount);
var matrixBReconstruct = matrixA * matrixX; var BReconstruct = A * X;
// Check the reconstruction. // Check the reconstruction.
for (var i = 0; i < matrixB.RowCount; i++) AssertHelpers.AlmostEqual(B, BReconstruct, 1);
{
for (var j = 0; j < matrixB.ColumnCount; j++)
{
Assert.AreEqual(matrixB[i, j].Real, matrixBReconstruct[i, j].Real, 1e-2f);
Assert.AreEqual(matrixB[i, j].Imaginary, matrixBReconstruct[i, j].Imaginary, 1e-2f);
}
}
// Make sure A didn't change. // Make sure A/B didn't change.
for (var i = 0; i < matrixA.RowCount; i++) AssertHelpers.AlmostEqual(ACopy, A, 14);
{ AssertHelpers.AlmostEqual(BCopy, B, 14);
for (var j = 0; j < matrixA.ColumnCount; j++)
{
Assert.AreEqual(matrixACopy[i, j], matrixA[i, j]);
}
}
} }
/// <summary> /// <summary>
@ -287,45 +207,27 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex32.Factorization
/// </summary> /// </summary>
/// <param name="order">Matrix order.</param> /// <param name="order">Matrix order.</param>
[Test] [Test]
[TestCase(1)] public void CanSolveForRandomVectorAndSymmetricMatrixWhenResultVectorGiven([Values(1, 2, 5, 10, 50, 100)] int order)
[TestCase(2)]
[TestCase(5)]
[TestCase(10)]
[TestCase(50)]
public void CanSolveForRandomVectorAndSymmetricMatrixWhenResultVectorGiven(int order)
{ {
var matrixA = Matrix<Complex32>.Build.RandomPositiveDefinite(order, 1); var A = Matrix<Complex32>.Build.RandomPositiveDefinite(order, 1);
MatrixHelpers.ForceConjugateSymmetric(matrixA); MatrixHelpers.ForceConjugateSymmetric(A);
var matrixACopy = matrixA.Clone(); var ACopy = A.Clone();
var factorEvd = matrixA.Evd(); var evd = A.Evd();
var vectorb = Vector<Complex32>.Build.Random(order, 1);
var vectorbCopy = vectorb.Clone();
var resultx = new DenseVector(order);
factorEvd.Solve(vectorb, resultx);
var matrixBReconstruct = matrixA * resultx; var b = Vector<Complex32>.Build.Random(order, 2);
var bCopy = b.Clone();
// Check the reconstruction. var x = new DenseVector(order);
for (var i = 0; i < vectorb.Count; i++) evd.Solve(b, x);
{
Assert.AreEqual(vectorb[i].Real, matrixBReconstruct[i].Real, 1e-2f);
Assert.AreEqual(vectorb[i].Imaginary, matrixBReconstruct[i].Imaginary, 1e-2f);
}
// Make sure A didn't change. var bReconstruct = A * x;
for (var i = 0; i < matrixA.RowCount; i++)
{
for (var j = 0; j < matrixA.ColumnCount; j++)
{
Assert.AreEqual(matrixACopy[i, j], matrixA[i, j]);
}
}
// Make sure b didn't change. // Check the reconstruction.
for (var i = 0; i < vectorb.Count; i++) AssertHelpers.ListAlmostEqual(b, bReconstruct, 2);
{
Assert.AreEqual(vectorbCopy[i], vectorb[i]); // Make sure A/B didn't change.
} AssertHelpers.AlmostEqual(ACopy, A, 14);
AssertHelpers.ListAlmostEqual(bCopy, b, 14);
} }
/// <summary> /// <summary>
@ -333,60 +235,33 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex32.Factorization
/// </summary> /// </summary>
/// <param name="order">Matrix order.</param> /// <param name="order">Matrix order.</param>
[Test] [Test]
[TestCase(1)] public void CanSolveForRandomMatrixAndSymmetricMatrixWhenResultMatrixGiven([Values(1, 2, 5, 10, 50, 100)] int order)
[TestCase(2)]
[TestCase(5)]
[TestCase(10)]
[TestCase(50)]
[TestCase(100)]
public void CanSolveForRandomMatrixAndSymmetricMatrixWhenResultMatrixGiven(int order)
{ {
var matrixA = Matrix<Complex32>.Build.RandomPositiveDefinite(order, 1); var A = Matrix<Complex32>.Build.RandomPositiveDefinite(order, 1);
MatrixHelpers.ForceConjugateSymmetric(matrixA); MatrixHelpers.ForceConjugateSymmetric(A);
var matrixACopy = matrixA.Clone(); var ACopy = A.Clone();
var factorEvd = matrixA.Evd(); var evd = A.Evd();
var matrixB = Matrix<Complex32>.Build.Random(order, order, 1); var B = Matrix<Complex32>.Build.Random(order, order, 2);
var matrixBCopy = matrixB.Clone(); var BCopy = B.Clone();
var matrixX = new DenseMatrix(order, order); var X = new DenseMatrix(order, order);
factorEvd.Solve(matrixB, matrixX); evd.Solve(B, X);
// The solution X row dimension is equal to the column dimension of A // The solution X row dimension is equal to the column dimension of A
Assert.AreEqual(matrixA.ColumnCount, matrixX.RowCount); Assert.AreEqual(A.ColumnCount, X.RowCount);
// The solution X has the same number of columns as B // The solution X has the same number of columns as B
Assert.AreEqual(matrixB.ColumnCount, matrixX.ColumnCount); Assert.AreEqual(B.ColumnCount, X.ColumnCount);
var matrixBReconstruct = matrixA * matrixX; var BReconstruct = A * X;
// Check the reconstruction. // Check the reconstruction.
for (var i = 0; i < matrixB.RowCount; i++) AssertHelpers.AlmostEqual(B, BReconstruct, 1);
{
for (var j = 0; j < matrixB.ColumnCount; j++)
{
Assert.AreEqual(matrixB[i, j].Real, matrixBReconstruct[i, j].Real, 1e-1f);
Assert.AreEqual(matrixB[i, j].Imaginary, matrixBReconstruct[i, j].Imaginary, 1e-1f);
}
}
// 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]);
}
}
// Make sure B didn't change. // Make sure A/B didn't change.
for (var i = 0; i < matrixB.RowCount; i++) AssertHelpers.AlmostEqual(ACopy, A, 14);
{ AssertHelpers.AlmostEqual(BCopy, B, 14);
for (var j = 0; j < matrixB.ColumnCount; j++)
{
Assert.AreEqual(matrixBCopy[i, j], matrixB[i, j]);
}
}
} }
} }
} }

185
src/UnitTests/LinearAlgebraTests/Complex32/Factorization/UserEvdTests.cs

@ -197,181 +197,122 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex32.Factorization
/// Can solve a system of linear equations for a random vector and symmetric matrix (Ax=b). /// Can solve a system of linear equations for a random vector and symmetric matrix (Ax=b).
/// </summary> /// </summary>
/// <param name="order">Matrix order.</param> /// <param name="order">Matrix order.</param>
[Test, Ignore] [Test]
public void CanSolveForRandomVectorAndSymmetricMatrix([Values(1, 2, 5, 10, 50, 100)] int order) public void CanSolveForRandomVectorAndSymmetricMatrix([Values(1, 2, 5, 10, 50, 100)] int order)
{ {
var matrixA = new UserDefinedMatrix(Matrix<Complex32>.Build.RandomPositiveDefinite(order, 1).ToArray()); var A = new UserDefinedMatrix(Matrix<Complex32>.Build.RandomPositiveDefinite(order, 1).ToArray());
var matrixACopy = matrixA.Clone(); MatrixHelpers.ForceConjugateSymmetric(A);
var factorEvd = matrixA.Evd(); var ACopy = A.Clone();
var evd = A.Evd();
var vectorb = new UserDefinedVector(Vector<Complex32>.Build.Random(order, 1).ToArray()); var b = new UserDefinedVector(Vector<Complex32>.Build.Random(order, 1).ToArray());
var resultx = factorEvd.Solve(vectorb); var bCopy = b.Clone();
Assert.AreEqual(matrixA.ColumnCount, resultx.Count); var x = evd.Solve(b);
var matrixBReconstruct = matrixA * resultx; var bReconstruct = A * x;
// Check the reconstruction. // Check the reconstruction.
for (var i = 0; i < vectorb.Count; i++) AssertHelpers.AlmostEqual(b, bReconstruct, 2);
{
Assert.AreEqual(vectorb[i].Real, matrixBReconstruct[i].Real, 1e-3f);
Assert.AreEqual(vectorb[i].Imaginary, matrixBReconstruct[i].Imaginary, 1e-3f);
}
// Make sure A didn't change. // Make sure A/B didn't change.
for (var i = 0; i < matrixA.RowCount; i++) AssertHelpers.AlmostEqual(ACopy, A, 14);
{ AssertHelpers.AlmostEqual(bCopy, b, 14);
for (var j = 0; j < matrixA.ColumnCount; j++)
{
Assert.AreEqual(matrixACopy[i, j], matrixA[i, j]);
}
}
} }
/// <summary> /// <summary>
/// Can solve a system of linear equations for a random matrix and symmetric matrix (AX=B). /// Can solve a system of linear equations for a random matrix and symmetric matrix (AX=B).
/// </summary> /// </summary>
/// <param name="order">Matrix order.</param> /// <param name="order">Matrix order.</param>
[TestCase(1)] [Test]
[TestCase(2)] public void CanSolveForRandomMatrixAndSymmetricMatrix([Values(1, 2, 5, 10, 50, 100)] int order)
[TestCase(5)]
[TestCase(10)]
[TestCase(50)]
[TestCase(100)]
public void CanSolveForRandomMatrixAndSymmetricMatrix(int order)
{ {
var matrixA = new UserDefinedMatrix(Matrix<Complex32>.Build.RandomPositiveDefinite(order, 1).ToArray()); var A = new UserDefinedMatrix(Matrix<Complex32>.Build.RandomPositiveDefinite(order, 1).ToArray());
var matrixACopy = matrixA.Clone(); MatrixHelpers.ForceConjugateSymmetric(A);
var factorEvd = matrixA.Evd(); var ACopy = A.Clone();
var evd = A.Evd();
var B = new UserDefinedMatrix(Matrix<Complex32>.Build.Random(order, order, 1).ToArray());
var BCopy = B.Clone();
var matrixB = new UserDefinedMatrix(Matrix<Complex32>.Build.Random(order, order, 1).ToArray()); var X = evd.Solve(B);
var matrixX = factorEvd.Solve(matrixB);
// The solution X row dimension is equal to the column dimension of A // The solution X row dimension is equal to the column dimension of A
Assert.AreEqual(matrixA.ColumnCount, matrixX.RowCount); Assert.AreEqual(A.ColumnCount, X.RowCount);
// The solution X has the same number of columns as B // The solution X has the same number of columns as B
Assert.AreEqual(matrixB.ColumnCount, matrixX.ColumnCount); Assert.AreEqual(B.ColumnCount, X.ColumnCount);
var matrixBReconstruct = matrixA * matrixX; var BReconstruct = A * X;
// Check the reconstruction. // Check the reconstruction.
for (var i = 0; i < matrixB.RowCount; i++) AssertHelpers.AlmostEqual(B, BReconstruct, 1);
{
for (var j = 0; j < matrixB.ColumnCount; j++)
{
Assert.AreEqual(matrixB[i, j].Real, matrixBReconstruct[i, j].Real, 1e-1f);
Assert.AreEqual(matrixB[i, j].Imaginary, matrixBReconstruct[i, j].Imaginary, 1e-1f);
}
}
// Make sure A didn't change. // Make sure A/B didn't change.
for (var i = 0; i < matrixA.RowCount; i++) AssertHelpers.AlmostEqual(ACopy, A, 14);
{ AssertHelpers.AlmostEqual(BCopy, B, 14);
for (var j = 0; j < matrixA.ColumnCount; j++)
{
Assert.AreEqual(matrixACopy[i, j], matrixA[i, j]);
}
}
} }
/// <summary> /// <summary>
/// Can solve a system of linear equations for a random vector and symmetric matrix (Ax=b) into a result matrix. /// Can solve a system of linear equations for a random vector and symmetric matrix (Ax=b) into a result matrix.
/// </summary> /// </summary>
/// <param name="order">Matrix order.</param> /// <param name="order">Matrix order.</param>
[Test, Ignore] [Test]
public void CanSolveForRandomVectorAndSymmetricMatrixWhenResultVectorGiven([Values(1, 2, 5, 10, 50, 100)] int order) public void CanSolveForRandomVectorAndSymmetricMatrixWhenResultVectorGiven([Values(1, 2, 5, 10, 50, 100)] int order)
{ {
var matrixA = new UserDefinedMatrix(Matrix<Complex32>.Build.RandomPositiveDefinite(order, 1).ToArray()); var A = new UserDefinedMatrix(Matrix<Complex32>.Build.RandomPositiveDefinite(order, 1).ToArray());
var matrixACopy = matrixA.Clone(); MatrixHelpers.ForceConjugateSymmetric(A);
var factorEvd = matrixA.Evd(); var ACopy = A.Clone();
var vectorb = new UserDefinedVector(Vector<Complex32>.Build.Random(order, 1).ToArray()); var evd = A.Evd();
var vectorbCopy = vectorb.Clone();
var resultx = new UserDefinedVector(order);
factorEvd.Solve(vectorb, resultx);
var matrixBReconstruct = matrixA * resultx; var b = new UserDefinedVector(Vector<Complex32>.Build.Random(order, 1).ToArray());
var bCopy = b.Clone();
// Check the reconstruction. var x = new UserDefinedVector(order);
for (var i = 0; i < vectorb.Count; i++) evd.Solve(b, x);
{
Assert.AreEqual(vectorb[i].Real, matrixBReconstruct[i].Real, 1e-3f);
Assert.AreEqual(vectorb[i].Imaginary, matrixBReconstruct[i].Imaginary, 1e-3f);
}
// Make sure A didn't change. var bReconstruct = A * x;
for (var i = 0; i < matrixA.RowCount; i++)
{
for (var j = 0; j < matrixA.ColumnCount; j++)
{
Assert.AreEqual(matrixACopy[i, j], matrixA[i, j]);
}
}
// Make sure b didn't change. // Check the reconstruction.
for (var i = 0; i < vectorb.Count; i++) AssertHelpers.AlmostEqual(b, bReconstruct, 2);
{
Assert.AreEqual(vectorbCopy[i], vectorb[i]); // Make sure A/B didn't change.
} AssertHelpers.AlmostEqual(ACopy, A, 14);
AssertHelpers.AlmostEqual(bCopy, b, 14);
} }
/// <summary> /// <summary>
/// Can solve a system of linear equations for a random matrix and symmetric matrix (AX=B) into result matrix. /// Can solve a system of linear equations for a random matrix and symmetric matrix (AX=B) into result matrix.
/// </summary> /// </summary>
/// <param name="order">Matrix order.</param> /// <param name="order">Matrix order.</param>
[TestCase(1)] [Test]
[TestCase(2)] public void CanSolveForRandomMatrixAndSymmetricMatrixWhenResultMatrixGiven([Values(1, 2, 5, 10, 50, 100)] int order)
[TestCase(5)]
[TestCase(10)]
[TestCase(50)]
[TestCase(100)]
public void CanSolveForRandomMatrixAndSymmetricMatrixWhenResultMatrixGiven(int order)
{ {
var matrixA = new UserDefinedMatrix(Matrix<Complex32>.Build.RandomPositiveDefinite(order, 1).ToArray()); var A = new UserDefinedMatrix(Matrix<Complex32>.Build.RandomPositiveDefinite(order, 1).ToArray());
var matrixACopy = matrixA.Clone(); MatrixHelpers.ForceConjugateSymmetric(A);
var factorEvd = matrixA.Evd(); var ACopy = A.Clone();
var evd = A.Evd();
var matrixB = new UserDefinedMatrix(Matrix<Complex32>.Build.Random(order, order, 1).ToArray()); var B = new UserDefinedMatrix(Matrix<Complex32>.Build.Random(order, order, 1).ToArray());
var matrixBCopy = matrixB.Clone(); var BCopy = B.Clone();
var matrixX = new UserDefinedMatrix(order, order); var X = new UserDefinedMatrix(order, order);
factorEvd.Solve(matrixB, matrixX); evd.Solve(B, X);
// The solution X row dimension is equal to the column dimension of A // The solution X row dimension is equal to the column dimension of A
Assert.AreEqual(matrixA.ColumnCount, matrixX.RowCount); Assert.AreEqual(A.ColumnCount, X.RowCount);
// The solution X has the same number of columns as B // The solution X has the same number of columns as B
Assert.AreEqual(matrixB.ColumnCount, matrixX.ColumnCount); Assert.AreEqual(B.ColumnCount, X.ColumnCount);
var matrixBReconstruct = matrixA * matrixX; var BReconstruct = A * X;
// Check the reconstruction. // Check the reconstruction.
for (var i = 0; i < matrixB.RowCount; i++) AssertHelpers.AlmostEqual(B, BReconstruct, 1);
{
for (var j = 0; j < matrixB.ColumnCount; j++)
{
Assert.AreEqual(matrixB[i, j].Real, matrixBReconstruct[i, j].Real, 1e-1f);
Assert.AreEqual(matrixB[i, j].Imaginary, matrixBReconstruct[i, j].Imaginary, 1e-1f);
}
}
// Make sure A didn't change. // Make sure A/B didn't change.
for (var i = 0; i < matrixA.RowCount; i++) AssertHelpers.AlmostEqual(ACopy, A, 14);
{ AssertHelpers.AlmostEqual(BCopy, B, 14);
for (var j = 0; j < matrixA.ColumnCount; j++)
{
Assert.AreEqual(matrixACopy[i, j], matrixA[i, j]);
}
}
// Make sure B didn't change.
for (var i = 0; i < matrixB.RowCount; i++)
{
for (var j = 0; j < matrixB.ColumnCount; j++)
{
Assert.AreEqual(matrixBCopy[i, j], matrixB[i, j]);
}
}
} }
} }
} }

373
src/UnitTests/LinearAlgebraTests/Double/Factorization/EvdTests.cs

@ -3,7 +3,9 @@
// http://numerics.mathdotnet.com // http://numerics.mathdotnet.com
// http://github.com/mathnet/mathnet-numerics // http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com // http://mathnetnumerics.codeplex.com
// Copyright (c) 2009-2010 Math.NET //
// Copyright (c) 2009-2014 Math.NET
//
// Permission is hereby granted, free of charge, to any person // Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation // obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without // files (the "Software"), to deal in the Software without
@ -12,8 +14,10 @@
// copies of the Software, and to permit persons to whom the // copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following // Software is furnished to do so, subject to the following
// conditions: // conditions:
//
// The above copyright notice and this permission notice shall be // The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software. // included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
@ -42,26 +46,19 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double.Factorization
[TestFixture, Category("LAFactorization")] [TestFixture, Category("LAFactorization")]
public class EvdTests public class EvdTests
{ {
/// <summary> [Test]
/// Can factorize identity matrix. public void CanFactorizeIdentityMatrix([Values(1, 10, 100)] int order)
/// </summary>
/// <param name="order">Matrix order.</param>
[TestCase(1)]
[TestCase(10)]
[TestCase(100)]
public void CanFactorizeIdentity(int order)
{ {
var matrixI = Matrix<double>.Build.DenseIdentity(order); var matrix = Matrix<double>.Build.DenseIdentity(order);
var factorEvd = matrixI.Evd(); var factorEvd = matrix.Evd();
var eigenValues = factorEvd.EigenValues; var eigenValues = factorEvd.EigenValues;
var eigenVectors = factorEvd.EigenVectors; var eigenVectors = factorEvd.EigenVectors;
var d = factorEvd.D; var d = factorEvd.D;
Assert.AreEqual(matrixI.RowCount, eigenVectors.RowCount); Assert.AreEqual(matrix.RowCount, eigenVectors.RowCount);
Assert.AreEqual(matrixI.RowCount, eigenVectors.ColumnCount); Assert.AreEqual(matrix.RowCount, eigenVectors.ColumnCount);
Assert.AreEqual(matrix.ColumnCount, d.RowCount);
Assert.AreEqual(matrixI.ColumnCount, d.RowCount); Assert.AreEqual(matrix.ColumnCount, d.ColumnCount);
Assert.AreEqual(matrixI.ColumnCount, d.ColumnCount);
for (var i = 0; i < eigenValues.Count; i++) for (var i = 0; i < eigenValues.Count; i++)
{ {
@ -69,127 +66,75 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double.Factorization
} }
} }
/// <summary> [Test]
/// Can factorize a random square matrix. public void CanFactorizeRandomSquareMatrix([Values(1, 2, 5, 10, 50, 100)] int order)
/// </summary>
/// <param name="order">Matrix order.</param>
[TestCase(1)]
[TestCase(2)]
[TestCase(5)]
[TestCase(10)]
[TestCase(50)]
[TestCase(100)]
public void CanFactorizeRandomMatrix(int order)
{ {
var matrixA = Matrix<double>.Build.Random(order, order, 1); var A = Matrix<double>.Build.Random(order, order, 1);
var factorEvd = matrixA.Evd(); var factorEvd = A.Evd();
var eigenVectors = factorEvd.EigenVectors; var V = factorEvd.EigenVectors;
var d = factorEvd.D; var λ = factorEvd.D;
Assert.AreEqual(order, eigenVectors.RowCount); Assert.AreEqual(order, V.RowCount);
Assert.AreEqual(order, eigenVectors.ColumnCount); Assert.AreEqual(order, V.ColumnCount);
Assert.AreEqual(order, λ.RowCount);
Assert.AreEqual(order, d.RowCount); Assert.AreEqual(order, λ.ColumnCount);
Assert.AreEqual(order, d.ColumnCount);
// Verify A*V = λ*V
// Make sure the A*V = λ*V var Av = A * V;
var matrixAv = matrixA * eigenVectors; var Lv = V * λ;
var matrixLv = eigenVectors * factorEvd.D; AssertHelpers.AlmostEqual(Av, Lv, 10);
AssertHelpers.AlmostEqualRelative(Av, Lv, 8);
for (var i = 0; i < matrixAv.RowCount; i++)
{
for (var j = 0; j < matrixAv.ColumnCount; j++)
{
Assert.AreEqual(matrixAv[i, j], matrixLv[i, j], 1.0e-10);
}
}
} }
/// <summary> [Test]
/// Can factorize a symmetric random square matrix. public void CanFactorizeRandomSymmetricMatrix([Values(1, 2, 5, 10, 50, 100)] int order)
/// </summary>
/// <param name="order">Matrix order.</param>
[TestCase(1)]
[TestCase(2)]
[TestCase(5)]
[TestCase(10)]
[TestCase(50)]
[TestCase(100)]
public void CanFactorizeRandomSymmetricMatrix(int order)
{ {
var matrixA = Matrix<double>.Build.RandomPositiveDefinite(order, 1); var A = Matrix<double>.Build.RandomPositiveDefinite(order, 1);
MatrixHelpers.ForceSymmetric(matrixA); MatrixHelpers.ForceSymmetric(A);
var factorEvd = matrixA.Evd(); var factorEvd = A.Evd();
var eigenVectors = factorEvd.EigenVectors; var V = factorEvd.EigenVectors;
var d = factorEvd.D; var λ = factorEvd.D;
Assert.AreEqual(order, eigenVectors.RowCount); Assert.AreEqual(order, V.RowCount);
Assert.AreEqual(order, eigenVectors.ColumnCount); Assert.AreEqual(order, V.ColumnCount);
Assert.AreEqual(order, λ.RowCount);
Assert.AreEqual(order, d.RowCount); Assert.AreEqual(order, λ.ColumnCount);
Assert.AreEqual(order, d.ColumnCount);
// Verify A = V*λ*VT
// Make sure the A = V*λ*VT var matrix = V * λ * V.Transpose();
var matrix = eigenVectors * d * eigenVectors.Transpose(); AssertHelpers.AlmostEqual(matrix, A, 10);
AssertHelpers.AlmostEqualRelative(matrix, A, 10);
for (var i = 0; i < matrix.RowCount; i++)
{
for (var j = 0; j < matrix.ColumnCount; j++)
{
Assert.AreEqual(matrix[i, j], matrixA[i, j], 1.0e-10);
}
}
} }
/// <summary> [Test]
/// Can check rank of square matrix. public void CanCheckRankSquare([Values(10, 50, 100)] int order)
/// </summary>
/// <param name="order">Matrix order.</param>
[TestCase(10)]
[TestCase(50)]
[TestCase(100)]
public void CanCheckRankSquare(int order)
{ {
var matrixA = Matrix<double>.Build.Random(order, order, 1); var A = Matrix<double>.Build.Random(order, order, 1);
var factorEvd = matrixA.Evd(); Assert.AreEqual(A.Evd().Rank, order);
Assert.AreEqual(factorEvd.Rank, order);
} }
/// <summary> [Test]
/// Can check rank of square singular matrix. public void CanCheckRankOfSquareSingular([Values(10, 50, 100)] int order)
/// </summary>
/// <param name="order">Matrix order.</param>
[TestCase(10)]
[TestCase(50)]
[TestCase(100)]
public void CanCheckRankOfSquareSingular(int order)
{ {
var matrixA = new DenseMatrix(order, order); var A = new DenseMatrix(order, order);
matrixA[0, 0] = 1; A[0, 0] = 1;
matrixA[order - 1, order - 1] = 1; A[order - 1, order - 1] = 1;
for (var i = 1; i < order - 1; i++) for (var i = 1; i < order - 1; i++)
{ {
matrixA[i, i - 1] = 1; A[i, i - 1] = 1;
matrixA[i, i + 1] = 1; A[i, i + 1] = 1;
matrixA[i - 1, i] = 1; A[i - 1, i] = 1;
matrixA[i + 1, i] = 1; A[i + 1, i] = 1;
} }
var factorEvd = matrixA.Evd(); var factorEvd = A.Evd();
Assert.AreEqual(factorEvd.Determinant, 0); Assert.AreEqual(factorEvd.Determinant, 0);
Assert.AreEqual(factorEvd.Rank, order - 1); Assert.AreEqual(factorEvd.Rank, order - 1);
} }
/// <summary> [Test]
/// Identity determinant is one. public void IdentityDeterminantIsOne([Values(1, 10, 100)] int order)
/// </summary>
/// <param name="order">Matrix order.</param>
[TestCase(1)]
[TestCase(10)]
[TestCase(100)]
public void IdentityDeterminantIsOne(int order)
{ {
var matrixI = Matrix<double>.Build.DenseIdentity(order); var matrixI = Matrix<double>.Build.DenseIdentity(order);
var factorEvd = matrixI.Evd(); var factorEvd = matrixI.Evd();
@ -201,40 +146,26 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double.Factorization
/// </summary> /// </summary>
/// <param name="order">Matrix order.</param> /// <param name="order">Matrix order.</param>
[Test] [Test]
[TestCase(1)] public void CanSolveForRandomVectorAndSymmetricMatrix([Values(1, 2, 5, 10, 50, 100)] int order)
[TestCase(2)]
[TestCase(5)]
[TestCase(10)]
[TestCase(50)]
[TestCase(100)]
public void CanSolveForRandomVectorAndSymmetricMatrix(int order)
{ {
var matrixA = Matrix<double>.Build.RandomPositiveDefinite(order, 1); var A = Matrix<double>.Build.RandomPositiveDefinite(order, 1);
MatrixHelpers.ForceSymmetric(matrixA); MatrixHelpers.ForceSymmetric(A);
var matrixACopy = matrixA.Clone(); var ACopy = A.Clone();
var factorEvd = matrixA.Evd(); var evd = A.Evd();
var vectorb = Vector<double>.Build.Random(order, 1); var b = Vector<double>.Build.Random(order, 2);
var resultx = factorEvd.Solve(vectorb); var bCopy = b.Clone();
Assert.AreEqual(matrixA.ColumnCount, resultx.Count); var x = evd.Solve(b);
var matrixBReconstruct = matrixA * resultx; var bReconstruct = A * x;
// Check the reconstruction. // Check the reconstruction.
for (var i = 0; i < vectorb.Count; i++) AssertHelpers.ListAlmostEqual(b, bReconstruct, 9);
{
Assert.AreEqual(vectorb[i], matrixBReconstruct[i], 1e-9);
}
// Make sure A didn't change. // Make sure A/B didn't change.
for (var i = 0; i < matrixA.RowCount; i++) AssertHelpers.AlmostEqual(ACopy, A, 14);
{ AssertHelpers.ListAlmostEqual(bCopy, b, 14);
for (var j = 0; j < matrixA.ColumnCount; j++)
{
Assert.AreEqual(matrixACopy[i, j], matrixA[i, j]);
}
}
} }
//private //private
@ -243,48 +174,32 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double.Factorization
/// </summary> /// </summary>
/// <param name="order">Matrix order.</param> /// <param name="order">Matrix order.</param>
[Test] [Test]
[TestCase(1)] public void CanSolveForRandomMatrixAndSymmetricMatrix([Values(1, 2, 5, 10, 50, 100)] int order)
[TestCase(2)]
[TestCase(5)]
[TestCase(10)]
[TestCase(50)]
[TestCase(100)]
public void CanSolveForRandomMatrixAndSymmetricMatrix(int order)
{ {
var matrixA = Matrix<double>.Build.RandomPositiveDefinite(order, 1); var A = Matrix<double>.Build.RandomPositiveDefinite(order, 1);
MatrixHelpers.ForceSymmetric(matrixA); MatrixHelpers.ForceSymmetric(A);
var matrixACopy = matrixA.Clone(); var ACopy = A.Clone();
var factorEvd = matrixA.Evd(); var evd = A.Evd();
var matrixB = Matrix<double>.Build.Random(order, order, 1); var B = Matrix<double>.Build.Random(order, order, 2);
var BCopy = B.Clone();
var matrixX = factorEvd.Solve(matrixB); var X = evd.Solve(B);
// The solution X row dimension is equal to the column dimension of A // The solution X row dimension is equal to the column dimension of A
Assert.AreEqual(matrixA.ColumnCount, matrixX.RowCount); Assert.AreEqual(A.ColumnCount, X.RowCount);
// The solution X has the same number of columns as B // The solution X has the same number of columns as B
Assert.AreEqual(matrixB.ColumnCount, matrixX.ColumnCount); Assert.AreEqual(B.ColumnCount, X.ColumnCount);
var matrixBReconstruct = matrixA * matrixX; var BReconstruct = A * X;
// Check the reconstruction. // Check the reconstruction.
for (var i = 0; i < matrixB.RowCount; i++) AssertHelpers.AlmostEqual(B, BReconstruct, 9);
{
for (var j = 0; j < matrixB.ColumnCount; j++)
{
Assert.AreEqual(matrixB[i, j], matrixBReconstruct[i, j], 1e-9);
}
}
// Make sure A didn't change. // Make sure A/B didn't change.
for (var i = 0; i < matrixA.RowCount; i++) AssertHelpers.AlmostEqual(ACopy, A, 14);
{ AssertHelpers.AlmostEqual(BCopy, B, 14);
for (var j = 0; j < matrixA.ColumnCount; j++)
{
Assert.AreEqual(matrixACopy[i, j], matrixA[i, j]);
}
}
} }
/// <summary> /// <summary>
@ -292,45 +207,27 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double.Factorization
/// </summary> /// </summary>
/// <param name="order">Matrix order.</param> /// <param name="order">Matrix order.</param>
[Test] [Test]
[TestCase(1)] public void CanSolveForRandomVectorAndSymmetricMatrixWhenResultVectorGiven([Values(1, 2, 5, 10, 50, 100)] int order)
[TestCase(2)]
[TestCase(5)]
[TestCase(10)]
[TestCase(50)]
[TestCase(100)]
public void CanSolveForRandomVectorAndSymmetricMatrixWhenResultVectorGiven(int order)
{ {
var matrixA = Matrix<double>.Build.RandomPositiveDefinite(order, 1); var A = Matrix<double>.Build.RandomPositiveDefinite(order, 1);
MatrixHelpers.ForceSymmetric(matrixA); MatrixHelpers.ForceSymmetric(A);
var matrixACopy = matrixA.Clone(); var ACopy = A.Clone();
var factorEvd = matrixA.Evd(); var evd = A.Evd();
var vectorb = Vector<double>.Build.Random(order, 1);
var vectorbCopy = vectorb.Clone();
var resultx = new DenseVector(order);
factorEvd.Solve(vectorb, resultx);
var matrixBReconstruct = matrixA * resultx; var b = Vector<double>.Build.Random(order, 2);
var bCopy = b.Clone();
// Check the reconstruction. var x = new DenseVector(order);
for (var i = 0; i < vectorb.Count; i++) evd.Solve(b, x);
{
Assert.AreEqual(vectorb[i], matrixBReconstruct[i], 1e-9);
}
// Make sure A didn't change. var bReconstruct = A * x;
for (var i = 0; i < matrixA.RowCount; i++)
{
for (var j = 0; j < matrixA.ColumnCount; j++)
{
Assert.AreEqual(matrixACopy[i, j], matrixA[i, j]);
}
}
// Make sure b didn't change. // Check the reconstruction.
for (var i = 0; i < vectorb.Count; i++) AssertHelpers.ListAlmostEqual(b, bReconstruct, 9);
{
Assert.AreEqual(vectorbCopy[i], vectorb[i]); // Make sure A/B didn't change.
} AssertHelpers.AlmostEqual(ACopy, A, 14);
AssertHelpers.ListAlmostEqual(bCopy, b, 14);
} }
/// <summary> /// <summary>
@ -338,59 +235,33 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double.Factorization
/// </summary> /// </summary>
/// <param name="order">Matrix order.</param> /// <param name="order">Matrix order.</param>
[Test] [Test]
[TestCase(1)] public void CanSolveForRandomMatrixAndSymmetricMatrixWhenResultMatrixGiven([Values(1, 2, 5, 10, 50, 100)] int order)
[TestCase(2)]
[TestCase(5)]
[TestCase(10)]
[TestCase(50)]
[TestCase(100)]
public void CanSolveForRandomMatrixAndSymmetricMatrixWhenResultMatrixGiven(int order)
{ {
var matrixA = Matrix<double>.Build.RandomPositiveDefinite(order, 1); var A = Matrix<double>.Build.RandomPositiveDefinite(order, 1);
MatrixHelpers.ForceSymmetric(matrixA); MatrixHelpers.ForceSymmetric(A);
var matrixACopy = matrixA.Clone(); var ACopy = A.Clone();
var factorEvd = matrixA.Evd(); var evd = A.Evd();
var matrixB = Matrix<double>.Build.Random(order, order, 1); var B = Matrix<double>.Build.Random(order, order, 2);
var matrixBCopy = matrixB.Clone(); var BCopy = B.Clone();
var matrixX = new DenseMatrix(order, order); var X = new DenseMatrix(order, order);
factorEvd.Solve(matrixB, matrixX); evd.Solve(B, X);
// The solution X row dimension is equal to the column dimension of A // The solution X row dimension is equal to the column dimension of A
Assert.AreEqual(matrixA.ColumnCount, matrixX.RowCount); Assert.AreEqual(A.ColumnCount, X.RowCount);
// The solution X has the same number of columns as B // The solution X has the same number of columns as B
Assert.AreEqual(matrixB.ColumnCount, matrixX.ColumnCount); Assert.AreEqual(B.ColumnCount, X.ColumnCount);
var matrixBReconstruct = matrixA * matrixX; var BReconstruct = A * X;
// Check the reconstruction. // Check the reconstruction.
for (var i = 0; i < matrixB.RowCount; i++) AssertHelpers.AlmostEqual(B, BReconstruct, 9);
{
for (var j = 0; j < matrixB.ColumnCount; j++)
{
Assert.AreEqual(matrixB[i, j], matrixBReconstruct[i, j], 1e-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]);
}
}
// Make sure B didn't change. // Make sure A/B didn't change.
for (var i = 0; i < matrixB.RowCount; i++) AssertHelpers.AlmostEqual(ACopy, A, 14);
{ AssertHelpers.AlmostEqual(BCopy, B, 14);
for (var j = 0; j < matrixB.ColumnCount; j++)
{
Assert.AreEqual(matrixBCopy[i, j], matrixB[i, j]);
}
}
} }
} }
} }

195
src/UnitTests/LinearAlgebraTests/Double/Factorization/UserEvdTests.cs

@ -198,187 +198,122 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double.Factorization
/// Can solve a system of linear equations for a random vector and symmetric matrix (Ax=b). /// Can solve a system of linear equations for a random vector and symmetric matrix (Ax=b).
/// </summary> /// </summary>
/// <param name="order">Matrix order.</param> /// <param name="order">Matrix order.</param>
[TestCase(1)] [Test]
[TestCase(2)] public void CanSolveForRandomVectorAndSymmetricMatrix([Values(1, 2, 5, 10, 50, 100)] int order)
[TestCase(5)]
[TestCase(10)]
[TestCase(50)]
[TestCase(100)]
public void CanSolveForRandomVectorAndSymmetricMatrix(int order)
{ {
var matrixA = new UserDefinedMatrix(Matrix<double>.Build.RandomPositiveDefinite(order, 1).ToArray()); var A = new UserDefinedMatrix(Matrix<double>.Build.RandomPositiveDefinite(order, 1).ToArray());
var matrixACopy = matrixA.Clone(); MatrixHelpers.ForceSymmetric(A);
var factorEvd = matrixA.Evd(); var ACopy = A.Clone();
var evd = A.Evd();
var vectorb = new UserDefinedVector(Vector<double>.Build.Random(order, 1).ToArray()); var b = new UserDefinedVector(Vector<double>.Build.Random(order, 1).ToArray());
var resultx = factorEvd.Solve(vectorb); var bCopy = b.Clone();
Assert.AreEqual(matrixA.ColumnCount, resultx.Count); var x = evd.Solve(b);
var matrixBReconstruct = matrixA * resultx; var bReconstruct = A * x;
// Check the reconstruction. // Check the reconstruction.
for (var i = 0; i < vectorb.Count; i++) AssertHelpers.AlmostEqual(b, bReconstruct, 9);
{
Assert.AreEqual(vectorb[i], matrixBReconstruct[i], 1e-9);
}
// Make sure A didn't change. // Make sure A/B didn't change.
for (var i = 0; i < matrixA.RowCount; i++) AssertHelpers.AlmostEqual(ACopy, A, 14);
{ AssertHelpers.AlmostEqual(bCopy, b, 14);
for (var j = 0; j < matrixA.ColumnCount; j++)
{
Assert.AreEqual(matrixACopy[i, j], matrixA[i, j]);
}
}
} }
/// <summary> /// <summary>
/// Can solve a system of linear equations for a random matrix and symmetric matrix (AX=B). /// Can solve a system of linear equations for a random matrix and symmetric matrix (AX=B).
/// </summary> /// </summary>
/// <param name="order">Matrix order.</param> /// <param name="order">Matrix order.</param>
[TestCase(1)] [Test]
[TestCase(2)] public void CanSolveForRandomMatrixAndSymmetricMatrix([Values(1, 2, 5, 10, 50, 100)] int order)
[TestCase(5)]
[TestCase(10)]
[TestCase(50)]
[TestCase(100)]
public void CanSolveForRandomMatrixAndSymmetricMatrix(int order)
{ {
var matrixA = new UserDefinedMatrix(Matrix<double>.Build.RandomPositiveDefinite(order, 1).ToArray()); var A = new UserDefinedMatrix(Matrix<double>.Build.RandomPositiveDefinite(order, 1).ToArray());
var matrixACopy = matrixA.Clone(); MatrixHelpers.ForceSymmetric(A);
var factorEvd = matrixA.Evd(); var ACopy = A.Clone();
var evd = A.Evd();
var B = new UserDefinedMatrix(Matrix<double>.Build.Random(order, order, 1).ToArray());
var BCopy = B.Clone();
var matrixB = new UserDefinedMatrix(Matrix<double>.Build.Random(order, order, 1).ToArray()); var X = evd.Solve(B);
var matrixX = factorEvd.Solve(matrixB);
// The solution X row dimension is equal to the column dimension of A // The solution X row dimension is equal to the column dimension of A
Assert.AreEqual(matrixA.ColumnCount, matrixX.RowCount); Assert.AreEqual(A.ColumnCount, X.RowCount);
// The solution X has the same number of columns as B // The solution X has the same number of columns as B
Assert.AreEqual(matrixB.ColumnCount, matrixX.ColumnCount); Assert.AreEqual(B.ColumnCount, X.ColumnCount);
var matrixBReconstruct = matrixA * matrixX; var BReconstruct = A * X;
// Check the reconstruction. // Check the reconstruction.
for (var i = 0; i < matrixB.RowCount; i++) AssertHelpers.AlmostEqual(B, BReconstruct, 8);
{
for (var j = 0; j < matrixB.ColumnCount; j++)
{
Assert.AreEqual(matrixB[i, j], matrixBReconstruct[i, j], 1e-9);
}
}
// Make sure A didn't change. // Make sure A/B didn't change.
for (var i = 0; i < matrixA.RowCount; i++) AssertHelpers.AlmostEqual(ACopy, A, 14);
{ AssertHelpers.AlmostEqual(BCopy, B, 14);
for (var j = 0; j < matrixA.ColumnCount; j++)
{
Assert.AreEqual(matrixACopy[i, j], matrixA[i, j]);
}
}
} }
/// <summary> /// <summary>
/// Can solve a system of linear equations for a random vector and symmetric matrix (Ax=b) into a result matrix. /// Can solve a system of linear equations for a random vector and symmetric matrix (Ax=b) into a result matrix.
/// </summary> /// </summary>
/// <param name="order">Matrix order.</param> /// <param name="order">Matrix order.</param>
[TestCase(1)] [Test]
[TestCase(2)] public void CanSolveForRandomVectorAndSymmetricMatrixWhenResultVectorGiven([Values(1, 2, 5, 10, 50, 100)] int order)
[TestCase(5)]
[TestCase(10)]
[TestCase(50)]
[TestCase(100)]
public void CanSolveForRandomVectorAndSymmetricMatrixWhenResultVectorGiven(int order)
{ {
var matrixA = new UserDefinedMatrix(Matrix<double>.Build.RandomPositiveDefinite(order, 1).ToArray()); var A = new UserDefinedMatrix(Matrix<double>.Build.RandomPositiveDefinite(order, 1).ToArray());
var matrixACopy = matrixA.Clone(); MatrixHelpers.ForceSymmetric(A);
var factorEvd = matrixA.Evd(); var ACopy = A.Clone();
var vectorb = new UserDefinedVector(Vector<double>.Build.Random(order, 1).ToArray()); var evd = A.Evd();
var vectorbCopy = vectorb.Clone();
var resultx = new UserDefinedVector(order);
factorEvd.Solve(vectorb, resultx);
var matrixBReconstruct = matrixA * resultx; var b = new UserDefinedVector(Vector<double>.Build.Random(order, 1).ToArray());
var bCopy = b.Clone();
// Check the reconstruction. var x = new UserDefinedVector(order);
for (var i = 0; i < vectorb.Count; i++) evd.Solve(b, x);
{
Assert.AreEqual(vectorb[i], matrixBReconstruct[i], 1e-9);
}
// Make sure A didn't change. var bReconstruct = A * x;
for (var i = 0; i < matrixA.RowCount; i++)
{
for (var j = 0; j < matrixA.ColumnCount; j++)
{
Assert.AreEqual(matrixACopy[i, j], matrixA[i, j]);
}
}
// Make sure b didn't change. // Check the reconstruction.
for (var i = 0; i < vectorb.Count; i++) AssertHelpers.AlmostEqual(b, bReconstruct, 9);
{
Assert.AreEqual(vectorbCopy[i], vectorb[i]); // Make sure A/B didn't change.
} AssertHelpers.AlmostEqual(ACopy, A, 14);
AssertHelpers.AlmostEqual(bCopy, b, 14);
} }
/// <summary> /// <summary>
/// Can solve a system of linear equations for a random matrix and symmetric matrix (AX=B) into result matrix. /// Can solve a system of linear equations for a random matrix and symmetric matrix (AX=B) into result matrix.
/// </summary> /// </summary>
/// <param name="order">Matrix order.</param> /// <param name="order">Matrix order.</param>
[TestCase(1)] [Test]
[TestCase(2)] public void CanSolveForRandomMatrixAndSymmetricMatrixWhenResultMatrixGiven([Values(1, 2, 5, 10, 50, 100)] int order)
[TestCase(5)]
[TestCase(10)]
[TestCase(50)]
[TestCase(100)]
public void CanSolveForRandomMatrixAndSymmetricMatrixWhenResultMatrixGiven(int order)
{ {
var matrixA = new UserDefinedMatrix(Matrix<double>.Build.RandomPositiveDefinite(order, 1).ToArray()); var A = new UserDefinedMatrix(Matrix<double>.Build.RandomPositiveDefinite(order, 1).ToArray());
var matrixACopy = matrixA.Clone(); MatrixHelpers.ForceSymmetric(A);
var factorEvd = matrixA.Evd(); var ACopy = A.Clone();
var evd = A.Evd();
var matrixB = new UserDefinedMatrix(Matrix<double>.Build.Random(order, order, 1).ToArray()); var B = new UserDefinedMatrix(Matrix<double>.Build.Random(order, order, 1).ToArray());
var matrixBCopy = matrixB.Clone(); var BCopy = B.Clone();
var matrixX = new UserDefinedMatrix(order, order); var X = new UserDefinedMatrix(order, order);
factorEvd.Solve(matrixB, matrixX); evd.Solve(B, X);
// The solution X row dimension is equal to the column dimension of A // The solution X row dimension is equal to the column dimension of A
Assert.AreEqual(matrixA.ColumnCount, matrixX.RowCount); Assert.AreEqual(A.ColumnCount, X.RowCount);
// The solution X has the same number of columns as B // The solution X has the same number of columns as B
Assert.AreEqual(matrixB.ColumnCount, matrixX.ColumnCount); Assert.AreEqual(B.ColumnCount, X.ColumnCount);
var matrixBReconstruct = matrixA * matrixX; var BReconstruct = A * X;
// Check the reconstruction. // Check the reconstruction.
for (var i = 0; i < matrixB.RowCount; i++) AssertHelpers.AlmostEqual(B, BReconstruct, 8);
{
for (var j = 0; j < matrixB.ColumnCount; j++)
{
Assert.AreEqual(matrixB[i, j], matrixBReconstruct[i, j], 1e-9);
}
}
// Make sure A didn't change. // Make sure A/B didn't change.
for (var i = 0; i < matrixA.RowCount; i++) AssertHelpers.AlmostEqual(ACopy, A, 14);
{ AssertHelpers.AlmostEqual(BCopy, B, 14);
for (var j = 0; j < matrixA.ColumnCount; j++)
{
Assert.AreEqual(matrixACopy[i, j], matrixA[i, j]);
}
}
// Make sure B didn't change.
for (var i = 0; i < matrixB.RowCount; i++)
{
for (var j = 0; j < matrixB.ColumnCount; j++)
{
Assert.AreEqual(matrixBCopy[i, j], matrixB[i, j]);
}
}
} }
} }
} }

361
src/UnitTests/LinearAlgebraTests/Single/Factorization/EvdTests.cs

@ -3,7 +3,9 @@
// http://numerics.mathdotnet.com // http://numerics.mathdotnet.com
// http://github.com/mathnet/mathnet-numerics // http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com // http://mathnetnumerics.codeplex.com
// Copyright (c) 2009-2010 Math.NET //
// Copyright (c) 2009-2014 Math.NET
//
// Permission is hereby granted, free of charge, to any person // Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation // obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without // files (the "Software"), to deal in the Software without
@ -12,8 +14,10 @@
// copies of the Software, and to permit persons to whom the // copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following // Software is furnished to do so, subject to the following
// conditions: // conditions:
//
// The above copyright notice and this permission notice shall be // The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software. // included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
@ -42,26 +46,19 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Single.Factorization
[TestFixture, Category("LAFactorization")] [TestFixture, Category("LAFactorization")]
public class EvdTests public class EvdTests
{ {
/// <summary> [Test]
/// Can factorize identity matrix. public void CanFactorizeIdentityMatrix([Values(1, 10, 100)] int order)
/// </summary>
/// <param name="order">Matrix order.</param>
[TestCase(1)]
[TestCase(10)]
[TestCase(100)]
public void CanFactorizeIdentity(int order)
{ {
var matrixI = DenseMatrix.CreateIdentity(order); var matrix = Matrix<float>.Build.DenseIdentity(order);
var factorEvd = matrixI.Evd(); var factorEvd = matrix.Evd();
var eigenValues = factorEvd.EigenValues; var eigenValues = factorEvd.EigenValues;
var eigenVectors = factorEvd.EigenVectors; var eigenVectors = factorEvd.EigenVectors;
var d = factorEvd.D; var d = factorEvd.D;
Assert.AreEqual(matrixI.RowCount, eigenVectors.RowCount); Assert.AreEqual(matrix.RowCount, eigenVectors.RowCount);
Assert.AreEqual(matrixI.RowCount, eigenVectors.ColumnCount); Assert.AreEqual(matrix.RowCount, eigenVectors.ColumnCount);
Assert.AreEqual(matrix.ColumnCount, d.RowCount);
Assert.AreEqual(matrixI.ColumnCount, d.RowCount); Assert.AreEqual(matrix.ColumnCount, d.ColumnCount);
Assert.AreEqual(matrixI.ColumnCount, d.ColumnCount);
for (var i = 0; i < eigenValues.Count; i++) for (var i = 0; i < eigenValues.Count; i++)
{ {
@ -69,116 +66,73 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Single.Factorization
} }
} }
/// <summary>
/// Can factorize a random square matrix.
/// </summary>
/// <param name="order">Matrix order.</param>
[Test] [Test]
public void CanFactorizeRandomMatrix([Values(1, 2, 5, 10, 50, 100)] int order) public void CanFactorizeRandomSquareMatrix([Values(1, 2, 5, 10, 50, 100)] int order)
{ {
var matrixA = Matrix<float>.Build.Random(order, order, 1); var A = Matrix<float>.Build.Random(order, order, 1);
var factorEvd = matrixA.Evd(); var factorEvd = A.Evd();
var eigenVectors = factorEvd.EigenVectors; var V = factorEvd.EigenVectors;
var d = factorEvd.D; var λ = factorEvd.D;
Assert.AreEqual(order, eigenVectors.RowCount); Assert.AreEqual(order, V.RowCount);
Assert.AreEqual(order, eigenVectors.ColumnCount); Assert.AreEqual(order, V.ColumnCount);
Assert.AreEqual(order, λ.RowCount);
Assert.AreEqual(order, d.RowCount); Assert.AreEqual(order, λ.ColumnCount);
Assert.AreEqual(order, d.ColumnCount);
// Verify A*V = λ*V
// Make sure the A*V = λ*V var Av = A * V;
var matrixAv = matrixA * eigenVectors; var Lv = V * λ;
var matrixLv = eigenVectors * d; AssertHelpers.AlmostEqual(Av, Lv, 4);
for (var i = 0; i < matrixAv.RowCount; i++)
{
for (var j = 0; j < matrixAv.ColumnCount; j++)
{
Assert.AreEqual(matrixAv[i, j], matrixLv[i, j], 1e-3);
}
}
} }
/// <summary>
/// Can factorize a symmetric random square matrix.
/// </summary>
/// <param name="order">Matrix order.</param>
[Test] [Test]
public void CanFactorizeRandomSymmetricMatrix([Values(1, 2, 5, 10, 50)] int order) public void CanFactorizeRandomSymmetricMatrix([Values(1, 2, 5, 10, 50, 100)] int order)
{ {
var matrixA = Matrix<float>.Build.RandomPositiveDefinite(order, 1); var A = Matrix<float>.Build.RandomPositiveDefinite(order, 1);
MatrixHelpers.ForceSymmetric(matrixA); MatrixHelpers.ForceSymmetric(A);
var factorEvd = matrixA.Evd(); var factorEvd = A.Evd();
var eigenVectors = factorEvd.EigenVectors; var V = factorEvd.EigenVectors;
var d = factorEvd.D; var λ = factorEvd.D;
Assert.AreEqual(order, eigenVectors.RowCount); Assert.AreEqual(order, V.RowCount);
Assert.AreEqual(order, eigenVectors.ColumnCount); Assert.AreEqual(order, V.ColumnCount);
Assert.AreEqual(order, λ.RowCount);
Assert.AreEqual(order, d.RowCount); Assert.AreEqual(order, λ.ColumnCount);
Assert.AreEqual(order, d.ColumnCount);
// Verify A = V*λ*VT
// Make sure the A = V*λ*VT var matrix = V * λ * V.Transpose();
var matrix = eigenVectors * d * eigenVectors.Transpose(); AssertHelpers.AlmostEqual(matrix, A, 3);
AssertHelpers.AlmostEqualRelative(matrix, A, 1);
for (var i = 0; i < matrix.RowCount; i++)
{
for (var j = 0; j < matrix.ColumnCount; j++)
{
Assert.AreEqual(matrix[i, j], matrixA[i, j], 1e-3);
}
}
} }
/// <summary> [Test]
/// Can check rank of square matrix. public void CanCheckRankSquare([Values(10, 50, 100)] int order)
/// </summary>
/// <param name="order">Matrix order.</param>
[TestCase(10)]
[TestCase(50)]
[TestCase(100)]
public void CanCheckRankSquare(int order)
{ {
var matrixA = Matrix<float>.Build.Random(order, order, 1); var A = Matrix<float>.Build.Random(order, order, 1);
var factorEvd = matrixA.Evd(); Assert.AreEqual(A.Evd().Rank, order);
Assert.AreEqual(factorEvd.Rank, order);
} }
/// <summary> [Test]
/// Can check rank of square singular matrix. public void CanCheckRankOfSquareSingular([Values(10, 50, 100)] int order)
/// </summary>
/// <param name="order">Matrix order.</param>
[TestCase(10)]
[TestCase(50)]
[TestCase(100)]
public void CanCheckRankOfSquareSingular(int order)
{ {
var matrixA = new DenseMatrix(order, order); var A = new DenseMatrix(order, order);
matrixA[0, 0] = 1; A[0, 0] = 1;
matrixA[order - 1, order - 1] = 1; A[order - 1, order - 1] = 1;
for (var i = 1; i < order - 1; i++) for (var i = 1; i < order - 1; i++)
{ {
matrixA[i, i - 1] = 1; A[i, i - 1] = 1;
matrixA[i, i + 1] = 1; A[i, i + 1] = 1;
matrixA[i - 1, i] = 1; A[i - 1, i] = 1;
matrixA[i + 1, i] = 1; A[i + 1, i] = 1;
} }
var factorEvd = matrixA.Evd(); var factorEvd = A.Evd();
Assert.AreEqual(factorEvd.Determinant, 0); Assert.AreEqual(factorEvd.Determinant, 0);
Assert.AreEqual(factorEvd.Rank, order - 1); Assert.AreEqual(factorEvd.Rank, order - 1);
} }
/// <summary> [Test]
/// Identity determinant is one. public void IdentityDeterminantIsOne([Values(1, 10, 100)] int order)
/// </summary>
/// <param name="order">Matrix order.</param>
[TestCase(1)]
[TestCase(10)]
[TestCase(100)]
public void IdentityDeterminantIsOne(int order)
{ {
var matrixI = DenseMatrix.CreateIdentity(order); var matrixI = DenseMatrix.CreateIdentity(order);
var factorEvd = matrixI.Evd(); var factorEvd = matrixI.Evd();
@ -190,40 +144,26 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Single.Factorization
/// </summary> /// </summary>
/// <param name="order">Matrix order.</param> /// <param name="order">Matrix order.</param>
[Test] [Test]
[TestCase(1)] public void CanSolveForRandomVectorAndSymmetricMatrix([Values(1, 2, 5, 10, 50, 100)] int order)
[TestCase(2)]
[TestCase(5)]
[TestCase(10)]
[TestCase(50)]
[TestCase(100)]
public void CanSolveForRandomVectorAndSymmetricMatrix(int order)
{ {
var matrixA = Matrix<float>.Build.RandomPositiveDefinite(order, 1); var A = Matrix<float>.Build.RandomPositiveDefinite(order, 1);
MatrixHelpers.ForceSymmetric(matrixA); MatrixHelpers.ForceSymmetric(A);
var matrixACopy = matrixA.Clone(); var ACopy = A.Clone();
var factorEvd = matrixA.Evd(); var evd = A.Evd();
var vectorb = Vector<float>.Build.Random(order, 1); var b = Vector<float>.Build.Random(order, 2);
var resultx = factorEvd.Solve(vectorb); var bCopy = b.Clone();
Assert.AreEqual(matrixA.ColumnCount, resultx.Count); var x = evd.Solve(b);
var matrixBReconstruct = matrixA * resultx; var bReconstruct = A * x;
// Check the reconstruction. // Check the reconstruction.
for (var i = 0; i < vectorb.Count; i++) AssertHelpers.ListAlmostEqual(b, bReconstruct, 0);
{
Assert.AreEqual(vectorb[i], matrixBReconstruct[i], 1e-1);
}
// Make sure A didn't change. // Make sure A/B didn't change.
for (var i = 0; i < matrixA.RowCount; i++) AssertHelpers.AlmostEqual(ACopy, A, 14);
{ AssertHelpers.ListAlmostEqual(bCopy, b, 14);
for (var j = 0; j < matrixA.ColumnCount; j++)
{
Assert.AreEqual(matrixACopy[i, j], matrixA[i, j]);
}
}
} }
/// <summary> /// <summary>
@ -231,47 +171,32 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Single.Factorization
/// </summary> /// </summary>
/// <param name="order">Matrix order.</param> /// <param name="order">Matrix order.</param>
[Test] [Test]
[TestCase(1)] public void CanSolveForRandomMatrixAndSymmetricMatrix([Values(1, 2, 5, 10, 50, 100)] int order)
[TestCase(2)]
[TestCase(5)]
[TestCase(10)]
[TestCase(50)]
[TestCase(100)]
public void CanSolveForRandomMatrixAndSymmetricMatrix(int order)
{ {
var matrixA = Matrix<float>.Build.RandomPositiveDefinite(order, 1); var A = Matrix<float>.Build.RandomPositiveDefinite(order, 1);
MatrixHelpers.ForceSymmetric(matrixA); MatrixHelpers.ForceSymmetric(A);
var matrixACopy = matrixA.Clone(); var ACopy = A.Clone();
var factorEvd = matrixA.Evd(); var evd = A.Evd();
var B = Matrix<float>.Build.Random(order, order, 2);
var BCopy = B.Clone();
var matrixB = Matrix<float>.Build.Random(order, order, 1); var X = evd.Solve(B);
var matrixX = factorEvd.Solve(matrixB);
// The solution X row dimension is equal to the column dimension of A // The solution X row dimension is equal to the column dimension of A
Assert.AreEqual(matrixA.ColumnCount, matrixX.RowCount); Assert.AreEqual(A.ColumnCount, X.RowCount);
// The solution X has the same number of columns as B // The solution X has the same number of columns as B
Assert.AreEqual(matrixB.ColumnCount, matrixX.ColumnCount); Assert.AreEqual(B.ColumnCount, X.ColumnCount);
var matrixBReconstruct = matrixA * matrixX; var BReconstruct = A * X;
// Check the reconstruction. // Check the reconstruction.
for (var i = 0; i < matrixB.RowCount; i++) AssertHelpers.AlmostEqual(B, BReconstruct, 0);
{
for (var j = 0; j < matrixB.ColumnCount; j++)
{
Assert.AreEqual(matrixB[i, j], matrixBReconstruct[i, j], 1);
}
}
// Make sure A didn't change. // Make sure A/B didn't change.
for (var i = 0; i < matrixA.RowCount; i++) AssertHelpers.AlmostEqual(ACopy, A, 14);
{ AssertHelpers.AlmostEqual(BCopy, B, 14);
for (var j = 0; j < matrixA.ColumnCount; j++)
{
Assert.AreEqual(matrixACopy[i, j], matrixA[i, j]);
}
}
} }
/// <summary> /// <summary>
@ -279,45 +204,27 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Single.Factorization
/// </summary> /// </summary>
/// <param name="order">Matrix order.</param> /// <param name="order">Matrix order.</param>
[Test] [Test]
[TestCase(1)] public void CanSolveForRandomVectorAndSymmetricMatrixWhenResultVectorGiven([Values(1, 2, 5, 10, 50, 100)] int order)
[TestCase(2)]
[TestCase(5)]
[TestCase(10)]
[TestCase(50)]
[TestCase(100)]
public void CanSolveForRandomVectorAndSymmetricMatrixWhenResultVectorGiven(int order)
{ {
var matrixA = Matrix<float>.Build.RandomPositiveDefinite(order, 1); var A = Matrix<float>.Build.RandomPositiveDefinite(order, 1);
MatrixHelpers.ForceSymmetric(matrixA); MatrixHelpers.ForceSymmetric(A);
var matrixACopy = matrixA.Clone(); var ACopy = A.Clone();
var factorEvd = matrixA.Evd(); var evd = A.Evd();
var vectorb = Vector<float>.Build.Random(order, 1);
var vectorbCopy = vectorb.Clone();
var resultx = new DenseVector(order);
factorEvd.Solve(vectorb, resultx);
var matrixBReconstruct = matrixA * resultx; var b = Vector<float>.Build.Random(order, 2);
var bCopy = b.Clone();
// Check the reconstruction. var x = new DenseVector(order);
for (var i = 0; i < vectorb.Count; i++) evd.Solve(b, x);
{
Assert.AreEqual(vectorb[i], matrixBReconstruct[i], 1e-1);
}
// Make sure A didn't change. var bReconstruct = A * x;
for (var i = 0; i < matrixA.RowCount; i++)
{
for (var j = 0; j < matrixA.ColumnCount; j++)
{
Assert.AreEqual(matrixACopy[i, j], matrixA[i, j]);
}
}
// Make sure b didn't change. // Check the reconstruction.
for (var i = 0; i < vectorb.Count; i++) AssertHelpers.ListAlmostEqual(b, bReconstruct, 0);
{
Assert.AreEqual(vectorbCopy[i], vectorb[i]); // Make sure A/B didn't change.
} AssertHelpers.AlmostEqual(ACopy, A, 14);
AssertHelpers.ListAlmostEqual(bCopy, b, 14);
} }
/// <summary> /// <summary>
@ -325,59 +232,33 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Single.Factorization
/// </summary> /// </summary>
/// <param name="order">Matrix order.</param> /// <param name="order">Matrix order.</param>
[Test] [Test]
[TestCase(1)] public void CanSolveForRandomMatrixAndSymmetricMatrixWhenResultMatrixGiven([Values(1, 2, 5, 10, 50, 100)] int order)
[TestCase(2)]
[TestCase(5)]
[TestCase(10)]
[TestCase(50)]
[TestCase(100)]
public void CanSolveForRandomMatrixAndSymmetricMatrixWhenResultMatrixGiven(int order)
{ {
var matrixA = Matrix<float>.Build.RandomPositiveDefinite(order, 1); var A = Matrix<float>.Build.RandomPositiveDefinite(order, 1);
MatrixHelpers.ForceSymmetric(matrixA); MatrixHelpers.ForceSymmetric(A);
var matrixACopy = matrixA.Clone(); var ACopy = A.Clone();
var factorEvd = matrixA.Evd(); var evd = A.Evd();
var matrixB = Matrix<float>.Build.Random(order, order, 1); var B = Matrix<float>.Build.Random(order, order, 2);
var matrixBCopy = matrixB.Clone(); var BCopy = B.Clone();
var matrixX = new DenseMatrix(order, order); var X = new DenseMatrix(order, order);
factorEvd.Solve(matrixB, matrixX); evd.Solve(B, X);
// The solution X row dimension is equal to the column dimension of A // The solution X row dimension is equal to the column dimension of A
Assert.AreEqual(matrixA.ColumnCount, matrixX.RowCount); Assert.AreEqual(A.ColumnCount, X.RowCount);
// The solution X has the same number of columns as B // The solution X has the same number of columns as B
Assert.AreEqual(matrixB.ColumnCount, matrixX.ColumnCount); Assert.AreEqual(B.ColumnCount, X.ColumnCount);
var matrixBReconstruct = matrixA * matrixX; var BReconstruct = A * X;
// Check the reconstruction. // Check the reconstruction.
for (var i = 0; i < matrixB.RowCount; i++) AssertHelpers.AlmostEqual(B, BReconstruct, 0);
{
for (var j = 0; j < matrixB.ColumnCount; j++)
{
Assert.AreEqual(matrixB[i, j], matrixBReconstruct[i, j], 1);
}
}
// 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]);
}
}
// Make sure B didn't change. // Make sure A/B didn't change.
for (var i = 0; i < matrixB.RowCount; i++) AssertHelpers.AlmostEqual(ACopy, A, 14);
{ AssertHelpers.AlmostEqual(BCopy, B, 14);
for (var j = 0; j < matrixB.ColumnCount; j++)
{
Assert.AreEqual(matrixBCopy[i, j], matrixB[i, j]);
}
}
} }
} }
} }

195
src/UnitTests/LinearAlgebraTests/Single/Factorization/UserEvdTests.cs

@ -193,187 +193,122 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Single.Factorization
/// Can solve a system of linear equations for a random vector and symmetric matrix (Ax=b). /// Can solve a system of linear equations for a random vector and symmetric matrix (Ax=b).
/// </summary> /// </summary>
/// <param name="order">Matrix order.</param> /// <param name="order">Matrix order.</param>
[TestCase(1)] [Test]
[TestCase(2)] public void CanSolveForRandomVectorAndSymmetricMatrix([Values(1, 2, 5, 10, 50, 100)] int order)
[TestCase(5)]
[TestCase(10)]
[TestCase(50)]
[TestCase(100)]
public void CanSolveForRandomVectorAndSymmetricMatrix(int order)
{ {
var matrixA = new UserDefinedMatrix(Matrix<float>.Build.RandomPositiveDefinite(order, 1).ToArray()); var A = new UserDefinedMatrix(Matrix<float>.Build.RandomPositiveDefinite(order, 1).ToArray());
var matrixACopy = matrixA.Clone(); MatrixHelpers.ForceSymmetric(A);
var factorEvd = matrixA.Evd(); var ACopy = A.Clone();
var evd = A.Evd();
var vectorb = new UserDefinedVector(Vector<float>.Build.Random(order, 1).ToArray()); var b = new UserDefinedVector(Vector<float>.Build.Random(order, 1).ToArray());
var resultx = factorEvd.Solve(vectorb); var bCopy = b.Clone();
Assert.AreEqual(matrixA.ColumnCount, resultx.Count); var x = evd.Solve(b);
var matrixBReconstruct = matrixA * resultx; var bReconstruct = A * x;
// Check the reconstruction. // Check the reconstruction.
for (var i = 0; i < vectorb.Count; i++) AssertHelpers.AlmostEqual(b, bReconstruct, 0);
{
Assert.AreEqual(vectorb[i], matrixBReconstruct[i], 1e-1);
}
// Make sure A didn't change. // Make sure A/B didn't change.
for (var i = 0; i < matrixA.RowCount; i++) AssertHelpers.AlmostEqual(ACopy, A, 14);
{ AssertHelpers.AlmostEqual(bCopy, b, 14);
for (var j = 0; j < matrixA.ColumnCount; j++)
{
Assert.AreEqual(matrixACopy[i, j], matrixA[i, j]);
}
}
} }
/// <summary> /// <summary>
/// Can solve a system of linear equations for a random matrix and symmetric matrix (AX=B). /// Can solve a system of linear equations for a random matrix and symmetric matrix (AX=B).
/// </summary> /// </summary>
/// <param name="order">Matrix order.</param> /// <param name="order">Matrix order.</param>
[TestCase(1)] [Test]
[TestCase(2)] public void CanSolveForRandomMatrixAndSymmetricMatrix([Values(1, 2, 5, 10, 50, 100)] int order)
[TestCase(5)]
[TestCase(10)]
[TestCase(50)]
[TestCase(100)]
public void CanSolveForRandomMatrixAndSymmetricMatrix(int order)
{ {
var matrixA = new UserDefinedMatrix(Matrix<float>.Build.RandomPositiveDefinite(order, 1).ToArray()); var A = new UserDefinedMatrix(Matrix<float>.Build.RandomPositiveDefinite(order, 1).ToArray());
var matrixACopy = matrixA.Clone(); MatrixHelpers.ForceSymmetric(A);
var factorEvd = matrixA.Evd(); var ACopy = A.Clone();
var evd = A.Evd();
var B = new UserDefinedMatrix(Matrix<float>.Build.Random(order, order, 1).ToArray());
var BCopy = B.Clone();
var matrixB = new UserDefinedMatrix(Matrix<float>.Build.Random(order, order, 1).ToArray()); var X = evd.Solve(B);
var matrixX = factorEvd.Solve(matrixB);
// The solution X row dimension is equal to the column dimension of A // The solution X row dimension is equal to the column dimension of A
Assert.AreEqual(matrixA.ColumnCount, matrixX.RowCount); Assert.AreEqual(A.ColumnCount, X.RowCount);
// The solution X has the same number of columns as B // The solution X has the same number of columns as B
Assert.AreEqual(matrixB.ColumnCount, matrixX.ColumnCount); Assert.AreEqual(B.ColumnCount, X.ColumnCount);
var matrixBReconstruct = matrixA * matrixX; var BReconstruct = A * X;
// Check the reconstruction. // Check the reconstruction.
for (var i = 0; i < matrixB.RowCount; i++) AssertHelpers.AlmostEqual(B, BReconstruct, 0);
{
for (var j = 0; j < matrixB.ColumnCount; j++)
{
Assert.AreEqual(matrixB[i, j], matrixBReconstruct[i, j], 1);
}
}
// Make sure A didn't change. // Make sure A/B didn't change.
for (var i = 0; i < matrixA.RowCount; i++) AssertHelpers.AlmostEqual(ACopy, A, 14);
{ AssertHelpers.AlmostEqual(BCopy, B, 14);
for (var j = 0; j < matrixA.ColumnCount; j++)
{
Assert.AreEqual(matrixACopy[i, j], matrixA[i, j]);
}
}
} }
/// <summary> /// <summary>
/// Can solve a system of linear equations for a random vector and symmetric matrix (Ax=b) into a result matrix. /// Can solve a system of linear equations for a random vector and symmetric matrix (Ax=b) into a result matrix.
/// </summary> /// </summary>
/// <param name="order">Matrix order.</param> /// <param name="order">Matrix order.</param>
[TestCase(1)] [Test]
[TestCase(2)] public void CanSolveForRandomVectorAndSymmetricMatrixWhenResultVectorGiven([Values(1, 2, 5, 10, 50, 100)] int order)
[TestCase(5)]
[TestCase(10)]
[TestCase(50)]
[TestCase(100)]
public void CanSolveForRandomVectorAndSymmetricMatrixWhenResultVectorGiven(int order)
{ {
var matrixA = new UserDefinedMatrix(Matrix<float>.Build.RandomPositiveDefinite(order, 1).ToArray()); var A = new UserDefinedMatrix(Matrix<float>.Build.RandomPositiveDefinite(order, 1).ToArray());
var matrixACopy = matrixA.Clone(); MatrixHelpers.ForceSymmetric(A);
var factorEvd = matrixA.Evd(); var ACopy = A.Clone();
var vectorb = new UserDefinedVector(Vector<float>.Build.Random(order, 1).ToArray()); var evd = A.Evd();
var vectorbCopy = vectorb.Clone();
var resultx = new UserDefinedVector(order);
factorEvd.Solve(vectorb, resultx);
var matrixBReconstruct = matrixA * resultx; var b = new UserDefinedVector(Vector<float>.Build.Random(order, 1).ToArray());
var bCopy = b.Clone();
// Check the reconstruction. var x = new UserDefinedVector(order);
for (var i = 0; i < vectorb.Count; i++) evd.Solve(b, x);
{
Assert.AreEqual(vectorb[i], matrixBReconstruct[i], 1e-1);
}
// Make sure A didn't change. var bReconstruct = A * x;
for (var i = 0; i < matrixA.RowCount; i++)
{
for (var j = 0; j < matrixA.ColumnCount; j++)
{
Assert.AreEqual(matrixACopy[i, j], matrixA[i, j]);
}
}
// Make sure b didn't change. // Check the reconstruction.
for (var i = 0; i < vectorb.Count; i++) AssertHelpers.AlmostEqual(b, bReconstruct, 0);
{
Assert.AreEqual(vectorbCopy[i], vectorb[i]); // Make sure A/B didn't change.
} AssertHelpers.AlmostEqual(ACopy, A, 14);
AssertHelpers.AlmostEqual(bCopy, b, 14);
} }
/// <summary> /// <summary>
/// Can solve a system of linear equations for a random matrix and symmetric matrix (AX=B) into result matrix. /// Can solve a system of linear equations for a random matrix and symmetric matrix (AX=B) into result matrix.
/// </summary> /// </summary>
/// <param name="order">Matrix order.</param> /// <param name="order">Matrix order.</param>
[TestCase(1)] [Test]
[TestCase(2)] public void CanSolveForRandomMatrixAndSymmetricMatrixWhenResultMatrixGiven([Values(1, 2, 5, 10, 50, 100)] int order)
[TestCase(5)]
[TestCase(10)]
[TestCase(50)]
[TestCase(100)]
public void CanSolveForRandomMatrixAndSymmetricMatrixWhenResultMatrixGiven(int order)
{ {
var matrixA = new UserDefinedMatrix(Matrix<float>.Build.RandomPositiveDefinite(order, 1).ToArray()); var A = new UserDefinedMatrix(Matrix<float>.Build.RandomPositiveDefinite(order, 1).ToArray());
var matrixACopy = matrixA.Clone(); MatrixHelpers.ForceSymmetric(A);
var factorEvd = matrixA.Evd(); var ACopy = A.Clone();
var evd = A.Evd();
var matrixB = new UserDefinedMatrix(Matrix<float>.Build.Random(order, order, 1).ToArray()); var B = new UserDefinedMatrix(Matrix<float>.Build.Random(order, order, 1).ToArray());
var matrixBCopy = matrixB.Clone(); var BCopy = B.Clone();
var matrixX = new UserDefinedMatrix(order, order); var X = new UserDefinedMatrix(order, order);
factorEvd.Solve(matrixB, matrixX); evd.Solve(B, X);
// The solution X row dimension is equal to the column dimension of A // The solution X row dimension is equal to the column dimension of A
Assert.AreEqual(matrixA.ColumnCount, matrixX.RowCount); Assert.AreEqual(A.ColumnCount, X.RowCount);
// The solution X has the same number of columns as B // The solution X has the same number of columns as B
Assert.AreEqual(matrixB.ColumnCount, matrixX.ColumnCount); Assert.AreEqual(B.ColumnCount, X.ColumnCount);
var matrixBReconstruct = matrixA * matrixX; var BReconstruct = A * X;
// Check the reconstruction. // Check the reconstruction.
for (var i = 0; i < matrixB.RowCount; i++) AssertHelpers.AlmostEqual(B, BReconstruct, 0);
{
for (var j = 0; j < matrixB.ColumnCount; j++)
{
Assert.AreEqual(matrixB[i, j], matrixBReconstruct[i, j], 1);
}
}
// Make sure A didn't change. // Make sure A/B didn't change.
for (var i = 0; i < matrixA.RowCount; i++) AssertHelpers.AlmostEqual(ACopy, A, 14);
{ AssertHelpers.AlmostEqual(BCopy, B, 14);
for (var j = 0; j < matrixA.ColumnCount; j++)
{
Assert.AreEqual(matrixACopy[i, j], matrixA[i, j]);
}
}
// Make sure B didn't change.
for (var i = 0; i < matrixB.RowCount; i++)
{
for (var j = 0; j < matrixB.ColumnCount; j++)
{
Assert.AreEqual(matrixBCopy[i, j], matrixB[i, j]);
}
}
} }
} }
} }

Loading…
Cancel
Save