Problemem jest oczywiście podwójne liczenie. Jest to dość łatwe dla niektórych klas DAG = drzewo, a nawet drzewo szeregowo-równoległe. Jedynym algorytmem, który znalazłem, który działa na ogólnych DAG w rozsądnym czasie, jest przybliżony (dyfuzja streszczenia), ale zwiększenie jego precyzji jest wykładnicze pod względem liczby bitów (i potrzebuję dużo bitów).
Tło: to zadanie jest wykonywane (kilka razy z różnymi „wagami”) w ramach obliczeń prawdopodobieństwa w BBChop (http://github.com/ealdwulf/bbchop) program do znajdowania przerywanych błędów (tj. Bayesowska wersja „ git bisect ”). Wspomniany DAG jest zatem historią zmian. Oznacza to, że liczba krawędzi prawdopodobnie nie zbliży się do kwadratu liczby węzłów, prawdopodobnie będzie mniejsza niż k razy liczba węzłów dla niektórych małych k. Niestety nie znalazłem żadnych innych użytecznych właściwości DAG wersji. Miałem na przykład nadzieję, że największy trójpodłączony komponent wzrośnie tylko jako pierwiastek kwadratowy z liczby węzłów, ale niestety (przynajmniej w historii jądra Linuksa) rośnie liniowo.
Odpowiedzi:
Zakładamy, że wagi wierzchołków mogą być dowolnymi dodatnimi liczbami całkowitymi, a dokładniej, mogą być dodatnimi liczbami całkowitymi co najwyżej 2 n . Wówczas bieżące zadanie nie może być wykonane nawet w nieco słabszym przedziale czasowym O ( n 2 ), chyba że przechodnie przechodzenie dowolnego ukierunkowanego wykresu można obliczyć w czasie O ( n 2 ), gdzie n oznacza liczbę wierzchołków. (Należy zauważyć, że algorytm czasowy O ( n 2 ) dla zamknięcia przechodniego będzie przełomem.) Jest to przeciwieństwo następującego twierdzenia:
Roszczenie . Jeśli bieżące zadanie można wykonać w czasie O ( n 2 ), przechodnie przechodzenie dowolnego ukierunkowanego wykresu podanego jako jego macierz przylegania można obliczyć w czasie O ( n 2 ) (przy założeniu pewnego rozsądnego modelu obliczeniowego).
Dowód . W ramach przetwarzania wstępnego obliczamy silnie połączony rozkład składowy danego ukierunkowanego wykresu G w czasie O ( n 2 ), aby otrzymać DAG G '. Zauważ, że jeśli możemy obliczyć przechodnie zamknięcie G ', możemy zrekonstruować przechodnie zamknięcie G' .
Teraz przypisz wagę 2 i do każdego wierzchołka i DAG G 'i użyj algorytmu dla bieżącego problemu. Następnie binarna reprezentacja sumy przypisanej do każdego wierzchołka i opisuje dokładnie zbiór przodków i , innymi słowy, obliczyliśmy przechodnie zamknięcie G '. QED .
Odwrotne jest również twierdzenie: jeśli możesz obliczyć przechodnie zamknięcie danego DAG, łatwo jest obliczyć wymagane sumy przez dodatkową pracę w czasie O ( n 2 ). Dlatego teoretycznie można osiągnąć bieżące zadanie w czasie O ( n 2.376 ), stosując algorytm do przechodzenia w oparciu o algorytm mnożenia macierzy Coppersmitha-Winograda .
Edycja : Wersja 2 i wcześniejsze nie zawierały wyraźnego założenia dotyczącego zakresu wag wierzchołków. Per Vognsen zauważył w komentarzu, że to domniemane założenie może nie być rozsądne (dzięki!) I zgadzam się. Nawet jeśli w aplikacjach nie są potrzebne arbitralne wagi, myślę, że ta odpowiedź może wykluczyć niektóre podejścia według następującego rozumowania: „Jeśli to podejście zadziałałoby, dałoby algorytm dla dowolnych wag, co jest wykluczone, chyba że przechodni zamknięcie można obliczyć w czasie O ( n 2 ). ”
Edycja : Wersja 4 i wcześniejsze nieprawidłowo podały kierunek krawędzi.
źródło
Jest to rozwinięcie mojego komentarza do odpowiedzi Tsuyoshi. Myślę, że negatywną odpowiedź na pytanie można uczynić bezwarunkową.
Chodzi o to, że leżący u podstaw porządek częściowy jest gęsty, ale DAG reprezentuje redukcję przechodnią, która może być rzadka.
źródło
To jest złe i opiera się na nieporozumieniu w kwestii. Dzięki Tsuyoshi za cierpliwe zwrócenie uwagi na mój błąd. Pozostawienie na wypadek, gdyby inni popełnili ten sam błąd.
Takie podejście powinno również działać dobrze, jeśli istnieje kilka węzłów z wieloma bezpośrednimi poprzednikami, o ile są one stosunkowo rzadkie.
źródło