Решение матриц вида Ax = B ==> ошибка: матрица близка к единице или плохо масштабируется

Мне сложно решить систему вида Ax = B

Решение системы должно быть

x = inv(A)*B

Однако это не работает.

Я получаю следующее сообщение об ошибке, когда пытаюсь выполнить приведенную выше строку кода:

Warning: Matrix is close to singular or badly scaled.
     Results may be inaccurate. RCOND = 1.156482e-018. 

Кажется, что у Matlab возникают проблемы с инвертированием указанной мною матрицы. Я попытался проверить правильность работы обратной функции, набрав inv (A) * A

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

Это матрица A, которую я использую:

A = [5/2   1/2  -1     0     0    -1/2  -1/2   0     0
     1/2   1/2   0     0     0    -1/2  -1/2   0     0 
    -1     0     5/2  -1/2  -1     0     0    -1/2   1/2
     0     0    -1/2   1/2   0     0     0     1/2  -1/2
     0     0    -1     0     3/2  -1/2   1/2   0     0
    -1/2  -1/2   0     0    -1/2   2     0    -1     0  
    -1/2  -1/2   0     0     1/2   0     1     0     0 
     0     0    -1/2   1/2   0    -1     0     2     0 
     0     0     1/2  -1/2   0     0     0     0     1]

Любые идеи относительно того, почему это не работает? Я также попытался преобразовать A в разреженную матрицу (разреженный (A)), а затем запустить обратную команду. Нет кубиков.

Ответ 1

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

Поскольку вы работаете с числами с плавающей запятой, это иногда вызывает другие тонкие проблемы, один из которых вы можете увидеть в результате det(A), который находится в порядке 1e-16, то есть точность машины или 0 на практике.

Вы можете видеть, что эта матрица не имеет полного ранга, выполняя функцию rank: rank(A) = 8. Для матрицы 9x9 это действительно означает, что матрица не обратима для удвоений (поскольку функция rank учитывает точность машины).

Если вы хотите использовать MATLAB для получения результата, который соответствует расчету вручную, вы можете использовать Symbolic Toolbox и его vpa (арифметику с переменной точностью) для решения возможных числовых задач за счет более медленного вычисления.

B = [5  1 -2  0  0 -1 -1  0  0;
     1  1  0  0  0 -1 -1  0  0;
    -2  0  5 -1 -2  0  0 -1  1;
     0  0 -1  1  0  0  0  1 -1;
     0  0 -2  0  3 -1  1  0  0;
    -1 -1  0  0 -1  4  0 -2  0;
    -1 -1  0  0  1  0  2  0  0;
     0  0 -1  1  0 -2  0  4  0;
     0  0  1 -1  0  0  0  0  2];
A = B/2;
size(A)    % = [9 9]
det(A)     % = -1.38777878078145e-17
rank(A)    % = 8
C = vpa(A);
det(C)     % = 0.0
rank(C)    % = 8

Как с VPA, так и с плавающими точками вы получите, что ранг равен 8, размер [9 9], а детерминант - практически 0, то есть сингулярный или не обратимый. Изменение нескольких записей может привести к тому, что ваша матрица будет регулярной (неособой), но она не будет гарантирована, и она решит другую проблему.

Чтобы решить вашу актуальную проблему A*x=b для x, вы можете попробовать использовать mldivide (a.k.a. оператор обратной косой черты) или псевдообратный псевдоним Moore-Penrose:

x1 = A\b;
x2 = pinv(A)*b;

Но помните, что такая система не имеет уникального решения, поэтому и псевдо-обратный, и обратный слэш-оператор могут (и в этом случае) возвращать очень разные решения, независимо от того, приемлемо ли какое-либо из них, действительно зависит от вашего приложение.

Ответ 2

Это означает именно то, что он говорит. Матрица единственная, что означает, что она не может быть инвертирована. Не все матрицы могут.

В геометрических терминах у вас есть матрица, которая превращает один 9-мерный объект в другой, но полностью выравнивает одно измерение. Это нельзя отменить; нет никакого способа сказать, как далеко продвинуться в этом направлении.

Ответ 3

Матрица сингулярна, рассмотрим B = 2 * A ниже:

B = [5  1 -2  0  0 -1 -1  0  0;
     1  1  0  0  0 -1 -1  0  0;
    -2  0  5 -1 -2  0  0 -1  1;
     0  0 -1  1  0  0  0  1 -1;
     0  0 -2  0  3 -1  1  0  0;
    -1 -1  0  0 -1  4  0 -2  0;
    -1 -1  0  0  1  0  2  0  0;
     0  0 -1  1  0 -2  0  4  0;
     0  0  1 -1  0  0  0  0  2]

det(B)

0

Ответ 4

bicgstab(A,b,tol,maxit), итеративный решатель, смог решить сингулярную линейную систему A * x = b для особой матрицы A:

size(A)=[162, 162] 
rank(A)=14 
cond(A)=4.1813e+132 

Я использовал:

tol=1e-10; 
maxit=100;

Ни один из вышеупомянутых (включая svd, \, inv, pinv, gmres) работал у меня, но bicgstab проделал хорошую работу. bicgstab сходится на итерации 4 к решению с относительным остатком 1.1e-11. Он работает быстро для разреженных матриц.

Смотрите здесь: https://uk.mathworks.com/help/matlab/ref/bicgstab.html