Решение матриц вида 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

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

это матрица 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 в разреженную матрицу(sparse (A)), а затем запустить обратную команду. Без костей.

4 ответов


проблема действительно в вашей математике. Матрица, которую вы предоставили, не имеет полного ранга, поэтому она не обратима. Вы можете проверить это вручную (не потратили время на это), но 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 (а.к.а. оператор обратный слеш ) или псевдо-инверсия Мура-Пенроуза:

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

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


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

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


матрица и сингулярный, рассмотрим 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

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.1 e-11. Он работает быстро для разреженных матриц.

см. документацию здесь: https://uk.mathworks.com/help/matlab/ref/bicgstab.html