Fiz isso pela primeira vez recentemente, usando sugestões do mathSE.
Acho que o SVD foi recomendado pela maioria, mas optei pela simplicidade de Cholesky:
Se a matriz , decomponho em uma matriz triangular usando Cholesky, de modo que . Em seguida, uso a substituição traseira ou substituição anterior (dependendo de escolher L como triangular superior ou inferior), para inverter , de modo que eu tenha . Com isso, posso calcular rapidamente .M=AA⊤MLM=LL⊤LL−1M−1=(LL⊤)−1=L−⊤L−1
Começar com:
M=AA⊤ , onde é conhecido e é implicitamente simétrico e também é positivo-definido.M
Fatoração de Cholesky:
M→LL⊤ , onde é quadrado e não singularL
Substituição traseira:
L→L−1 , provavelmente a maneira mais rápida de inverter (não me cite nisso)L
Multiplicação:
M−1=(LL⊤)−1=L−⊤L−1
Notação usada:
índices inferiores são linhas, índices superiores são colunas e é a transposição deL−⊤L−1
Algoritmo My Cholesky (provavelmente de Numerical Recipes ou Wikipedia)
Lji=Mji−Mi⋅MjMii−Mi⋅Mi
Isso quase pode ser feito no local (você só precisa de armazenamento temporário para os elementos diagonais, um acumulador e alguns iteradores inteiros).
Meu algoritmo de substituição traseira (de Numerical Recipes, verifique sua versão, pois eu posso ter cometido um erro com a marcação LaTeX)
(L−1)ji=⎧⎩⎨1/Lii(−Li⋅(L−T)j)/Liiif i=jotherwise
Como aparece na expressão, a ordem que você itera sobre a matriz é importante (algumas partes da matriz de resultados dependem de outras partes dela que devem ser calculadas previamente). Verifique o código de Receitas numéricas para obter um exemplo completo no código. [Editar]: Na verdade, basta verificar o exemplo de Receitas numéricas. Eu simplifiquei demais usando produtos de ponto, a ponto de a equação acima ter uma dependência cíclica, independentemente da ordem em que você itera ...L−T