Dano mi macierz , która jest symetryczna, odwracalna, dodatnia określona i gęsta. Muszę sprawdzić, czy gdzie J jest macierzą wszystkich jedynek.Q det ( Q ) = det ( 12 I - Q - J )J
Obecnie robię to z biblioteką pancernika, ale okazuje się, że jest zbyt wolny. Chodzi o to, że muszę to zrobić dla tryliona macierzy i okazuje się, że obliczenie dwóch wyznaczników jest wąskim gardłem mojego programu. Dlatego mam dwa pytania
Czy jest jakiś sposób na szybsze obliczenie wyznacznika, biorąc pod uwagę jego wielkość? Czy być może niechlujne rozszerzenie dla macierzy , które mogłoby działać w tym przypadku?
Czy istnieje jakiś inny skuteczny sposób sprawdzenia równości
Edytować. Aby odpowiedzieć na komentarze. Muszę obliczyć wszystkie połączone niekomplementarne wykresy rzędu tak aby i miały tę samą liczbę drzew rozpinających. Motywację do tego można znaleźć w tym poście mathoverflow . Jeśli chodzi o maszynę, to równolegle pracuję na 8-rdzeniowej maszynie 3.4GHh.
Edytować. Udało mi się zmniejszyć oczekiwany czas działania o 50%, tworząc program C do specyficznego obliczania wyznacznika macierzy . Sugestie są nadal mile widziane.
źródło
Odpowiedzi:
Ponieważ już używasz C ++, a twoje macierze są symetryczne dodatnio określone, wykonałbym niepodzielną faktoryzację dla a także dla Q 12 I - Q - J 12 I - Q - J L D L TL D LT. Q 12 I- Q - J . Tutaj że jest również dodatnio określony, w przeciwnym razie będzie wymagał obrotu dla stabilności numerycznej (możliwe jest również, że nawet jeśli nie jest to wartość dodatnia, nie jest konieczne, ale musisz spróbować).12 I- Q - J L D LT.
Jest to szybsze niż faktoryzacja LU, a także szybsze niż Cholesky, ponieważ unika się pierwiastków kwadratowych. Wyznacznik jest po prostu iloczynem elementów diagonalnej macierzyKod do faktoryzacji LDL jest tak prosty, że możesz napisać go w mniej niż 50 liniach C. Strona WikipediiL D L Tre na to opisuje algorytm, i mam kilka prostych matrycy kod do zrobienia Cholesky tutaj . Możesz to znacznie uprościć i zmodyfikować, aby uniknąć pierwiastka kwadratowego w celu zaimplementowania faktoryzacjiL D LT.
Ponieważ możesz także kontrolować format przechowywania, możesz dalej optymalizować procedurę, aby przechowywać tylko połowę macierzy i pakować ją w szyk liniowy, aby zmaksymalizować lokalizację pamięci. Napisałbym również prosty niestandardowy produkt kropkowy i procedury aktualizacji rangi 1, ponieważ rozmiary problemów są tak małe, że powinieneś pozwolić kompilatorowi na wprowadzenie procedur, aby zmniejszyć obciążenie połączeń. Ponieważ jest to pętla o stałym rozmiarze, kompilator powinien mieć możliwość automatycznego wstawiania i rozwijania elementów w razie potrzeby.
Unikałbym próbowania sztuczek, aby wykorzystać fakt, że zawiera w wyrażeniu. Jest prawdopodobne, że przy tak małych rozmiarach problemów sztuczki te są wolniejsze niż po prostu wykonywanie dwóch oddzielnych obliczeń determinant. Oczywiście jedynym sposobem na zweryfikowanie tych twierdzeń jest wypróbowanie ich.Q12 I- Q - J Q
źródło
Bez pewnych informacji na temat budowy tych pozytywnych określonych rzeczywistych macierzy symetrycznych, sugestie, które należy poczynić, są z konieczności dość ograniczone.12 × 12
Pobrałem pakiet Armadillo z Sourceforge i przejrzałem dokumentację. Postaraj się poprawić wydajność osobnego obliczania i , gdzie jest macierzą pierwszego rzędu wszystkich, ustawiając np . Dokumentacja zauważa, że jest to ustawienie domyślne dla macierzy do rozmiaru , więc przez pominięcie zakładam, że opcja jest domyślna dladet ( 12 Idet ( Q ) J 4 × 4 12 × 12det ( 12 I- Q - J) jot 4 × 4 12 × 12 .
det(Q,slow=false)
slow=true
To, coQ 12 × 12 wyznacznik zostanie wykonany, ponieważ obliczenia zostaną „przerzucone przez ścianę” do LAPACK (lub ATLAS) w tym punkcie bez wskazania, że obrót nie jest wymagany; widzieć
slow=true
przypuszczalnie działa, to częściowe lub pełne obrócenie w celu uzyskania formy rzutu rzędowego, z której łatwo można znaleźć wyznacznik. Jakkolwiek wiesz z góry, macierz jest pozytywnie określona, więc obrót nie jest konieczny dla stabilności (przynajmniej przypuszczalnie dla większości twoich obliczeń. Nie jest jasne, czy pakiet Armadillo rzuca wyjątek, jeśli osie stają się zbyt małe, ale powinno to być cecha rozsądnego numerycznego pakietu algebry liniowej EDYCJA: Znalazłem kod Armadillo, który implementuje się w pliku nagłówkowym , używając szablonów C ++ dla znacznej funkcjonalności.12 × 12det
include\armadillo_bits\auxlib_meat.hpp
slow=false
nie wpływa na to, jakdet_lapack
i jego wywołania w tym pliku.Inną kwestią byłoby zastosowanie się do ich zalecenia budowy pakietu Armadillo łączącego szybkie zamienniki BLAS i LAPACK, jeśli rzeczywiście ich używasz; patrz ust. 5 pliku README.TXT Armadillo, aby uzyskać szczegółowe informacje. [Użycie dedykowanej 64-bitowej wersji BLAS lub LAPACK jest również zalecane ze względu na szybkość na obecnych komputerach 64-bitowych.]
Redukcja wiersza do postaci ekhelona jest zasadniczo eliminacją Gaussa i ma złożoność arytmetyczną . W przypadku obu macierzy stanowi to dwukrotność tej pracy lub . Operacje te mogą być „wąskim gardłem” w przetwarzaniu, ale nie ma nadziei, że bez specjalnej struktury w (lub niektórych znanych zależności między trylionami przypadków testowych umożliwiających amortyzację) praca mogłaby zostać zredukowana do42)3)n3)+ O ( n2)) Q O ( n 2 )43)n3)+ O ( n2)) Q O ( n2)) .
Dla porównania, ekspansja przez kofaktory ogólnej macierzy obejmujeoperacje mnożenia (i mniej więcej tyle samo dodawania / odejmowania), więc dla porównanie ( vs. ) wyraźnie sprzyja eliminacji nad kofaktorami.n ! n = 12 12 ! = 479001600 2n × n n ! n = 12 12 ! = 479001600 2)3)n3)= 1152
Innym podejściem wymagającym pracy byłoby sprowadzenie do postaci tridiagonalnej za pomocą transformacji Householdera, co również nadaje formie tridiagonal. Obliczenia i można następnie wykonać w operacjach . [Wpływ aktualizacji rangi 1 na drugą determinantę można wyrazić jako czynnik skalarny podany przez rozwiązanie jednego układu trójosiowego.]Q12I-Qdet(Q)det(12I43)n3)+ O ( n2)) Q 12I−Q det(Q) O ( n ) - Jdet(12I−Q−J) O(n) −J
Wdrożenie takiego niezależnego obliczenia może być przydatne jako sprawdzenie wyników udanych (lub nieudanych) wywołań
det
funkcji Armadillo .Przypadek specjalny: jak sugeruje Komentarz Jernej, załóżmy, że gdzie jak poprzednio, jest macierzą (rangi 1) wszystkich, a jest macierz niepołączona (dodatnia). Rzeczywiście dla proponowanego zastosowania w teorii grafów byłyby to macierze całkowite. Następnie wyraźna formuła dlaJ DQ=D−J J det ( Q )D=diag(d1,…,dn) det(Q) to:
Szkic dowodu daje możliwość zilustrowania szerszego zastosowania, tj. Ilekroć ma znaną determinantę, a układ jest szybko rozwiązywany. Zacznij od faktorowania:D v = ( 1 … 1 ) TD Dv=(1…1)T
Teraz znów zajmuje 1 pozycję, a mianowicie( d - 1 1 …D−1J (d−11…d−1n)T(1…1) . Zauważ, że drugą determinantą jest po prostu:
gdzie jest charakterystyczny wielomianem . Jako macierz rangi 1, musi mieć (co najmniej) czynniki aby uwzględnić jej pustą przestrzeń. „Brakująca” wartość własna to , jak można zobaczyć na podstawie obliczeń:D - 1 J f ( x ) n - 1f(x) D−1J f(x) n−1 ∑ d - 1 ix ∑d−1i
Wynika z tego, że charakterystyczny wielomian , a jest taki jak pokazano powyżej dla , .f ( 1 ) det ( I - D - 1 J ) 1 - ∑ d - 1 if(x)=xn−1(x−∑d−1i) f(1) det(I−D−1J) 1−∑d−1i
Zauważ też, że jeśli , to , macierz diagonalna, której wyznacznikiem jest po prostu iloczyn jej wpisów diagonalnych.12 I -Q=D−J 12I−Q−J=12I−D+J−J=12I−D
źródło
Jeśli masz uporządkowany sposób wyliczania wykresów, które chcesz obliczyć wyznaczniki, być może znajdziesz aktualizacje niskiej rangi, które przenoszą cię z jednego wykresu na drugi.
Jeśli tak, to możesz użyć lematu wyznacznika macierzy, aby tanio obliczyć wyznacznik kolejnego wykresu, który ma być zliczony, korzystając z wiedzy o wyznaczniku bieżącego wykresu.
To znaczy, dla macierzy i wektorów : Można to uogólnić, jeśli U i V są macierzy, a jest :A u,v det(A+uvT)=(1+vTA−1u)det(A) n×m A n×n det(A+UVT)=det(Im+VTA−1U)det(A)
Aby efektywnie obliczyć odwrotność, możesz użyć wzoru Shermana-Morrisona, aby uzyskać odwrotność kolejnej macierzy z bieżącej:(A+uvT)−1=A−1−A−1uvTA−11+vTA−1u
źródło