Я хотел бы взять обратную матрицу nxn для использования в моем GraphSlam.
Проблемы, с которыми я столкнулся:
.inverse()
Собственная библиотека (3.1.2) не допускает нулевые значения, возвращает NaN
Кто-нибудь успешно реализовал N Икс 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 ]
Реальный пример будет 170×170 и содержит 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-й ряд.
Я также могу сделать это для моей матрицы 170×170, 4×4 был просто примером.
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
Работает с:
A ^ -1:
[0.56 -0.12 -0.44]
[-0.12 0.22 -0.11]
[-0.44 -0.11 0.56]
Если все, что вам нужно, это решить задачу вида Ax = B (или эквивалентно вычислить произведения вида A ^ -1 * b), то я рекомендую вам не вычислять обратное или псевдообратное значение A, а непосредственно решать для Ax = b с использованием подходящего решателя, раскрывающего рейтинг. Например, используя Eigen:
x = A.colPivHouseholderQr().solve(b);
x = A.jacobiSvd(ComputeThinU|ComputeThinV).solve(b);
Ваша команда Matlab не вычисляет обратное значение в вашем случае, потому что матрица имеет определенный ноль. pinv
Command рассчитывает Псевдообратный Мур-Пенроуз. pinv(A)
имеет некоторые, но не все, свойства inv(A)
,
Так что вы не делаете то же самое в C ++ и в Matlab!
предыдущий
Как в моем комментарии. Теперь как ответ. Вы должны убедиться, что вы инвертируете обратимые матрицы. Это означает
det A != 0
В вашем примере матрицы определитель равен нулю. Это не обратимая матрица. Я надеюсь, что вы не примеряете это!
Например, данная матрица имеет нулевой определитель, если имеется полная строка или столбец с нулевыми записями.
Вы уверены, что это из-за нулевых / отрицательных значений, а не потому, что ваша матрица необратима?
Обратная матрица имеет место только в том случае, если ее определитель ненулевой (ссылка на mathworld), а пример матрицы вы выложили в вопросе имеет нулевой определитель и поэтому он не имеет обратного.
Это должно объяснить, почему эти библиотеки не позволяют использовать обратную матрицу, но я не могу сказать, имеет ли место то же самое рассуждение для вашей полноразмерной матрицы 170×170.
Если ваши матрицы являются своего рода ковариационными или весовыми матрицами, вы можете использовать «обобщенную инверсию Холецкого» вместо SVD. Результаты будут более приемлемыми для практического использования