Browse Source

LA: Matrix.IsSymmetric now a method; added IsConjugateSymmetric; more efficient #209

pull/222/head
Christoph Ruegg 12 years ago
parent
commit
2e787ddafb
  1. 50
      src/Numerics/LinearAlgebra/Complex/DenseMatrix.cs
  2. 17
      src/Numerics/LinearAlgebra/Complex/DiagonalMatrix.cs
  3. 24
      src/Numerics/LinearAlgebra/Complex/Matrix.cs
  4. 75
      src/Numerics/LinearAlgebra/Complex/SparseMatrix.cs
  5. 50
      src/Numerics/LinearAlgebra/Complex32/DenseMatrix.cs
  6. 17
      src/Numerics/LinearAlgebra/Complex32/DiagonalMatrix.cs
  7. 24
      src/Numerics/LinearAlgebra/Complex32/Matrix.cs
  8. 75
      src/Numerics/LinearAlgebra/Complex32/SparseMatrix.cs
  9. 25
      src/Numerics/LinearAlgebra/Double/DenseMatrix.cs
  10. 9
      src/Numerics/LinearAlgebra/Double/DiagonalMatrix.cs
  11. 8
      src/Numerics/LinearAlgebra/Double/Matrix.cs
  12. 62
      src/Numerics/LinearAlgebra/Double/SparseMatrix.cs
  13. 32
      src/Numerics/LinearAlgebra/Matrix.cs
  14. 25
      src/Numerics/LinearAlgebra/Single/DenseMatrix.cs
  15. 9
      src/Numerics/LinearAlgebra/Single/DiagonalMatrix.cs
  16. 8
      src/Numerics/LinearAlgebra/Single/Matrix.cs
  17. 64
      src/Numerics/LinearAlgebra/Single/SparseMatrix.cs
  18. 2
      src/UnitTests/LinearAlgebraTests/Complex/DiagonalMatrixTests.cs
  19. 4
      src/UnitTests/LinearAlgebraTests/Complex/MatrixTests.cs
  20. 2
      src/UnitTests/LinearAlgebraTests/Complex32/DiagonalMatrixTests.cs
  21. 4
      src/UnitTests/LinearAlgebraTests/Complex32/MatrixTests.cs
  22. 2
      src/UnitTests/LinearAlgebraTests/Double/DiagonalMatrixTests.cs
  23. 4
      src/UnitTests/LinearAlgebraTests/Double/MatrixTests.cs
  24. 2
      src/UnitTests/LinearAlgebraTests/Single/DiagonalMatrixTests.cs
  25. 4
      src/UnitTests/LinearAlgebraTests/Single/MatrixTests.cs

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

@ -1228,6 +1228,56 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
return (DenseMatrix)leftSide.Remainder(rightSide);
}
/// <summary>
/// Evaluates whether this matrix is symmetric.
/// </summary>
public override bool IsSymmetric()
{
if (RowCount != ColumnCount)
{
return false;
}
for (var j = 0; j < ColumnCount; j++)
{
var index = j * RowCount;
for (var i = j + 1; i < RowCount; i++)
{
if (_values[(i*ColumnCount) + j] != _values[index + i])
{
return false;
}
}
}
return true;
}
/// <summary>
/// Evaluates whether this matrix is conjugate symmetric.
/// </summary>
public override bool IsConjugateSymmetric()
{
if (RowCount != ColumnCount)
{
return false;
}
for (var j = 0; j < ColumnCount; j++)
{
var index = j * RowCount;
for (var i = j + 1; i < RowCount; i++)
{
if (_values[(i*ColumnCount) + j] != _values[index + i].Conjugate())
{
return false;
}
}
}
return true;
}
public override Cholesky<Complex> Cholesky()
{
return DenseCholesky.Create(this);

17
src/Numerics/LinearAlgebra/Complex/DiagonalMatrix.cs

@ -955,14 +955,19 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
}
/// <summary>
/// Gets a value indicating whether this matrix is symmetric.
/// Evaluates whether this matrix is symmetric.
/// </summary>
public override bool IsSymmetric
public override sealed bool IsSymmetric()
{
get
{
return true;
}
return true;
}
/// <summary>
/// Evaluates whether this matrix is conjugate symmetric.
/// </summary>
public override sealed bool IsConjugateSymmetric()
{
return true;
}
}
}

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

