Adakah yang benar-benar mengimplementasikan Fibonacci-Heap secara efisien?

151

Apakah ada di antara Anda yang pernah menerapkan Fibonacci-Heap ? Saya melakukannya beberapa tahun yang lalu, tapi beberapa kali lipat lebih lambat daripada menggunakan BinHeaps berbasis array.

Saat itu, saya menganggapnya sebagai pelajaran berharga tentang bagaimana penelitian tidak selalu sebagus seperti yang diklaim. Namun, banyak makalah penelitian mengklaim waktu menjalankan algoritma mereka berdasarkan menggunakan Fibonacci-Heap.

Apakah Anda pernah berhasil menghasilkan implementasi yang efisien? Atau apakah Anda bekerja dengan set data yang sangat besar sehingga Fibonacci-Heap lebih efisien? Jika demikian, beberapa detail akan dihargai.

mdm
sumber
25
Apakah Anda tidak tahu algoritma ini dudes selalu menyembunyikan konstanta besar mereka di belakang besar mereka yang besar oh ?! :) Sepertinya dalam prakteknya, sebagian besar waktu, "n" tidak pernah mendekati "n0"!
Mehrdad Afshari
Saya tahu sekarang. Saya menerapkannya ketika saya pertama kali mendapatkan salinan "Pengantar Algoritma". Juga, saya tidak memilih Tarjan untuk seseorang yang akan menemukan struktur data yang tidak berguna, karena Splay-Trees-nya sebenarnya cukup keren.
mdm
mdm: Tentu saja itu tidak sia-sia, tetapi seperti jenis penyisipan yang mengalahkan quicksort dalam kumpulan data kecil, tumpukan biner mungkin bekerja lebih baik karena konstanta yang lebih kecil.
Mehrdad Afshari
1
Sebenarnya, program yang saya butuhkan adalah heap untuk menemukan Steiner-Trees untuk routing dalam VLSI-chips, jadi set data tidak terlalu kecil. Tetapi saat ini (kecuali untuk hal-hal sederhana seperti penyortiran) saya akan selalu menggunakan algoritma yang lebih sederhana sampai "istirahat" pada kumpulan data.
mdm
1
Jawaban saya untuk ini sebenarnya "ya". (Ya, rekan penulis saya di atas kertas melakukannya.) Saya tidak memiliki kode sekarang, jadi saya akan mendapatkan lebih banyak info sebelum saya benar-benar merespons. Melihat grafik kami, bagaimanapun, saya perhatikan bahwa tumpukan F membuat perbandingan lebih sedikit daripada b tumpukan. Apakah Anda menggunakan sesuatu yang perbandingannya murah?
A. Rex

Jawaban:

136

The Meningkatkan C ++ perpustakaan mencakup implementasi tumpukan Fibonacci di boost/pending/fibonacci_heap.hpp. File ini tampaknya sudah pending/bertahun-tahun dan dengan proyeksi saya tidak akan pernah diterima. Juga, ada bug dalam implementasi itu, yang diperbaiki oleh kenalan saya dan cowok keren yang serba bisa, Aaron Windsor. Sayangnya, sebagian besar versi file itu yang dapat saya temukan online (dan yang ada di paket libboost-dev Ubuntu) masih memiliki bug; Saya harus menarik versi bersih dari repositori Subversion.

Sejak versi 1.49 Boost C ++ libraries menambahkan banyak heaps struct baru termasuk fibonacci heap.

Saya dapat mengkompilasi dijkstra_heap_performance.cpp terhadap versi modifikasi dari dijkstra_shortest_paths.hpp untuk membandingkan tumpukan Fibonacci dan tumpukan biner. (Sejalan typedef relaxed_heap<Vertex, IndirectCmp, IndexMap> MutableQueue, ubah relaxedmenjadi fibonacci.) Saya pertama kali lupa mengkompilasi dengan optimisasi, dalam hal ini Fibonacci dan tumpukan biner berkinerja sama, dengan tumpukan Fibonacci biasanya mengungguli dengan jumlah yang tidak signifikan. Setelah saya kompilasi dengan optimasi yang sangat kuat, tumpukan biner mendapat dorongan besar. Dalam pengujian saya, Fibonacci tumpukan hanya mengungguli tumpukan biner ketika grafik sangat besar dan padat, misalnya:

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.

