rozwiąż

12

Przenoszę istniejący kod z MATLAB do C ++ i mam liniowy system do rozwiązania (zamiast bardziej typowej formy A x = b )xZA=bZAx=b

Matryca jest gęsta i ma ogólną formę, ale nie jest większa niż 1000 x 1000. Tak więc w MATLAB rozwiązaniem jest funkcja lub notacja ukośnika do przoduZAmrdivide(b,A)x = b/A;

Jak mam rozwiązać ten problem w kodzie C ++ przy użyciu procedur BLAS i LAPACK?

Znam procedurę LAPACK, DGESVktóra rozwiązuje dla x .ZAx=bx

Jedną z moich myśli było wykonanie pewnych manipulacji przy użyciu macierzy transponujących tożsamość:

(xZA)T.=bT.

ZAT.xT.=bT.

xT.=(ZAT.)-1bT.

Następnie rozwiązać ostateczny kształt za pomocą DGESVdziałających na transponowana . (więc koszt transpozycji A i koszt rozwiązania systemu)ZAT.ZA

Czy istnieje podejście bardziej wydajne lub w inny sposób lepsze ?

Pracuję z klasami macierzy i wektorów, a także implementacją BLAS z biblioteki BOOST uBLAS, a także powiązaniami z procedurami biblioteki LAPACK. Korzystałem z tej konfiguracji z powodzeniem do innych operacji i mam nadzieję znaleźć rozwiązanie ograniczone do tych bibliotek.

Powinienem również zauważyć, że wykonuję ten typ operacji tylko kilka razy podczas konfiguracji kodu, więc wydajność nie jest krytyczna.

Może to MATLAB dokumentacja na mrdivideto pomocne dla innych.

NoahR
źródło

Odpowiedzi:

10

Trywialna odpowiedź dla kwadratu : zastosowanie, które rozwiązuje również dla A T x = b kiedy .ZAdgesvxZAT.x=bTRANS = 'T'

Należy pamiętać, że w przypadku BLAS lub LAPACK prawie nie trzeba transponować (zamieniać elementów w pamięci) macierzy: większość podprogramów ma TRANSargument umożliwiający działanie na macierzy transpozycji lub na macierzy przechowywanej z innym układem pamięci. (Transpozycja jest równoważna zmianie układu pamięci ciągłej Fortran na C-contiguos i viceversa.)

Stefano M.
źródło
Dzięki za odpowiedź i wyjaśnienie! Z LAPACK wykonałem bardzo mało pracy i teraz wiem, jak szukać opcji TRANS. Mam problem z przepracowaniem argumentu TRANS boost::numeric::bindings::lapack::gesvx(), ale to nie jest część mojego pytania tutaj. Jeśli mi się uda, wrócę z notatką, jak to zrobić.
NoahR
Mam działające rozwiązanie gesvx(), ale nie bez przeszkód po drodze. Gdy argumentem TRANS jest „T”, dokumentacja LAPACK mówi, że gesvxrozwiązuje , ale tak naprawdę rozwiązuje A T X T = B T, ponieważ oczekuje się, że postać argumentów wejściowych X i B nie będzie transponowana Formularz. Tak więc argument A jest transponowany, podczas gdy X i BZAT.X=bZAT.XT.=bT.XbZAXbnie są. Świetnie, to wygodniejsze. Jeśli ktoś inny natknie się na to, próbując użyć powiązań numerycznych boost, powiem, że nie byłem w stanie uzyskać interfejsu transpozycji używanego w tym rozwiązaniu. pracować przez powiązania.
NoahR
Ok, znalazłem sposób na skorzystanie z gesvxformularza transpozycji boost::numeric::bindings. Zawiń transponowaną macierz w funkcji. To identyfikuje parametr jako typ transpozycji : ZAT.trans()boost::numeric::bindings::lapack::gesvx( FACT, boost::numeric::bindings::trans(Atransposed), af, ipiv, equed, r, c, b, x, rcond, ferr, berr );
NoahR
0

Możesz obliczyć pseudo odwrotność , używając powiedzmy dekompozycji SVD, które są zawarte w LAPACK.ZA

xZA=bxQR=bx=bR-1QT.

ZA

Gil
źródło
3
ZARR-1