2013-08-31 11 views
18

Attualmente sto cercando di sviluppare una piccola libreria matematica orientata alla matrice (sto usando Eigen 3 per le strutture e le operazioni di dati matriciali) e volevo implementare alcuni pratiche funzioni di Matlab, come l'operatore backslash ampiamente utilizzato (che è equivalente a mldivide) per calcolare la soluzione di sistemi lineari (espressi in forma di matrice).Come implementare la mldivide di Matlab (ovvero l'operatore backslash "")

Esiste una buona spiegazione dettagliata su come ciò potrebbe essere realizzato? (Ho già implementato la pseudo-inversa pinv funzione con una decomposizione classica SVD, ma ho letto da qualche parte che A\b non è sempre pinv(A)*b, almeno Matalb non si limita a farlo)

Grazie

+2

Non è semplice e consiglio vivamente contro il tentativo. Basta interfacciarlo con DGEMV di LAPACK. Un sacco di persone intelligenti hanno dedicato molto tempo alla messa a punto di 'mldivide'. –

+0

domanda simile: [In che modo l'operatore backslash MATLAB risolve Ax = b per le matrici quadrate?] (Http://scicomp.stackexchange.com/questions/1001/how-does-the-matlab-backslash-operator-solve-ax -b-per-matrici quadrate) – Amro

+0

@Amro, woohoo La mia domanda. LOL –

risposta

33

Per x = A\b, l'operatore backslash comprende un numero di algorithms per gestire diversi tipi di matrici di input. Quindi viene diagnosticata la matrice A e viene selezionato un percorso di esecuzione in base alle sue caratteristiche.

Il seguente page descrive in pseudo-codice quando A è una matrice completa:

if size(A,1) == size(A,2)   % A is square 
    if isequal(A,tril(A))   % A is lower triangular 
     x = A \ b;    % This is a simple forward substitution on b 
    elseif isequal(A,triu(A))  % A is upper triangular 
     x = A \ b;    % This is a simple backward substitution on b 
    else 
     if isequal(A,A')   % A is symmetric 
      [R,p] = chol(A); 
      if (p == 0)   % A is symmetric positive definite 
       x = R \ (R' \ b); % a forward and a backward substitution 
       return 
      end 
     end 
     [L,U,P] = lu(A);   % general, square A 
     x = U \ (L \ (P*b));  % a forward and a backward substitution 
    end 
else        % A is rectangular 
    [Q,R] = qr(A); 
    x = R \ (Q' * b); 
end 

Per matrici non quadrati, QR decomposition viene utilizzato. Per matrici triangolari quadrate, esegue un semplice forward/backward substitution. Per le matrici simmetriche con segno positivo definito, viene utilizzato Cholesky decomposition. Altrimenti LU decomposition viene utilizzato per le matrici quadrate generali.

Aggiornamento: MathWorks ha aggiornato il algorithm section nella pagina doc di mldivide con alcuni bei diagrammi di flusso. Vedere here e here (casi pieni e sparsi).

mldivide_full

Tutti questi algoritmi sono metodi corrispondenti a LAPACK, e in effetti è probabilmente quello che sta facendo MATLAB (si noti che le versioni recenti di MATLAB nave con l'ottimizzato Intel MKL implementazione).

La ragione per avere metodi diversi è che tenta di utilizzare l'algoritmo più specifico per risolvere il sistema di equazioni che sfrutta tutte le caratteristiche della matrice dei coefficienti (o perché sarebbe più veloce o più numericamente stabile). Quindi potresti certamente usare un risolutore generale, ma non sarà il più efficiente.

Infatti, se si conosce come A è come prima, è possibile saltare il processo di test extra chiamando linsolve e specificando direttamente le opzioni.

se A è rettangolare o singolari, si potrebbe anche usare PINV per trovare una norma minima soluzione di minimi quadrati (implementata utilizzando SVD decomposition):

x = pinv(A)*b 

Tutto quanto sopra vale per le matrici dense, matrici sparse sono una storia completamente diversa. Solitamente iterative solvers vengono utilizzati in questi casi. Credo che MATLAB usi UMFPACK e altre librerie correlate dal pacchetto SuiteSpase per i risolutori diretti.

Quando si lavora con matrici sparse, è possibile attivare le informazioni di diagnostica e di vedere i test eseguiti e gli algoritmi scelti utilizzando spparms:

spparms('spumoni',2) 
x = A\b; 

Cosa c'è di più, l'operatore backslash funziona anche su gpuArray 's, nel qual caso si basa su cuBLAS e MAGMA da eseguire sulla GPU.

E 'anche implementato per distributed arrays che funziona in un ambiente di elaborazione distribuito (lavoro diviso in un cluster di computer in cui ogni lavoratore ha solo una parte dell'array, probabilmente dove l'intera matrice non può essere memorizzata in memoria tutto in una volta). L'implementazione sottostante utilizza ScaLAPACK.

Questo è un ordine abbastanza alto se si desidera implementare tutto questo da soli :)

+0

Grazie Amro, è stata una risposta molto costruttiva. "A" è molto probabilmente una matrice non quadrata, quindi, se ho capito bene, il metodo più adatto da usare è la decomposizione QR. E sì, sono disposto a (almeno provare) a implementare ciò che è necessario per creare una libreria un po 'autonoma, quindi non voglio veramente usare altri pacchetti matematici (l'efficienza degli algoritmi è, per il momento, non il mio obiettivo principale;)). È un progetto personale, niente di serio per ora ... – 865719

+2

@ M4XMX: Sì, è possibile utilizzare la decomposizione QR: 'Asse = b -> QRx = b -> Rx = Q'b -> x = R \ (Q'b) '(dove l'ultimo passo è un semplice processo di sostituzione all'indietro). Vedi [qui] (https://inst.eecs.berkeley.edu/~ee127a/book/login/l_lineqs_solving.html) per una spiegazione. Ecco anche una [domanda] correlata (http://stackoverflow.com/q/7949229/97160) che mostra come risolvere 'Ax = b' usando varie librerie: GSL, Armadillo, Eigen. Non c'è bisogno di reinventare la ruota :) – Amro

+2

Penso che MATLAB potrebbe usare anche [pivot] (https://en.wikipedia.org/wiki/QR_decomposition#Column_pivoting) per migliorare la precisione numerica. Questa è la scomposizione: 'AP = QR' dove' P' è una matrice di permutazione – Amro

Problemi correlati