Sejauh yang saya mengerti, ini menyentuh perbedaan mendasar antara tumpukan Fibonacci dan tumpukan biner. Satu-satunya perbedaan teoretis nyata antara kedua struktur data adalah bahwa tumpukan Fibonacci mendukung penurunan kunci dalam waktu konstan (diamortisasi). Di sisi lain, tumpukan biner mendapatkan banyak kinerja dari implementasi mereka sebagai sebuah array; menggunakan struktur penunjuk eksplisit berarti tumpukan Fibonacci mengalami pukulan kinerja yang sangat besar.

Oleh karena itu, untuk mendapatkan manfaat dari tumpukan Fibonacci dalam praktiknya , Anda harus menggunakannya dalam aplikasi di mana penurunan_kunci sangat sering terjadi. Dalam hal Dijkstra, ini berarti bahwa grafik yang mendasarinya padat. Beberapa aplikasi bisa secara intrinsik mengurangi_kunci; Saya ingin mencoba algoritma pemotongan minimum Nagomochi-Ibaraki karena ternyata ia menghasilkan banyak penurunan_kunci, tetapi terlalu banyak upaya untuk membuat perbandingan waktu berfungsi.

Peringatan : Saya mungkin telah melakukan kesalahan. Anda mungkin ingin mencoba mereproduksi hasil ini sendiri.

Catatan Teoritis : Peningkatan kinerja tumpukan Fibonacci di penurunan_key penting untuk aplikasi teoretis, seperti runtutan Dijkstra. Fibonacci tumpukan juga mengungguli tumpukan biner pada penyisipan dan penggabungan (keduanya diamortisasi waktu-konstan untuk tumpukan Fibonacci). Penyisipan pada dasarnya tidak relevan, karena tidak memengaruhi runtuhnya Dijkstra, dan cukup mudah untuk memodifikasi tumpukan biner dan juga memasukkan waktu diamortisasi yang disisipkan. Menggabungkan dalam waktu yang konstan itu fantastis, tetapi tidak relevan dengan aplikasi ini.

Catatan pribadi : Seorang teman saya dan saya pernah menulis makalah yang menjelaskan antrian prioritas baru, yang mencoba mereplikasi waktu berjalan (secara teoritis) tumpukan Fibonacci tanpa kerumitan mereka. Makalah ini tidak pernah diterbitkan, tetapi rekan penulis saya mengimplementasikan tumpukan biner, tumpukan Fibonacci, dan antrian prioritas kami sendiri untuk membandingkan struktur data. Grafik dari hasil percobaan menunjukkan bahwa Fibonacci menumpuk sedikit melebihi kinerja biner dalam hal perbandingan total, menunjukkan bahwa tumpukan Fibonacci akan berkinerja lebih baik dalam situasi di mana biaya perbandingan melebihi overhead. Sayangnya, saya tidak memiliki kode yang tersedia, dan mungkin dalam perbandingan situasi Anda murah, jadi komentar ini relevan tetapi tidak secara langsung berlaku.

Secara kebetulan, saya sangat merekomendasikan untuk mencoba mencocokkan runtime dari tumpukan Fibonacci dengan struktur data Anda sendiri. Saya menemukan bahwa saya hanya menemukan kembali Fibonacci menumpuk sendiri. Sebelum saya berpikir bahwa semua kerumitan tumpukan Fibonacci adalah beberapa ide acak, tetapi setelah itu saya menyadari bahwa semuanya adalah alami dan cukup dipaksakan.

A. Rex
sumber
Terima kasih! Pertanyaan ini sudah lama ada di benak saya. Saya benar-benar menerapkan Dijkstra menggunakan Fibonacci-Heaps sebelum saya mencoba Steiner-Trees. Namun, tampaknya grafik saya jauh lebih padat daripada di contoh Anda. Mereka memiliki jutaan node, tetapi tingkat rata-rata hanya 5-6.
mdm
Kinerja Fib Heap dapat diprediksi melalui urutan operasi. Saya telah menulis algoritma Heap-heavy yang berakhir lebih cepat dengan Fib Heap (vs. Bin Heap). Triknya adalah menumpuk pekerjaan. Terlepas dari frekuensi operasi apa pun, perbedaannya ada di sini: DecreaseKey - ExtractMin - DecreaseKey - ExtractMin versus DecreaseKey - DecreaseKey - ExtractMin - ExtractMin (lanjutan di bawah)
Gaminic
Yang terakhir akan kira-kira dua kali lebih cepat, karena 2nd ExtractMin hampir gratis. Algoritme kami mengekstrak sekelompok elemen Min yang banyak dibuang; sampah di Bin Heap, tapi lebih baik di Fib Heap. Sayangnya ini tidak jelas tercermin dalam kompleksitas waktu yang disediakan orang ketika berbicara tentang algoritma berbasis Heap. Dengan batas diamortisasi, kompleksitas total bukan hanya # operasi * kompleksitas operasi.
Gaminic
1
Apakah ada peluang untuk mencoba memadatkan tumpukan dan / atau tumpukan santai?
Thomas Ahle
1
Saya tidak yakin mengapa hasil Anda muncul sangat dekat, saya menggunakan STL priority_queue vs fibonacci Heap yang diimplementasikan dan tumpukan biner berada di belakang dengan selisih besar dalam tes saya .
Nicholas Pipitone
33

