2017-08-29 13 views
0

Ich muss viele kleine (n = 4) homogene lineare Systeme der Form Ax = 0 lösen, wobei A eine singuläre Matrix ist. Ich verwende derzeit den folgenden Code:Schnellste Lösung kleiner homogener linearer Systeme mit Eigen

void solve(const matrix_t& A, vector_t& x){ 
    auto svd = A.jacobiSvd(Eigen::ComputeFullU | Eigen::ComputeFullV); 
    auto V = svd.matrixV(); 
    x = V.col(A.rows() - 1); 
    x.normalize(); 
} 

Gibt es schnellere Möglichkeiten, das zu tun?

+0

Das ist ein Maßstab für die verschiedenen Eigenzerlegungen finden Sie hier was ich tun würde. Was ist Ihr Service-Level-Ziel? Haben Sie die Leistung anhand repräsentativer Daten gemessen? Wie verhält sich die Wandzeit des 90. Perzentils mit diesem SLO? – duffymo

+1

Warum fragen Sie nach U, wenn Sie nur V verwenden? Müssen Sie V kopieren? –

+0

@MarcGlisse Sie haben Recht, Computing U ist nicht wirklich nützlich. Ich testete ein paar andere Möglichkeiten und fand heraus, dass die Verwendung von LU oder QR-Dekomposition viel schneller ist. Haben diese irgendwelche Nachteile? – dari

Antwort

3

Der schnellste Weg, um den Nullraum einer allgemeinen Matrix mit Eigen zu erhalten, ist die Verwendung seiner LU-Zerlegung. In der Praxis verwende ich die Householder-QR-Zerlegung anstelle von LU, weil sie stabiler zu sein scheint, wenn die Eingabematrix nicht perfekt singulär ist. QR ist immer noch viel schneller als die in der Frage vorgeschlagene SVD und gibt sehr ähnliche Ergebnisse für meine Probleme. https://eigen.tuxfamily.org/dox/group__DenseDecompositionBenchmark.html

-Code zur Berechnung der Nullraum mit LU, QR und SVD (Anmerkung: x.normalize() ist nicht erforderlich, aber hilfreich zum Vergleich die Lösungen):

template<typename matrix_t, typename vector_t> 
void solveNullspaceLU(const matrix_t& A, vector_t& x){ 
    x = A.fullPivLu().kernel(); 
    x.normalize(); 
} 

template<typename matrix_t, typename vector_t> 
void solveNullspaceQR(const matrix_t& A, vector_t& x){ 
    auto qr = A.transpose().colPivHouseholderQr(); 
    matrix_t Q = qr.householderQ(); 
    x = Q.col(A.rows() - 1); 
    x.normalize(); 
} 

template<typename matrix_t, typename vector_t> 
void solveNullspaceSVD(const matrix_t& A, vector_t& x){ 
    x = A.jacobiSvd(Eigen::ComputeFullV).matrixV().col(A.rows() - 1); 
    x.normalize(); 
}