@ -661,6 +661,30 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
return sum;
}
/// <summary>
/// Evaluates whether this matrix is conjugate symmetric.
/// </summary>
public override bool IsConjugateSymmetric()
{
if (RowCount != ColumnCount)
{
return false;
}
for (var row = 0; row < RowCount; row++)
{
for (var column = row + 1; column < ColumnCount; column++)
{
if (!At(row, column).Equals(At(column, row).Conjugate()))
{
return false;
}
}
}
return true;
}
public override Cholesky<Complex> Cholesky()
{
return UserCholesky.Create(this);

75
src/Numerics/LinearAlgebra/Complex/SparseMatrix.cs

@ -1209,58 +1209,73 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
}
/// <summary>
/// Gets a value indicating whether this matrix is symmetric.
/// Evaluates whether this matrix is symmetric.
/// </summary>
public override bool IsSymmetric
public override bool IsSymmetric()
{
get
if (RowCount != ColumnCount)
{
if (RowCount != ColumnCount)
return false;
}
var rowPointers = _storage.RowPointers;
var columnIndices = _storage.ColumnIndices;
var values = _storage.Values;
for (var row = 0; row < RowCount; row++)
{
var start = rowPointers[row];
var end = rowPointers[row + 1];
if (start == end)
{
return false;
continue;
}
// todo: we might be able to speed this up by caching one half of the matrix
var rowPointers = _storage.RowPointers;
for (var row = 0; row < RowCount; row++)
for (var index = start; index < end; index++)
{
var start = rowPointers[row];
var end = rowPointers[row + 1];
if (start == end)
{
continue;
}
if (!CheckIfOppositesAreEqual(start, end, row))
var column = columnIndices[index];
if (!values[index].Equals(At(column, row)))
{
return false;
}
}
return true;
}
return true;
}
/// <summary>
/// Checks if opposites in a range are equal.
/// Evaluates whether this matrix is conjugate symmetric.
/// </summary>
/// <param name="start">The start of the range.</param>
/// <param name="end">The end of the range.</param>
/// <param name="row">The row the row to check.</param>
/// <returns>If the values are equal or not.</returns>
private bool CheckIfOppositesAreEqual(int start, int end, int row)
public override bool IsConjugateSymmetric()
{
if (RowCount != ColumnCount)
{
return false;
}
var rowPointers = _storage.RowPointers;
var columnIndices = _storage.ColumnIndices;
var values = _storage.Values;
for (var index = start; index < end; index++)
for (var row = 0; row < RowCount; row++)
{
var column = columnIndices[index];
var opposite = At(column, row);
if (!values[index].Equals(opposite))
var start = rowPointers[row];
var end = rowPointers[row + 1];
if (start == end)
{
return false;
continue;
}
for (var index = start; index < end; index++)
{
var column = columnIndices[index];
if (!values[index].Equals(At(column, row).Conjugate()))
{
return false;
}
}
}

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

@ -1225,6 +1225,56 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
return (DenseMatrix)leftSide.Remainder(rightSide);
}
/// <summary>
/// Evaluates whether this matrix is symmetric.
/// </summary>
public override bool IsSymmetric()
{
if (RowCount != ColumnCount)
{
return false;
}
for (var j = 0; j < ColumnCount; j++)
{
var index = j * RowCount;
for (var i = j + 1; i < RowCount; i++)
{
if (_values[(i*ColumnCount) + j] != _values[index + i])
{
return false;
}
}
}
return true;
}
/// <summary>
/// Evaluates whether this matrix is conjugate symmetric.
/// </summary>
public override bool IsConjugateSymmetric()
{
if (RowCount != ColumnCount)
{
return false;
}
for (var j = 0; j < ColumnCount; j++)
{
var index = j * RowCount;
for (var i = j + 1; i < RowCount; i++)
{
if (_values[(i*ColumnCount) + j] != _values[index + i].Conjugate())
{
return false;
}
}
}
return true;
}
public override Cholesky<Complex32> Cholesky()
{
return DenseCholesky.Create(this);

17
src/Numerics/LinearAlgebra/Complex32/DiagonalMatrix.cs

@ -949,14 +949,19 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
}
/// <summary>
/// Gets a value indicating whether this matrix is symmetric.
/// Evaluates whether this matrix is symmetric.
/// </summary>
public override bool IsSymmetric
public override sealed bool IsSymmetric()
{
get
{
return true;
}
return true;
}
/// <summary>
/// Evaluates whether this matrix is conjugate symmetric.
/// </summary>
public override sealed bool IsConjugateSymmetric()
{
return true;
}
}
}

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