Knuth melakukan perbandingan antara fibonacci Heap dan tumpukan biner untuk pohon spanning minimum kembali pada tahun 1993 untuk bukunya Stanford Graphbase . Dia menemukan fibonacci menjadi 30 hingga 60 lebih lambat dari tumpukan biner pada ukuran grafik yang dia uji, 128 simpul pada kepadatan yang berbeda.

The kode sumber dalam C (atau lebih tepatnya CWEB yang merupakan persilangan antara C, matematika dan TeX) di bagian MILES_SPAN.

kuda kertas
sumber
1

Penolakan

Saya tahu hasilnya sangat mirip dan "sepertinya waktu berjalan benar-benar didominasi oleh sesuatu selain tumpukan" (@Alpedar). Tetapi saya tidak dapat menemukan bukti apa pun dalam kode itu. Kode terbuka, jadi jika Anda dapat menemukan apa pun yang dapat memengaruhi hasil tes, beri tahu saya.


Mungkin saya melakukan sesuatu yang salah, tetapi saya menulis tes , berdasarkan A.Rex anwser membandingkan:

  • Fibonacci-Heap
  • D-Ary-heap (4)
  • Biner-Tumpukan
  • Santai-Tumpukan

Waktu eksekusi (hanya untuk grafik lengkap) untuk semua tumpukan sangat dekat. Tes ini dibuat untuk grafik lengkap dengan 1000.2000.3000.4000.5000.6000.7000 dan 8000 simpul. Untuk setiap tes 50 grafik acak dihasilkan dan output adalah waktu rata-rata setiap tumpukan:

Maaf tentang hasilnya, ini tidak terlalu bertele-tele karena saya membutuhkannya untuk membuat beberapa bagan dari file teks.


Inilah hasilnya (dalam detik):

tabel hasil tumpukan

Guilherme Torres Castro
sumber
4
Berapa banyak tepi yang ada di setiap kasing? Dan algoritma apa yang Anda jalankan sebenarnya? Hasil Anda tidak masuk akal jika kami tidak tahu apa yang sedang kami hadapi.
kokx
Ketika saya sedih, semua grafik selesai, sehingga Anda dapat menghitung jumlah tepi untuk setiap kasus. Apa yang Anda maksudkan, "apakah Anda menjalankan dengan tepat". Mereka ada di kepala tabel.
Guilherme Torres Castro
22
Ini sepertinya waktu yang berjalan benar-benar didominasi oleh sesuatu selain tumpukan (bisa menghasilkan grafik atau IO). Hasil yang hampir persis sama itu sulit dipercaya.
Alpedar
2
Yah mungkin waktu itu didominasi oleh sesuatu yang lain, tetapi saya yakin itu bukan IO atau generasi dari grafik. Pokoknya kode sumber tersedia dan saya akan sangat senang jika seseorang menemukan kesalahan dan memperbaiki mesure.
Guilherme Torres Castro
Tes-tes itu tampaknya mengukur sesuatu yang sama sekali berbeda. Bisakah Anda mengomentari tes yang Anda jalankan? Ingat bahwa Masalah Jalur Terpendek pada grafik lengkap adalah O (1) jika jarak Geometris / Euclidian.
Gaminic
0

Saya juga melakukan percobaan kecil dengan tumpukan Fibonacci. Berikut ini tautan untuk detailnya: Eksperimen-dengan-dijkstras-algoritme . Saya hanya googled istilah "Fibonacci heap java" dan mencoba beberapa implementasi open-source dari Fibonacci heap. Tampaknya beberapa dari mereka memiliki masalah kinerja, tetapi ada beberapa yang cukup bagus. Setidaknya, mereka mengalahkan kinerja PQ naif dan tumpukan biner dalam pengujian saya. Mungkin mereka dapat membantu menerapkan yang efisien.

gabormakrai
sumber