Hipparchus-Math / hipparchus

An efficient, general-purpose mathematics components library in the Java programming language
Apache License 2.0
136 stars 41 forks source link

Avoid exception "org.hipparchus.exception.MathIllegalArgumentException: matrix is singular" for complex implementations #337

Open axkr opened 2 months ago

axkr commented 2 months ago

The EigenDecompositionNonSymmetricimplementation returns a result without an exception.

Can the exception org.hipparchus.exception.MathIllegalArgumentException: matrix is singular also be avoided for the "Complex implementations" ComplexEigenDecomposition and OrderedComplexEigenDecomposition?

@Test
  public void testEqualEigenValuesSingular() {
    Array2DRowRealMatrix matrix =
        new Array2DRowRealMatrix(new double[][] {{1, 0, 0}, {-2, 1, 0}, {0, 1, 1}});
    EigenDecompositionNonSymmetric ed = new EigenDecompositionNonSymmetric(matrix);
    for (int i = 0; i < 3; i++) {
      System.out.println(ed.getEigenvector(i));
    }

    try {
      ComplexEigenDecomposition complexEigenDecomposition = new ComplexEigenDecomposition(matrix);
      for (int i = 0; i < 3; i++) {
        System.out.println(complexEigenDecomposition.getEigenvector(i));
      }
    } catch (MathRuntimeException mre) {
      mre.printStackTrace();
    }

    try {
      ComplexEigenDecomposition ced = new OrderedComplexEigenDecomposition(matrix, //
          ComplexEigenDecomposition.DEFAULT_EIGENVECTORS_EQUALITY, //
          ComplexEigenDecomposition.DEFAULT_EPSILON, //
          ComplexEigenDecomposition.DEFAULT_EPSILON_AV_VD_CHECK, //
          (c1, c2) -> Double.compare(c2.norm(), c1.norm()));
      for (int i = 0; i < 3; i++) {
        System.out.println(ced.getEigenvector(i));
      }
    } catch (MathRuntimeException mre) {
      mre.printStackTrace();
    }
  }

See:

axkr commented 1 month ago

This input:

Eigenvalues({{1,0,0,0,0},{3,1,0,0,0},{6,3,2,0,0},{10,6,3,2,0},{15,10,6,3,2}})

raises a "failed decomposition of a 5x5 matrix" exception for the OrderedComplexEigenDecomposition implementation:

org.hipparchus.exception.MathRuntimeException: failed decomposition of a 5x5 matrix
    at org.hipparchus.linear.ComplexEigenDecomposition.checkDefinition(ComplexEigenDecomposition.java:455)
    at org.hipparchus.linear.ComplexEigenDecomposition.<init>(ComplexEigenDecomposition.java:167)
    at org.hipparchus.linear.OrderedComplexEigenDecomposition.<init>(OrderedComplexEigenDecomposition.java:98)
    at org.matheclipse.core.builtin.LinearAlgebra$Eigenvalues.realMatrixEval(LinearAlgebra.java:2204)

if I set epsilonAVVDCheck = 1e-4 I get a result.

Thereas the EigenDecompositionNonSymmetric implementation doesn't need this adjustment:

      EigenDecompositionNonSymmetric edns = new EigenDecompositionNonSymmetric(matrix);
      Complex[] eigenvalues = edns.getEigenvalues();
      return F.mapRange(0, eigenvalues.length, (int i) -> {
        if (F.isZero(eigenvalues[i].getImaginary())) {
          return F.num(eigenvalues[i].getReal());
        }
        return F.complexNum(eigenvalues[i].getReal(), eigenvalues[i].getImaginary());
      });

returns the result: {2.00008+I*0.000132429,2.00008+I*(-0.000132429),1.99985,1.0,1.0}

maisonobe commented 1 month ago

I confirm the problem. Already worked a few hours on it. I am still invetigating.