@ -655,6 +655,30 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
return sum;
}
/// <summary>
/// Evaluates whether this matrix is conjugate symmetric.
/// </summary>
public override bool IsConjugateSymmetric()
{
if (RowCount != ColumnCount)
{
return false;
}
for (var row = 0; row < RowCount; row++)
{
for (var column = row + 1; column < ColumnCount; column++)
{
if (!At(row, column).Equals(At(column, row).Conjugate()))
{
return false;
}
}
}
return true;
}
public override Cholesky<Complex32> Cholesky()
{
return UserCholesky.Create(this);

75
src/Numerics/LinearAlgebra/Complex32/SparseMatrix.cs

@ -1203,58 +1203,73 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
}
/// <summary>
/// Gets a value indicating whether this matrix is symmetric.
/// Evaluates whether this matrix is symmetric.
/// </summary>
public override bool IsSymmetric
public override bool IsSymmetric()
{
get
if (RowCount != ColumnCount)
{
if (RowCount != ColumnCount)
return false;
}
var rowPointers = _storage.RowPointers;
var columnIndices = _storage.ColumnIndices;
var values = _storage.Values;
for (var row = 0; row < RowCount; row++)
{
var start = rowPointers[row];
var end = rowPointers[row + 1];
if (start == end)
{
return false;
continue;
}
// todo: we might be able to speed this up by caching one half of the matrix
var rowPointers = _storage.RowPointers;
for (var row = 0; row < RowCount; row++)
for (var index = start; index < end; index++)
{
var start = rowPointers[row];
var end = rowPointers[row + 1];
if (start == end)
{
continue;
}
if (!CheckIfOppositesAreEqual(start, end, row))
var column = columnIndices[index];
if (!values[index].Equals(At(column, row)))
{
return false;
}
}
return true;
}
return true;
}
/// <summary>
/// Checks if opposites in a range are equal.
/// Evaluates whether this matrix is conjugate symmetric.
/// </summary>
/// <param name="start">The start of the range.</param>
/// <param name="end">The end of the range.</param>
/// <param name="row">The row the row to check.</param>
/// <returns>If the values are equal or not.</returns>
private bool CheckIfOppositesAreEqual(int start, int end, int row)
public override bool IsConjugateSymmetric()
{
if (RowCount != ColumnCount)
{
return false;
}
var rowPointers = _storage.RowPointers;
var columnIndices = _storage.ColumnIndices;
var values = _storage.Values;
for (var index = start; index < end; index++)
for (var row = 0; row < RowCount; row++)
{
var column = columnIndices[index];
var opposite = At(column, row);
if (!values[index].Equals(opposite))
var start = rowPointers[row];
var end = rowPointers[row + 1];
if (start == end)
{
return false;
continue;
}
for (var index = start; index < end; index++)
{
var column = columnIndices[index];
if (!values[index].Equals(At(column, row).Conjugate()))
{
return false;
}
}
}

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

@ -1180,6 +1180,31 @@ namespace MathNet.Numerics.LinearAlgebra.Double
return (DenseMatrix)leftSide.Remainder(rightSide);
}
/// <summary>
/// Evaluates whether this matrix is symmetric.
/// </summary>
public override bool IsSymmetric()
{
if (RowCount != ColumnCount)
{
return false;
}
for (var j = 0; j < ColumnCount; j++)
{
var index = j * RowCount;
for (var i = j + 1; i < RowCount; i++)
{
if (_values[(i*ColumnCount) + j] != _values[index + i])
{
return false;
}
}
}
return true;
}
public override Cholesky<double> Cholesky()
{
return DenseCholesky.Create(this);

9
src/Numerics/LinearAlgebra/Double/DiagonalMatrix.cs

@ -799,14 +799,11 @@ namespace MathNet.Numerics.LinearAlgebra.Double
}
/// <summary>
/// Gets a value indicating whether this matrix is symmetric.
/// Evaluates whether this matrix is symmetric.
/// </summary>
public override bool IsSymmetric
public override sealed bool IsSymmetric()
{
get
{
return true;
}
return true;
}
/// <summary>

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

