(Псевдо)-обратная от N к N матрица с нулевым определителем

Я хотел бы взять обратную матрицу nxn для использования в моем GraphSlam.

Проблемы, с которыми я столкнулся:

  • .inverse() Собственная библиотека (3.1.2) не допускает нулевые значения, возвращает NaN
  • Библиотека LAPACK (3.4.2) не позволяет использовать нулевой определитель, но допускает нулевые значения (использовался пример кода из вычисления обратной матрицы с использованием lapack в C)
  • Библиотека Seldon (5.1.2) по какой-то причине не компилируется

Кто-нибудь успешно реализовал код инверсии матрицы n x n, который допускает отрицательные, нулевые значения и определитель нуля? Любые хорошие рекомендации библиотеки (C++)?

Я пытаюсь рассчитать омега в следующем для GraphSlam: http://www.acastano.com/others/udacity/cs_373_autonomous_car.html


Простой пример:

[ 1 -1  0 0 ]
[ -1 2 -1 0 ]
[ 0 -1  1 0 ]
[ 0  0  0 0 ]

Реальный пример будет 170x170 и содержит 0, отрицательные значения, большие положительные значения. Данный простой пример используется для отладки кода.


Я могу рассчитать это в Matlab (псевдообратная Мура-Пенроуза), но по какой-то причине я не могу запрограммировать это в C++.

A = [1 -1 0 0; -1 2 -1 0; 0 -1 1 0; 0 0 0 0]
B = pinv(A)
B=
[0.56   -0.12  -0.44  0]
[-0.12  0.22   -0.11  0]
[-0.44  -0.11   0.56  0]
[0  0  0   0]

Для моего приложения я могу (временно) удалить измерение с нулями.
Поэтому я собираюсь удалить 4-й столбец и 4-й ряд.
Я также могу сделать это для моей матрицы 170x170, 4x4 был просто примером.

A:

[ 1 -1  0 ]
[ -1 2 -1 ]
[ 0 -1  1 ]

Таким образом, удаление 4-го столбца и 4-го ряда не приведет к нулевому определителю. Но у меня все еще может быть нулевой определитель, если моя матрица такая же, как указано выше. Это когда сумма каждой строки или каждого столбца равна нулю. (Который у меня будет все время в GraphSlam)

Решение LAPACK (основанное на инверсии Мура-Пенроуза) работало, если детерминант не был равен нулю (использовался пример кода из вычисления обратной матрицы с использованием lapack в C).
Но потерпел неудачу как "псевдообратный" с определителем нуля.


РЕШЕНИЕ: (все кредиты Фрэнку Рейнингхаусу) с использованием SVD(разложение по сингулярным числам)
http://sourceware.org/ml/gsl-discuss/2008-q2/msg00013.html

Работает с:

  • Нулевые значения (даже полные 0 строк и полные 0 столбцов)
  • Отрицательные значения
  • Определитель нуля

A^-1:

[0.56   -0.12  -0.44]
[-0.12  0.22   -0.11]
[-0.44  -0.11   0.56]

4 ответа

Если все, что вам нужно, это решить задачу вида Ax=B (или эквивалентно вычислить произведения вида A^-1 * b), то я рекомендую вам не вычислять обратное или псевдообратное значение A, а непосредственно решать для Ax=b с использованием подходящего решателя, раскрывающего рейтинг. Например, используя Eigen:

x = A.colPivHouseholderQr().solve(b);
x = A.jacobiSvd(ComputeThinU|ComputeThinV).solve(b);

Ваша команда Matlab не вычисляет обратное значение в вашем случае, потому что матрица имеет определенный ноль. pinv commmand вычисляет псевдообращение Мура-Пенроуза. pinv(A) имеет некоторые, но не все, свойства inv(A),

Так что вы не делаете то же самое в C++ и в Matlab!

предыдущий

Как в моем комментарии. Теперь как ответ. Вы должны убедиться, что вы инвертируете обратимые матрицы. Это означает

det A != 0

В вашем примере матрицы определитель равен нулю. Это не обратимая матрица. Я надеюсь, что вы не примеряете это!

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

Вы уверены, что это из-за нулевых / отрицательных значений, а не потому, что ваша матрица необратима?

Матрица имеет обратное значение только в том случае, если ее определитель отличен от нуля ( ссылка на mathworld), а пример матрицы, который вы разместили в вопросе, имеет нулевой определитель и поэтому не имеет обратного.

Это должно объяснить, почему эти библиотеки не позволяют использовать обратную матрицу, но я не могу сказать, имеет ли место то же рассуждение для вашей полноразмерной матрицы 170x170.

Если ваши матрицы являются своего рода ковариационными или весовыми матрицами, вы можете использовать "обобщенную инверсию Холецкого" вместо SVD. Результаты будут более приемлемыми для практического использования

Другие вопросы по тегам