mathnet / mathnet-numerics

Math.NET Numerics
http://numerics.mathdotnet.com
MIT License
3.48k stars 894 forks source link

matrix<double> operator == performs false on identical matrices #1089

Open Anatom70 opened 1 month ago

Anatom70 commented 1 month ago

I create an int random symmetrical matrix and calculate the transposed matrix, which should be identical. The matrix == operator compiles, but performs false on comparison, An extended method, which compares the matrices element by element performs true

jkalias commented 4 days ago

Can you please provide a code snippet which demonstrates this behavior?

Anatom70 commented 4 days ago

Hello!

The issue occurs with 12x12 matrices filled with random numbers[-100,100] and is not reproducible.

I build a symmetrical matrix, transpose it and compare it with the original.

The behavior disappears when I check for deviations > 1E-10 overriding the == operator.

Regards, Thomas

Von: jkalias @.> Gesendet: Samstag, 28. September 2024 13:21 An: mathnet/mathnet-numerics @.> Cc: Anatom70 @.>; Author @.> Betreff: Re: [mathnet/mathnet-numerics] matrix operator == performs false on identical matrices (Issue #1089)

Can you please provide a code snippet which demonstrates this behavior?

— Reply to this email directly, view it on GitHub https://github.com/mathnet/mathnet-numerics/issues/1089#issuecomment-2380607294 , or unsubscribe https://github.com/notifications/unsubscribe-auth/BKT7QJ2FP32PUGT23AD5OYDZY2GJFAVCNFSM6AAAAABMXODXA2VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDGOBQGYYDOMRZGQ . You are receiving this because you authored the thread. https://github.com/notifications/beacon/BKT7QJ7VDWRGWUMHPLRIOULZY2GJFA5CNFSM6AAAAABMXODXA2WGG33NNVSW45C7OR4XAZNMJFZXG5LFINXW23LFNZ2KUY3PNVWWK3TUL5UWJTUN4UXT4.gif Message ID: @. @.> >

jkalias commented 4 days ago

What do you mean it's not reproducible? Can you provide a code snippet for this 12x12 matrix? Or at bare minimum print out the matrix for which this happens, otherwise the bug can't be fixed.

Anatom70 commented 4 days ago

Name

Wert

Typ

$exception

{"Fehler bei \"Assert.IsTrue\". "}

Microsoft.VisualStudio.TestTools.UnitTesting.AssertFailedException

this

{UnitTest1.UnitTest_Quadratical_Matrices}

UnitTest1.UnitTest_Quadratical_Matrices

matrixDimension

30

int

◢ randomGeneratorDimension

{RiosEngineering.Mathematics.Statistics.RandomGenerator}

RiosEngineering.Mathematics.Statistics.RandomGenerator

▶ csp

{System.Security.Cryptography.RNGCryptoServiceProvider}

System.Security.Cryptography.RNGCryptoServiceProvider

▶ range

{int[2]}

int[]

▶ Statische Member

i

0

int

symmetricMatrix

{RiosEngineering.Mathematics.LinearAlgebra.MatrixGenerator}

RiosEngineering.Mathematics.LinearAlgebra.MatrixGenerator

▶ Matrix

DenseMatrix 30x30-Double

MathNet.Numerics.LinearAlgebra.Matrix {MathNet.Numerics.LinearAlgebra.Double.DenseMatrix}

▶ randomGenerator

{RiosEngineering.Mathematics.Statistics.RandomGenerator}

RiosEngineering.Mathematics.Statistics.RandomGenerator

eigen

{MathNet.Numerics.LinearAlgebra.Double.Factorization.DenseEvd}

MathNet.Numerics.LinearAlgebra.Factorization.Evd {MathNet.Numerics.LinearAlgebra.Double.Factorization.DenseEvd}

▶ D

DenseMatrix 30x30-Double

MathNet.Numerics.LinearAlgebra.Matrix {MathNet.Numerics.LinearAlgebra.Double.DenseMatrix}

Determinant

1.0072948434831587E+69

double

▶ EigenValues

DenseVector 30-Complex

MathNet.Numerics.LinearAlgebra.Vector {MathNet.Numerics.LinearAlgebra.Complex.DenseVector}

▶ EigenVectors

DenseMatrix 30x30-Double

MathNet.Numerics.LinearAlgebra.Matrix {MathNet.Numerics.LinearAlgebra.Double.DenseMatrix}

IsFullRank

true

bool

IsSymmetric

true

bool

Rank

30

int

transposedMatrix

DenseMatrix 30x30-Double

MathNet.Numerics.LinearAlgebra.Matrix {MathNet.Numerics.LinearAlgebra.Double.DenseMatrix}

ColumnCount

30

int

RowCount

30

int

▶ Storage

{MathNet.Numerics.LinearAlgebra.Storage.DenseColumnMajorMatrixStorage}

MathNet.Numerics.LinearAlgebra.Storage.MatrixStorage {MathNet.Numerics.LinearAlgebra.Storage.DenseColumnMajorMatrixStorage}

▶ Values

{double[900]}

double[]

▶ Statische Member

▶ Nicht öffentliche Member

areEqual

false

bool

eigenvector

DenseVector 30-Complex

MathNet.Numerics.LinearAlgebra.Vector {MathNet.Numerics.LinearAlgebra.Complex.DenseVector}

index

30

int

9 -75 -56 -19 -85 77 83 69 -6 26 64 -68 38 .. 4 24

-75 -51 -85 -19 -45 -51 -15 -58 98 -85 23 -25 22 .. 90 72

-56 -85 -17 -76 -1 56 79 -61 -5 71 47 48 -89 .. -3 90

-19 -19 -76 -35 95 -7 35 -62 -72 9 76 2 58 .. 67 76

-85 -45 -1 95 -43 -73 64 -87 -10 98 -36 90 -81 .. 37 -57

77 -51 56 -7 -73 55 -77 -4 77 -17 40 87 86 .. 87 70

83 -15 79 35 64 -77 26 -80 57 -70 -21 -7 -40 .. -2 -31

69 -58 -61 -62 -87 -4 -80 71 72 -12 -76 37 17 .. -34 -21

.. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..

50 -93 50 -77 0 9 13 28 -37 84 82 -40 68 .. -86 -58

-34 -88 -76 -30 -96 -69 17 59 99 61 0 -60 90 .. -89 -85

4 90 -3 67 37 87 -2 -34 -98 -22 31 25 -46 .. -54 -63

24 72 90 76 -57 70 -31 -21 99 44 -28 15 33 .. -63 -46

"testhost.exe" (CLR v4.0.30319: TestSourceHost: Enumerating source "C:\Program Files\Microsoft Visual Studio\2022\Professional\Common7\IDE\Extensions\TestPlatform\Microsoft.TestPlatform.CoreUtilities.dll" geladen. Das Laden von Symbolen wurde übersprungen. Das Modul ist optimiert, und die Debugoption "Nur eigenen Code" ist aktiviert.

9 -75 -56 -19 -85 77 83 69 -6 26 64 -68 38 .. 4 24

-75 -51 -85 -19 -45 -51 -15 -58 98 -85 23 -25 22 .. 90 72

-56 -85 -17 -76 -1 56 79 -61 -5 71 47 48 -89 .. -3 90

-19 -19 -76 -35 95 -7 35 -62 -72 9 76 2 58 .. 67 76

-85 -45 -1 95 -43 -73 64 -87 -10 98 -36 90 -81 .. 37 -57

77 -51 56 -7 -73 55 -77 -4 77 -17 40 87 86 .. 87 70

83 -15 79 35 64 -77 26 -80 57 -70 -21 -7 -40 .. -2 -31

69 -58 -61 -62 -87 -4 -80 71 72 -12 -76 37 17 .. -34 -21

.. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..

50 -93 50 -77 0 9 13 28 -37 84 82 -40 68 .. -86 -58

-34 -88 -76 -30 -96 -69 17 59 99 61 0 -60 90 .. -89 -85

4 90 -3 67 37 87 -2 -34 -98 -22 31 25 -46 .. -54 -63

24 72 90 76 -57 70 -31 -21 99 44 -28 15 33 .. -63 -46

Microsoft.VisualStudio.TestTools.UnitTesting.AssertFailedException

HResult=0x80131500

Nachricht = Fehler bei "Assert.IsTrue".

Quelle = Microsoft.VisualStudio.TestPlatform.TestFramework

Stapelüberwachung:

bei Microsoft.VisualStudio.TestTools.UnitTesting.Assert.HandleFail(String assertionName, String message, Object[] parameters)

bei Microsoft.VisualStudio.TestTools.UnitTesting.Assert.IsTrue(Boolean condition)

bei UnitTest1.UnitTest_Quadratical_Matrices.Test_SymmetricMatrix() in C:\Software\Entwicklung\Mathematics\LinearAlgebra\MatrixGenerator\UnitTest1\UnitTest_Quadratical_Matrices.cs: Zeile78

[TestMethod]

public void Test_SymmetricMatrix()

{

   for (int i = 0; i < 95; i++)

   {

      MatrixGenerator symmetricMatrix = new MatrixGenerator(MatrixGenerator.Types.Symmetric, matrixDimension);

      Trace.WriteLine(symmetricMatrix.Matrix.ToMatrixString());

      symmetricMatrix.Matrix.CheckElements(CheckSymmetry);

      Evd<double> eigen = symmetricMatrix.Matrix.Evd();

      var eigenvector = eigen.EigenValues;

      int index = 0;

      eigenvector.ToList().ForEach(delegate (Complex eigenWert)

      {

         Assert.AreEqual(0, eigenvector[index].Imaginary, eigenvector[index].ToString() + " hat Imaginärteil !");

         //Assert.AreEqual(eigenWerteNominal[index], eigenvector[index].Real, delta);

         index++;

      });

      var transposedMatrix = symmetricMatrix.Matrix.Transpose();

      Trace.WriteLine(transposedMatrix.ToMatrixString());

      //bool areEqual = symmetricMatrix.Matrix.IsEqualTo(transposedMatrix);

      bool areEqual = symmetricMatrix.Matrix==transposedMatrix;

      Assert.IsTrue(areEqual);

   }

}

public class MatrixGenerator

{

  readonly RandomGenerator randomGenerator = new RandomGenerator(-100, 100);

  public enum Types

  {

     Zero,

     Identity,

     Normal,

     UpperTriangel,

     LowerTriangel,

     Symmetric,

     SkewSymmetric

  }

    /// <summary>

    /// Access to the matrix instance

    /// </summary>

    public Matrix<double> Matrix { get; private set; }

    public MatrixGenerator(Types type, int rowCount, int colCount = -1)

    {

     int columnCount = Math.Max(rowCount, colCount);

     switch (type)

     {

        case Types.Zero:          Matrix = Matrix<double>.Build.Dense(rowCount, columnCount); break;

        case Types.Identity:      Matrix = Matrix<double>.Build.DenseIdentity(rowCount, columnCount); break;

        case Types.Normal:        

           Matrix = Matrix<double>.Build.Dense(rowCount, columnCount);

           FillRandomElements(type);

           break;

        case Types.UpperTriangel: Matrix = Matrix<double>.Build.Dense(rowCount, columnCount, BuildUpperTriangelMatrix); break;

        case Types.LowerTriangel: Matrix = Matrix<double>.Build.Dense(rowCount, columnCount, BuildLowerTriangelMatrix); break;

        case Types.Symmetric:

           Matrix = Matrix<double>.Build.Dense(rowCount, columnCount);

          FillRandomElements(type);

           break;

        case Types.SkewSymmetric:

           Matrix = Matrix<double>.Build.Dense(rowCount, columnCount);

           FillRandomElements(type);

           break;

        default:

           break;

     }

    }

  private void FillRandomElements(Types type)

  {

     for (int i = 0; i < Matrix.RowCount; i++)

     {

        for (int j = 0; j < Matrix.ColumnCount; j++)

        {

           var value = randomGenerator.Next();

           Matrix[i, j] = value;

           if (type > Types.Normal)

           {

              if (i == j) // Diagonale ?

              {

                 if (type == Types.SkewSymmetric)

                 {

                    Matrix[i, j] = 0;

                 }

              }

              else

              {

                 Matrix[j, i] = (type == Types.SkewSymmetric) ? -value : value;

              }

           }       

        } // next j

     } // next i

  } // end FillRandomElements

  private double BuildLowerTriangelMatrix(int row, int col)

  {

     if (row < col)

     {

        return 0;

     }

     else

     {

        return randomGenerator.Next();

     }

  }

  private double BuildUpperTriangelMatrix(int row, int col)

  {

     if (row > col)

     {

        return 0;

     }

     else

     {

        return randomGenerator.Next();

     }

  }

} // end class MatrixGenerator

Von: jkalias @.> Gesendet: Samstag, 28. September 2024 15:00 An: mathnet/mathnet-numerics @.> Cc: Anatom70 @.>; Author @.> Betreff: Re: [mathnet/mathnet-numerics] matrix operator == performs false on identical matrices (Issue #1089)

What do you mean it's not reproducible? Can you provide a code snippet for this 12x12 matrix? Or at bare minimum print out the matrix for which this happens, otherwise the bug can't be fixed.

— Reply to this email directly, view it on GitHub https://github.com/mathnet/mathnet-numerics/issues/1089#issuecomment-2380632347 , or unsubscribe https://github.com/notifications/unsubscribe-auth/BKT7QJ32L54J6LXZ4JZ2GELZY2R4TAVCNFSM6AAAAABMXODXA2VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDGOBQGYZTEMZUG4 . You are receiving this because you authored the thread. https://github.com/notifications/beacon/BKT7QJ2ABJIK7A2VBNPYST3ZY2R4TA5CNFSM6AAAAABMXODXA2WGG33NNVSW45C7OR4XAZNMJFZXG5LFINXW23LFNZ2KUY3PNVWWK3TUL5UWJTUN4WIRW.gif Message ID: @. @.> >

jkalias commented 4 days ago

Wow, this is a bit...difficult to read :) Could you please repost it, but not from an email client? Perhaps directly in github.com? Thank you for effort though