@ -656,6 +656,14 @@ namespace MathNet.Numerics.LinearAlgebra.Double
return sum;
}
/// <summary>
/// Evaluates whether this matrix is conjugate symmetric.
/// </summary>
public override sealed bool IsConjugateSymmetric()
{
return IsSymmetric();
}
public override Cholesky<double> Cholesky()
{
return UserCholesky.Create(this);

62
src/Numerics/LinearAlgebra/Double/SparseMatrix.cs

@ -1256,58 +1256,36 @@ namespace MathNet.Numerics.LinearAlgebra.Double
}
/// <summary>
/// Gets a value indicating whether this matrix is symmetric.
/// Evaluates whether this matrix is symmetric.
/// </summary>
public override bool IsSymmetric
public override bool IsSymmetric()
{
get
if (RowCount != ColumnCount)
{
if (RowCount != ColumnCount)
{
return false;
}
// todo: we might be able to speed this up by caching one half of the matrix
var rowPointers = _storage.RowPointers;
for (var row = 0; row < RowCount; row++)
{
var start = rowPointers[row];
var end = rowPointers[row + 1];
if (start == end)
{
continue;
}
if (!CheckIfOppositesAreEqual(start, end, row))
{
return false;
}
}
return true;
return false;
}
}
/// <summary>
/// Checks if opposites in a range are equal.
/// </summary>
/// <param name="start">The start of the range.</param>
/// <param name="end">The end of the range.</param>
/// <param name="row">The row the row to check.</param>
/// <returns>If the values are equal or not.</returns>
private bool CheckIfOppositesAreEqual(int start, int end, int row)
{
var rowPointers = _storage.RowPointers;
var columnIndices = _storage.ColumnIndices;
var values = _storage.Values;
for (var index = start; index < end; index++)
for (var row = 0; row < RowCount; row++)
{
var column = columnIndices[index];
var opposite = At(column, row);
if (!values[index].Equals(opposite))
var start = rowPointers[row];
var end = rowPointers[row + 1];
if (start == end)
{
continue;
}
for (var index = start; index < end; index++)
{
return false;
var column = columnIndices[index];
if (!values[index].Equals(At(column, row)))
{
return false;
}
}
}

32
src/Numerics/LinearAlgebra/Matrix.cs

@ -1268,32 +1268,34 @@ namespace MathNet.Numerics.LinearAlgebra
}
/// <summary>
/// Gets a value indicating whether this matrix is symmetric.
/// Evaluates whether this matrix is symmetric.
/// </summary>
public virtual bool IsSymmetric
public virtual bool IsSymmetric()
{
get
if (RowCount != ColumnCount)
{
if (RowCount != ColumnCount)
{
return false;
}
return false;
}
for (var row = 0; row < RowCount; row++)
for (var row = 0; row < RowCount; row++)
{
for (var column = row + 1; column < ColumnCount; column++)
{
for (var column = row + 1; column < ColumnCount; column++)
if (!At(row, column).Equals(At(column, row)))
{
if (!At(row, column).Equals(At(column, row)))
{
return false;
}
return false;
}
}
return true;
}
return true;
}
/// <summary>
/// Evaluates whether this matrix is conjugate symmetric.
/// </summary>
public abstract bool IsConjugateSymmetric();
/// <summary>
/// Returns this matrix as a multidimensional array.
/// </summary>

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

