J'ai du mal à résoudre un système de la forme Ax = B
La solution au système devrait être
x = inv(A)*B
Cependant, cela ne fonctionne pas.
Je reçois le message d'erreur suivant lorsque j'essaie la ligne de code ci-dessus:
Warning: Matrix is close to singular or badly scaled.
Results may be inaccurate. RCOND = 1.156482e-018.
Il semble que matlab rencontre des difficultés pour inverser la matrice que j'ai spécifiée. J'ai essayé de vérifier que la fonction inverse fonctionnait correctement en tapant inv (A) * A
Cela devrait donner la matrice d’identité, mais j’ai eu la même erreur et des numéros erronés.
Ceci est la matrice que j'utilise:
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]
Des idées pour expliquer pourquoi cela ne fonctionne pas? J'ai également essayé de convertir A en une matrice creuse (sparse (A)), puis d'exécuter la commande inverse. Pas de dé.
Le problème est bien dans vos mathématiques. La matrice que vous avez fournie n’est pas de rang complet, elle n’est donc pas inversible. Vous pouvez vérifier cela manuellement (vous n’avez pas pris le temps de le faire), mais MATLAB le signale déjà en affichant cet avertissement. .
Etant donné que vous travaillez avec des nombres à virgule flottante, cela cause parfois d’autres problèmes subtils, dont l’un est visible dans le résultat de det(A)
, qui est dans l’ordre de 1e-16
, c’est-à-dire la précision de la machine ou 0 dans la pratique.
Vous pouvez voir que cette matrice n’a pas un rang complet en exécutant la fonction rank
: rank(A) = 8
. Pour une matrice 9x9
, cela signifie en effet que la matrice n'est pas inversible pour les doublons (car la fonction rank
représente la précision de la machine).
Si vous souhaitez utiliser MATLAB pour obtenir un résultat correspondant à un calcul manuel, vous pouvez utiliser la boîte à outils Symbolic et sa vpa
(arithmétique à précision variable) pour contourner d'éventuels problèmes numériques au détriment d'un calcul plus lent.
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
Avec l’APV et les points flottants, vous obtiendrez que le rang est 8, la taille est [9 9] et le déterminant est pratiquement 0, c’est-à-dire singulier ou non inversible. Changer quelques entrées peut rendre votre matrice régulière (non singulière), mais son fonctionnement n'est pas garanti et cela résoudra un problème différent.
Pour résoudre votre problème actuel A*x=b
pour x
, vous pouvez essayer d'utiliser mldivide
(a.k.a. l'opérateur de barre oblique inverse) ou un pseudo-inverse de Moore-Penrose:
x1 = A\b;
x2 = pinv(A)*b;
Mais rappelez-vous qu’un tel système n’a pas de solution unique, aussi bien le pseudo-inverse que l’opérateur de barre oblique inversée peuvent (et dans ce cas-là) renvoyer des solutions très différentes, que l’une d’elles soit acceptable dépend de votre application.
Cela signifie exactement ce que cela dit. La matrice est singulière, ce qui signifie qu’elle ne peut pas vraiment être inversée . Toutes les matrices ne le peuvent pas.
En termes géométriques, vous avez une matrice qui transforme un objet à 9 dimensions en un autre, mais aplatit complètement une dimension. Cela ne peut pas être annulé. il n'y a aucun moyen de savoir jusqu'où il faut tirer les choses dans cette direction.
La matrice est singulier, considérons B = 2 * A ci-dessous:
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)
, un solutionneur itératif, était capable de résoudre un système linéaire singulier A * x = b pour une matrice singulière A:
size(A)=[162, 162]
rank(A)=14
cond(A)=4.1813e+132
J'ai utilisé:
tol=1e-10;
maxit=100;
Aucune des personnes mentionnées ci-dessus (y compris svd
, \
, inv
, pinv
, gmres
) ne travaillait pour moi, mais bicgstab
faisait du bon travail. bicgstab
a convergé à l'itération 4 vers une solution avec résiduel relatif 1.1e-11. Cela fonctionne vite pour les matrices clairsemées.
Voir la documentation ici: https://uk.mathworks.com/help/matlab/ref/bicgstab.html