Hat jemand von euch jemals einen Fibonacci-Heap implementiert ? Ich habe dies vor ein paar Jahren getan, aber es war mehrere Größenordnungen langsamer als die Verwendung von Array-basierten BinHeaps.
Damals hielt ich es für eine wertvolle Lektion, wie Forschung nicht immer so gut ist, wie sie behauptet. Viele Forschungsarbeiten behaupten jedoch, dass die Laufzeiten ihrer Algorithmen auf der Verwendung eines Fibonacci-Heaps basieren.
Haben Sie jemals eine effiziente Implementierung erreicht? Oder haben Sie mit Datensätzen gearbeitet, die so groß waren, dass der Fibonacci-Heap effizienter war? Wenn ja, würden einige Details geschätzt.
Antworten:
Die Boost C ++ - Bibliotheken enthalten eine Implementierung von Fibonacci-Heaps inboost/pending/fibonacci_heap.hpp
. Diese Datei ist anscheinend seitpending/
Jahren in und wird von meinen Projektionen nie akzeptiert. Außerdem gab es Fehler in dieser Implementierung, die von meinem Bekannten und rundum coolen Aaron Windsor behoben wurden. Leider hatten die meisten Versionen dieser Datei, die ich online finden konnte (und die in Ubuntus libboost-dev-Paket), immer noch die Fehler; Ich musste eine saubere Version aus dem Subversion-Repository ziehen.Seit Version 1.49 haben Boost C ++ - Bibliotheken viele neue Heap-Strukturen hinzugefügt, einschließlich Fibonacci-Heap.
Ich konnte dijkstra_heap_performance.cpp gegen eine modifizierte Version von dijkstra_shortest_paths.hpp kompilieren , um Fibonacci-Heaps und binäre Heaps zu vergleichen. (
typedef relaxed_heap<Vertex, IndirectCmp, IndexMap> MutableQueue
Wechseln Sierelaxed
in der Zeile zufibonacci
.) Ich habe zuerst vergessen, mit Optimierungen zu kompilieren. In diesem Fall funktionieren Fibonacci-Heaps und binäre Heaps ungefähr gleich, wobei Fibonacci-Heaps normalerweise eine unbedeutende Leistung erbringen. Nachdem ich mit sehr starken Optimierungen kompiliert hatte, erhielten binäre Heaps einen enormen Schub. In meinen Tests übertrafen Fibonacci-Heaps nur dann binäre Heaps, wenn der Graph unglaublich groß und dicht war, z.Soweit ich weiß, berührt dies die grundlegenden Unterschiede zwischen Fibonacci-Haufen und binären Haufen. Der einzige wirkliche theoretische Unterschied zwischen den beiden Datenstrukturen besteht darin, dass Fibonacci-Haufen die Abnahme des Schlüssels in (amortisierter) konstanter Zeit unterstützen. Auf der anderen Seite erzielen binäre Heaps durch ihre Implementierung als Array eine hohe Leistung. Die Verwendung einer expliziten Zeigerstruktur bedeutet, dass Fibonacci-Haufen einen enormen Leistungseinbruch erleiden.
Um von Fibonacci-Haufen in der Praxis zu profitieren , müssen Sie sie daher in einer Anwendung verwenden, in der Abnahmeschlüssel unglaublich häufig sind. In Bezug auf Dijkstra bedeutet dies, dass der zugrunde liegende Graph dicht ist. Einige Anwendungen können von Natur aus abnehmungsintensiv sein. Ich wollte den Nagomochi-Ibaraki-Minimum-Cut-Algorithmus ausprobieren, da er anscheinend viele Abnahmeschlüssel generiert, aber es war zu aufwendig , einen Timing-Vergleich zum Laufen zu bringen.
Warnung : Ich habe möglicherweise etwas falsch gemacht. Möglicherweise möchten Sie versuchen, diese Ergebnisse selbst zu reproduzieren.
Theoretischer Hinweis : Die verbesserte Leistung von Fibonacci-Heaps auf minus_key ist wichtig für theoretische Anwendungen wie die Laufzeit von Dijkstra. Fibonacci-Heaps übertreffen auch binäre Heaps beim Einfügen und Zusammenführen (beide amortisierte konstante Zeit für Fibonacci-Heaps). Das Einfügen ist im Wesentlichen irrelevant, da es die Laufzeit von Dijkstra nicht beeinflusst und es ziemlich einfach ist, binäre Heaps so zu ändern, dass sie auch in einer amortisierten konstanten Zeit eingefügt werden. Das Zusammenführen in konstanter Zeit ist fantastisch, aber für diese Anwendung nicht relevant.
Persönliche Anmerkung : Ein Freund von mir und ich haben einmal ein Papier geschrieben, in dem eine neue Prioritätswarteschlange erklärt wurde, in der versucht wurde, die (theoretische) Laufzeit von Fibonacci-Haufen ohne deren Komplexität zu replizieren. Das Papier wurde nie veröffentlicht, aber mein Co-Autor hat binäre Heaps, Fibonacci-Heaps und unsere eigene Prioritätswarteschlange implementiert, um die Datenstrukturen zu vergleichen. Die Grafiken der experimentellen Ergebnisse zeigen, dass Fibonacci-Heaps die binären Heaps in Bezug auf Gesamtvergleiche leicht übertrafen, was darauf hindeutet, dass Fibonacci-Heaps in einer Situation, in der die Vergleichskosten den Overhead übersteigen, eine bessere Leistung erbringen würden. Leider habe ich den Code nicht zur Verfügung und vermutlich ist der Vergleich in Ihrer Situation billig, daher sind diese Kommentare relevant, aber nicht direkt anwendbar.
Im Übrigen empfehle ich dringend, die Laufzeit von Fibonacci-Heaps mit Ihrer eigenen Datenstruktur abzugleichen. Ich fand heraus, dass ich Fibonacci-Haufen einfach neu erfunden habe. Früher dachte ich, dass alle Komplexitäten von Fibonacci-Haufen zufällige Ideen waren, aber danach wurde mir klar, dass sie alle natürlich und ziemlich erzwungen waren.
quelle
Knuth führte 1993 für sein Buch Stanford Graphbase einen Vergleich zwischen Fibonacci-Haufen und binären Haufen für minimale Spannbäume durch . Er fand, dass Fibonacci bei den von ihm getesteten Graphengrößen 30 bis 60 Prozent langsamer sind als binäre Haufen, 128 Eckpunkte bei verschiedenen Dichten.
Der Quellcode befindet sich in C (oder besser CWEB, eine Kreuzung zwischen C, Mathe und TeX) im Abschnitt MILES_SPAN.
quelle
Haftungsausschluss
Ich weiß, dass die Ergebnisse ziemlich ähnlich sind und "die Laufzeit anscheinend völlig von etwas anderem als dem Haufen dominiert wird" (@Alpedar). Aber ich konnte im Code keine Beweise dafür finden. Der Code ist offen. Wenn Sie also etwas finden, das das Testergebnis beeinflussen kann, sagen Sie es mir bitte.
Vielleicht habe ich etwas falsch gemacht, aber ich habe einen Test geschrieben , der auf dem Vergleich von A.Rex antwortet basiert :
Die Ausführungszeiten (nur für vollständige Diagramme) für alle Heaps waren sehr eng. Der Test wurde für vollständige Diagramme mit 1000,2000,3000,4000,5000,6000,7000 und 8000 Eckpunkten durchgeführt. Für jeden Test wurden 50 zufällige Diagramme erstellt und die Ausgabe ist die durchschnittliche Zeit jedes Heaps:
Entschuldigung für die Ausgabe, sie ist nicht sehr ausführlich, da ich sie brauchte, um einige Diagramme aus Textdateien zu erstellen.
Hier sind die Ergebnisse (in Sekunden):
quelle
Ich habe auch ein kleines Experiment mit Fibonacci-Haufen gemacht. Hier ist der Link für die Details: Experimentieren mit dem Dijkstras-Algorithmus . Ich habe gerade die Begriffe "Fibonacci-Heap-Java" gegoogelt und einige vorhandene Open-Source-Implementierungen des Fibonacci-Heaps ausprobiert. Es scheint, dass einige von ihnen Leistungsprobleme haben, aber es gibt einige, die ziemlich gut sind. Zumindest übertreffen sie in meinem Test die naive und die binäre Heap-PQ-Leistung. Vielleicht können sie helfen, die effiziente umzusetzen.
quelle