Le librerie Boost C ++ includono un'implementazione di heap di Fibonacci in boost/pending/fibonacci_heap.hpp
. A quanto pare questo file esiste pending/
da anni e dalle mie proiezioni non sarà mai accettato. Inoltre, ci sono stati dei bug in quell'implementazione, che sono stati corretti dalla mia conoscenza e dal bravissimo Aaron Windsor. Sfortunatamente, la maggior parte delle versioni di quel file che ho trovato online (e quella nel pacchetto libboost-dev di Ubuntu) aveva ancora i bug; Ho dovuto estrarre una versione pulita dal repository Subversion.
Dalla versione 1.49 Boost le librerie C ++ hanno aggiunto molte nuove strutture heap, incluso l'heap fibonacci.
Sono stato in grado di compilare dijkstra_heap_performance.cpp rispetto a una versione modificata di dijkstra_shortest_paths.hpp per confrontare heap di Fibonacci e heap binari. (Nella riga typedef relaxed_heap<Vertex, IndirectCmp, IndexMap> MutableQueue
, relaxed
passa a fibonacci
.) Ho prima dimenticato di compilare con ottimizzazioni, nel qual caso Fibonacci e heap binari si comportano allo stesso modo, con gli heap di Fibonacci che di solito superano di un importo insignificante. Dopo aver compilato con ottimizzazioni molto forti, i cumuli binari hanno avuto un enorme incremento. Nei miei test, i mucchi di Fibonacci hanno sovraperformato i cumuli binari solo quando il grafico era incredibilmente grande e denso, ad esempio:
Generating graph...10000 vertices, 20000000 edges.
Running Dijkstra's with binary heap...1.46 seconds.
Running Dijkstra's with Fibonacci heap...1.31 seconds.
Speedup = 1.1145.
Per quanto ho capito, ciò tocca le differenze fondamentali tra i cumuli di Fibonacci e i cumuli binari. L'unica vera differenza teorica tra le due strutture di dati è che i cumuli di Fibonacci supportano il tasto di riduzione nel tempo costante (ammortizzato). D'altra parte, gli heap binari ottengono grandi prestazioni dalla loro implementazione come array; l'utilizzo di una struttura di puntatore esplicita significa che i cumuli di Fibonacci subiscono un enorme impatto sulle prestazioni.
Pertanto, per beneficiare in pratica dei cumuli di Fibonacci , è necessario utilizzarli in un'applicazione in cui i metodi diminuzioni sono incredibilmente frequenti. In termini di Dijkstra, ciò significa che il grafico sottostante è denso. Alcune applicazioni potrebbero essere intrinsecamente diminuire_intenso-chiave; Volevo provare l'algoritmo di taglio minimo Nagomochi-Ibaraki perché a quanto pare genera un sacco di tasti di riduzione, ma è stato uno sforzo eccessivo per far funzionare un confronto di temporizzazione.
Attenzione : potrei aver fatto qualcosa di sbagliato. Potresti provare a riprodurre questi risultati da solo.
Nota teorica : il miglioramento delle prestazioni degli heap di Fibonacci su dimin_key è importante per le applicazioni teoriche, come il tempo di esecuzione di Dijkstra. I cumuli di Fibonacci superano anche i cumuli binari per inserimento e fusione (entrambi ammortizzati a tempo costante per i cumuli di Fibonacci). L'inserimento è essenzialmente irrilevante, perché non influisce sul tempo di esecuzione di Dijkstra ed è abbastanza facile modificare gli heap binari per avere anche l'inserimento in un tempo costante ammortizzato. Unire a tempo costante è fantastico, ma non pertinente per questa applicazione.
Nota personale : un mio amico e una volta abbiamo scritto un documento in cui spiegava una nuova coda prioritaria, che tentava di replicare il tempo (teorico) di funzionamento dei cumuli di Fibonacci senza la loro complessità. Il documento non è mai stato pubblicato, ma il mio coautore ha implementato heap binari, heap di Fibonacci e la nostra coda di priorità per confrontare le strutture di dati. I grafici dei risultati sperimentali indicano che Fibonacci ha accumulato cumuli binari leggermente superati in termini di confronti totali, suggerendo che i cumuli di Fibonacci avrebbero prestazioni migliori in una situazione in cui il costo del confronto supera le spese generali. Sfortunatamente, non ho il codice disponibile e presumibilmente nel confronto della tua situazione è economico, quindi questi commenti sono rilevanti ma non direttamente applicabili.
Per inciso, consiglio vivamente di provare ad abbinare il tempo di esecuzione degli heap di Fibonacci con la propria struttura di dati. Ho scoperto che ho semplicemente reinventato il mucchio di Fibonacci da solo. Prima pensavo che tutte le complessità dei cumuli di Fibonacci fossero idee casuali, ma in seguito mi sono reso conto che erano tutte naturali e abbastanza forzate.