@ -1180,6 +1180,31 @@ namespace MathNet.Numerics.LinearAlgebra.Single
return (DenseMatrix)leftSide.Remainder(rightSide);
}
/// <summary>
/// Evaluates whether this matrix is symmetric.
/// </summary>
public override bool IsSymmetric()
{
if (RowCount != ColumnCount)
{
return false;
}
for (var j = 0; j < ColumnCount; j++)
{
var index = j * RowCount;
for (var i = j + 1; i < RowCount; i++)
{
if (_values[(i*ColumnCount) + j] != _values[index + i])
{
return false;
}
}
}
return true;
}
public override Cholesky<float> Cholesky()
{
return DenseCholesky.Create(this);

9
src/Numerics/LinearAlgebra/Single/DiagonalMatrix.cs

@ -799,14 +799,11 @@ namespace MathNet.Numerics.LinearAlgebra.Single
}
/// <summary>
/// Gets a value indicating whether this matrix is symmetric.
/// Evaluates whether this matrix is symmetric.
/// </summary>
public override bool IsSymmetric
public override sealed bool IsSymmetric()
{
get
{
return true;
}
return true;
}
/// <summary>

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

@ -656,6 +656,14 @@ namespace MathNet.Numerics.LinearAlgebra.Single
return sum;
}
/// <summary>
/// Evaluates whether this matrix is conjugate symmetric.
/// </summary>
public override sealed bool IsConjugateSymmetric()
{
return IsSymmetric();
}
public override Cholesky<float> Cholesky()
{
return UserCholesky.Create(this);

64
src/Numerics/LinearAlgebra/Single/SparseMatrix.cs

@ -1261,58 +1261,38 @@ namespace MathNet.Numerics.LinearAlgebra.Single
}
/// <summary>
/// Gets a value indicating whether this matrix is symmetric.
/// Evaluates whether this matrix is symmetric.
/// </summary>
public override bool IsSymmetric
public override bool IsSymmetric()
{
get
if (RowCount != ColumnCount)
{
if (RowCount != ColumnCount)
{
return false;
}
// todo: we might be able to speed this up by caching one half of the matrix
var rowPointers = _storage.RowPointers;
for (var row = 0; row < RowCount; row++)
{
var start = rowPointers[row];
var end = rowPointers[row + 1];
if (start == end)
{
continue;
}
if (!CheckIfOppositesAreEqual(start, end, row))
{
return false;
}
}
return true;
return false;
}
}
/// <summary>
/// Checks if opposites in a range are equal.
/// </summary>
/// <param name="start">The start of the range.</param>
/// <param name="end">The end of the range.</param>
/// <param name="row">The row the row to check.</param>
/// <returns>If the values are equal or not.</returns>
private bool CheckIfOppositesAreEqual(int start, int end, int row)
{
// todo: we might be able to speed this up by caching one half of the matrix
var rowPointers = _storage.RowPointers;
var columnIndices = _storage.ColumnIndices;
var values = _storage.Values;
for (var index = start; index < end; index++)
for (var row = 0; row < RowCount; row++)
{
var column = columnIndices[index];
var opposite = At(column, row);
if (!values[index].Equals(opposite))
var start = rowPointers[row];
var end = rowPointers[row + 1];
if (start == end)
{
continue;
}
for (var index = start; index < end; index++)
{
return false;
var column = columnIndices[index];
var opposite = At(column, row);
if (!values[index].Equals(opposite))
{
return false;
}
}
}

2
src/UnitTests/LinearAlgebraTests/Complex/DiagonalMatrixTests.cs

@ -362,7 +362,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex
public override void CanCheckIfMatrixIsSymmetric()
{
var matrix = TestMatrices["Square3x3"];
Assert.IsTrue(matrix.IsSymmetric);
Assert.IsTrue(matrix.IsSymmetric());
}
[Test]

4
src/UnitTests/LinearAlgebraTests/Complex/MatrixTests.cs

@ -156,10 +156,10 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex
public virtual void CanCheckIfMatrixIsSymmetric()
{
var matrix = TestMatrices["Symmetric3x3"];
Assert.IsTrue(matrix.IsSymmetric);
Assert.IsTrue(matrix.IsSymmetric());
matrix = TestMatrices["Square3x3"];
Assert.IsFalse(matrix.IsSymmetric);
Assert.IsFalse(matrix.IsSymmetric());
}
}
}

