Das Problem ist natürlich die Doppelzählung. Es ist einfach genug, dies für bestimmte Klassen von DAGs zu tun = einen Baum oder sogar einen Seriell-Parallel-Baum. Der einzige Algorithmus, den ich gefunden habe, um allgemeine DAGs in angemessener Zeit zu bearbeiten, ist ein Näherungsalgorithmus (Synopsis Diffusion), aber die Erhöhung der Genauigkeit ist exponentiell in Bezug auf die Anzahl der Bits (und ich benötige viele Bits).
Hintergrund: Diese Aufgabe wird im Rahmen der Wahrscheinlichkeitsberechnung in BBChop (http://github.com/ealdwulf/bbchop), einem Programm zum Auffinden von zeitweiligen Fehlern (dh einer Bayes-Version von ' git bisect '). Die fragliche DAG ist daher eine Revisionshistorie. Dies bedeutet, dass sich die Anzahl der Kanten wahrscheinlich nicht dem Quadrat der Anzahl der Knoten annähert. Es ist wahrscheinlich, dass sie weniger als das k-fache der Anzahl der Knoten für ein kleines k beträgt. Leider habe ich keine anderen nützlichen Eigenschaften von Revisions-DAGs gefunden. Ich hatte zum Beispiel gehofft, dass die größte dreifach verbundene Komponente nur als Quadratwurzel der Anzahl der Knoten wächst, aber leider (zumindest in der Geschichte des Linux-Kernels) wächst sie linear.
Antworten:
Wir gehen davon aus, dass es sich bei den Scheitelpunktgewichten um beliebige positive Ganzzahlen handeln kann, genauer gesagt, um positive Ganzzahlen von höchstens 2 n . Dann kann die aktuelle Aufgabe nicht einmal in einer etwas schwächeren Zeitspanne O ( n 2 ) ausgeführt werden, es sei denn, der transitive Abschluss eines willkürlich gerichteten Graphen kann in O ( n 2 ) berechnet werden, wobei n die Anzahl der Eckpunkte bezeichnet. (Beachten Sie, dass ein O ( n 2 ) -Zeitalgorithmus für den transitiven Verschluss ein Durchbruch sein wird.) Dies ist das Gegenteil der folgenden Behauptung:
Anspruch . Wenn die aktuelle Aufgabe kann in der Zeit O (durchgeführt werden , n 2 ), wobei die transitive Schließung eines gerichteten beliebiges Graphen als Adjazenzmatrix gegeben kann in O berechnet werden ( n 2 ) Zeit (ein vernünftiges Rechenmodell vorausgesetzt).
Beweis . Als Vorverarbeitung berechnen wir die stark zusammenhängende Komponentenzerlegung des gegebenen gerichteten Graphen G in der Zeit O ( n 2 ), um einen DAG G 'zu erhalten. Beachten Sie, dass , wenn wir die transitive Schließung berechnen kann , G ', wir die transitive Schließung rekonstruieren kann G .
Ordnen Sie nun jedem Vertex i der DAG G ' das Gewicht 2 i zu und verwenden Sie den Algorithmus für das aktuelle Problem. Dann beschreibt die binäre Darstellung der jedem Scheitelpunkt i zugeordneten Summe genau die Menge der Vorfahren von i , mit anderen Worten, wir haben den transitiven Abschluss von G ' berechnet . QED .
Die Umkehrung der Behauptung lautet auch: Wenn Sie den transitiven Abschluss einer bestimmten DAG berechnen können, ist es einfach, die erforderlichen Summen durch zusätzliche Arbeit in Zeit O ( n 2 ) zu berechnen . Theoretisch können Sie daher die aktuelle Aufgabe in Zeit O ( n 2.376 ) lösen, indem Sie den Algorithmus für den transitiven Abschluss verwenden, der auf dem Coppersmith-Winograd-Matrixmultiplikationsalgorithmus basiert .
Bearbeiten : Revision 2 und früher haben die Annahme über den Bereich der Scheitelpunktgewichte nicht explizit angegeben. Per Vognsen wies in einem Kommentar darauf hin, dass diese implizite Annahme möglicherweise nicht vernünftig ist (danke!), Und ich stimme zu. Selbst wenn in Anwendungen keine willkürlichen Gewichte benötigt werden, schätze ich, dass diese Antwort einige Ansätze durch die folgende Argumentation ausschließen könnte Die Schließung kann in der Zeit O ( n 2 ) berechnet werden . “
Edit : In Revision 4 und früher wurde die Richtung der Kanten falsch angegeben.
quelle
Dies ist eine Erweiterung meines Kommentars zu Tsuyoshis Antwort. Ich denke, die negative Antwort auf die Frage kann bedingungslos gemacht werden.
Der Punkt scheint zu sein, dass die zugrunde liegende Teilordnung dicht ist, aber die DAG repräsentiert ihre transitive Reduktion, die spärlich sein kann.
quelle
Dies ist falsch und beruht auf einem Missverständnis in der Frage. Vielen Dank an Tsuyoshi, der geduldig auf meinen Fehler hingewiesen hat. Aufgeben, falls andere den gleichen Fehler machen.
Dieser Ansatz sollte auch gut funktionieren, wenn es einige Knoten mit vielen unmittelbaren Vorgängern gibt, sofern sie relativ selten sind.
quelle