Java: инверсия матрицы с использованием EJML не работает должным образом

В рамках проекта Java, который я разработал, мне нужно вычислить обратную матрицу. Для согласования с другими проектами и другими разработчиками я использую библиотеку Efficient Java Matrix Library (orj.ejml).

Для инвертирования Матрицы я использую инвертирование из org.ejml.ops.CommonOps, и до сих пор работала нормально, получая неожиданный результат

Я выделил случай, который не работает, чтобы быть:

    DenseMatrix64F X = new DenseMatrix64F(3, 3);
    X.setData(new double[]{77.44000335693366,-24.64000011444091,-8.800000190734865, -24.640000114440916,7.839999732971196,2.799999952316285, -8.800000190734865,2.799999952316285,1.0000000000000004});
    DenseMatrix64F invX = new DenseMatrix64F(3, 3);
    boolean completed = CommonOps.invert(X, invX);
    System.out.println(X);
    System.out.println(invX);
    System.out.println(completed);  

Вывод, который я получаю из этого теста:

Тип = плотный, numRows = 3, numCols = 3
77,440 -24,640 -8,800
-24,640 7,840 2,800
-8.800 2.800 1.000

Тип = плотный, numRows = 3, numCols = 3
NaN -бесконечность бесконечность
NaN Бесконечность-бесконечность
NaN -бесконечность бесконечность

правда

Моей первой мыслью было, что это может быть единичная матрица и, следовательно, не обратимая, но после тестирования той же самой матрицы с помощью другого инструмента вычисления я обнаружил, что она не является единственной.

Поэтому я вернулся к документации EJML и обнаружил следующую информацию для этой конкретной функции.

Если алгоритм не может инвертировать матрицу, возвращается false. Если он возвращает true, это означает, что алгоритм завершен. Результаты могут все еще быть плохими, потому что матрица единственная или почти единственная.

И, в данном конкретном случае, матрица не является единственной, но мы можем сказать, что она почти единственная.

Единственное решение, о котором я мог подумать, - это искать в перевернутой матрице NaN или Infinites после ее вычисления, и если я нахожу там что-то смешное, я просто заменяю инвертированную матрицу исходной матрицей, хотя это не кажется очень чистой практикой. это дает разумные результаты.

Мой вопрос:

  • Не могли бы вы придумать какое-нибудь решение для этой ситуации? Что-то умнее и мудрее, чем просто использовать исходную матрицу в качестве собственной обратной матрицы.

  • В случае, если нет никакого способа обойти это, знаете ли вы о какой-либо другой библиотеке Java Matrix, которая имеет какое-то решение этой ситуации, я не собираюсь представлять новую библиотеку, но это может быть единственным решением, если это станет реальной проблемой,

С уважением и благодарностью за ваш вклад!

1 ответ

Решение

Вы должны попробовать использовать SVD, если у вас есть обратное. Также рассмотрите псевдообратное. В основном любая библиотека, использующая декомпозицию LU, будет иметь серьезные проблемы. Вот выход из Октавы. Обратите внимание, что два значения в единственном числе почти равны нулю. Октава даст вам обратное с реальными числами, но это плохое...

octave:7> cond(B)
ans =    8.5768e+17
octave:8> svd(B)
ans =

   8.6280e+01
   3.7146e-15
   1.0060e-16

inv(B)*B
warning: inverse: matrix singular to machine precision, rcond = 4.97813e-19
ans =

   0.62500   0.06250   0.03125
   0.00000   0.00000   0.00000
   0.00000   0.00000   4.00000
Другие вопросы по тегам