2
src/UnitTests/LinearAlgebraTests/Complex32/DiagonalMatrixTests.cs

@ -358,7 +358,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex32
public override void CanCheckIfMatrixIsSymmetric()
{
var matrix = TestMatrices["Square3x3"];
Assert.IsTrue(matrix.IsSymmetric);
Assert.IsTrue(matrix.IsSymmetric());
}
[Test]

4
src/UnitTests/LinearAlgebraTests/Complex32/MatrixTests.cs

@ -156,10 +156,10 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex32
public virtual void CanCheckIfMatrixIsSymmetric()
{
var matrix = TestMatrices["Symmetric3x3"];
Assert.IsTrue(matrix.IsSymmetric);
Assert.IsTrue(matrix.IsSymmetric());
matrix = TestMatrices["Square3x3"];
Assert.IsFalse(matrix.IsSymmetric);
Assert.IsFalse(matrix.IsSymmetric());
}
}
}

2
src/UnitTests/LinearAlgebraTests/Double/DiagonalMatrixTests.cs

@ -357,7 +357,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double
public override void CanCheckIfMatrixIsSymmetric()
{
var matrix = TestMatrices["Square3x3"];
Assert.IsTrue(matrix.IsSymmetric);
Assert.IsTrue(matrix.IsSymmetric());
}
[Test]

4
src/UnitTests/LinearAlgebraTests/Double/MatrixTests.cs

@ -129,10 +129,10 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double
public virtual void CanCheckIfMatrixIsSymmetric()
{
var matrix = TestMatrices["Symmetric3x3"];
Assert.IsTrue(matrix.IsSymmetric);
Assert.IsTrue(matrix.IsSymmetric());
matrix = TestMatrices["Square3x3"];
Assert.IsFalse(matrix.IsSymmetric);
Assert.IsFalse(matrix.IsSymmetric());
}
}
}

2
src/UnitTests/LinearAlgebraTests/Single/DiagonalMatrixTests.cs

@ -356,7 +356,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Single
public override void CanCheckIfMatrixIsSymmetric()
{
var matrix = TestMatrices["Square3x3"];
Assert.IsTrue(matrix.IsSymmetric);
Assert.IsTrue(matrix.IsSymmetric());
}
[Test]

4
src/UnitTests/LinearAlgebraTests/Single/MatrixTests.cs

@ -129,10 +129,10 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Single
public virtual void CanCheckIfMatrixIsSymmetric()
{
var matrix = TestMatrices["Symmetric3x3"];
Assert.IsTrue(matrix.IsSymmetric);
Assert.IsTrue(matrix.IsSymmetric());
matrix = TestMatrices["Square3x3"];
Assert.IsFalse(matrix.IsSymmetric);
Assert.IsFalse(matrix.IsSymmetric());
}
}
}

Loading…
Cancel
Save