มีใครใช้งานฟีโบนัชชี - กองอย่างมีประสิทธิภาพจริงหรือไม่?


151

Fibonacci-Heapเคยมีใครบ้างในพวกคุณบ้างไหม? ฉันทำไม่กี่ปีที่ผ่านมา แต่มันก็มีหลายคำสั่งที่ช้ากว่าการใช้ BinHeaps แบบอาเรย์

ย้อนกลับไปฉันคิดว่ามันเป็นบทเรียนที่มีค่าในการวิจัยที่ไม่ดีเท่าที่ควรจะเป็น อย่างไรก็ตามงานวิจัยจำนวนมากอ้างว่าเวลาทำงานของอัลกอริทึมของพวกเขาขึ้นอยู่กับการใช้ Fibonacci-Heap

คุณเคยสร้างการใช้งานที่มีประสิทธิภาพหรือไม่? หรือคุณทำงานกับชุดข้อมูลขนาดใหญ่จนฟีโบนักชี - กองมีประสิทธิภาพมากขึ้นหรือไม่? ถ้าเป็นเช่นนั้นรายละเอียดบางอย่างจะได้รับการชื่นชม


25
คุณไม่ได้เรียนรู้อัลกอริธึมเหล่านี้เสมอซ่อนค่าคงที่ใหญ่โตของพวกมันไว้ข้างหลังตัวโตใหญ่ของพวกมันโอ้! :) ดูเหมือนว่าในทางปฏิบัติส่วนใหญ่แล้วสิ่งที่ "n" ไม่เคยได้ใกล้เคียงกับ "n0"!
Mehrdad Afshari

ฉันรู้แล้วตอนนี้. ฉันนำไปใช้เมื่อฉันได้รับ "Introduction to Algorithms" เป็นครั้งแรก นอกจากนี้ฉันไม่ได้เลือก Tarjan สำหรับใครบางคนที่จะประดิษฐ์โครงสร้างข้อมูลที่ไร้ประโยชน์เพราะ Splay-Trees ของเขาค่อนข้างเจ๋งจริง ๆ
mdm

mdm: แน่นอนว่ามันไร้ประโยชน์ แต่ก็เหมือนกับการเรียงลำดับการแทรกที่เต้นเร็วในชุดข้อมูลขนาดเล็ก heap แบบไบนารีอาจทำงานได้ดีขึ้นเนื่องจากค่าคงที่ขนาดเล็กลง
Mehrdad Afshari

1
ที่จริงแล้วโปรแกรมที่ฉันต้องการฮีปคือการค้นหา Steiner-Trees สำหรับการกำหนดเส้นทางใน VLSI-chips ดังนั้นชุดข้อมูลจึงไม่เล็ก แต่ทุกวันนี้ (ยกเว้นเรื่องง่าย ๆ เช่นการเรียงลำดับ) ฉันมักจะใช้อัลกอริทึมที่ง่ายกว่าจนกว่าจะ "หยุด" บนชุดข้อมูล
mdm

1
คำตอบของฉันคือ "ใช่" (ผู้เขียนร่วมของฉันลงบนกระดาษได้) ฉันยังไม่มีรหัสดังนั้นฉันจะขอข้อมูลเพิ่มเติมก่อนที่ฉันจะตอบ อย่างไรก็ตามเมื่อดูกราฟของเราฉันสังเกตว่ากอง F ทำการเปรียบเทียบน้อยกว่ากอง b คุณใช้สิ่งที่การเปรียบเทียบราคาถูกหรือไม่
A. Rex

คำตอบ:


136

Boost c ++ ห้องสมุดรวมถึงการดำเนินการของกอง Fibonacci boost/pending/fibonacci_heap.hppใน ไฟล์นี้มีมาpending/นานหลายปีแล้วและจากการคาดการณ์ของฉันจะไม่ได้รับการยอมรับ นอกจากนี้ยังมีข้อผิดพลาดในการใช้งานซึ่งได้รับการแก้ไขโดยคนรู้จักของฉันและคนที่แต่งตัวประหลาดสุดยอด Aaron Aaron Windsor น่าเสียดายที่ไฟล์ส่วนใหญ่เวอร์ชันที่ฉันหาได้ทางออนไลน์ (และไฟล์หนึ่งในแพ็คเกจ libboost-dev ของ Ubuntu) ยังคงมีข้อบกพร่องอยู่ ฉันต้องดึงเวอร์ชั่นใหม่ทั้งหมดออกจากที่เก็บ Subversion

ตั้งแต่เวอร์ชั่น1.49 Boost C ++ไลบรารี่เพิ่ม heaps structs ใหม่ ๆ มากมายรวมถึง fibonacci heap

ผมสามารถที่จะรวบรวมdijkstra_heap_performance.cppกับรุ่นที่ปรับเปลี่ยนdijkstra_shortest_paths.hppเพื่อเปรียบเทียบกอง Fibonacci และกองไบนารี (ในบรรทัดtypedef relaxed_heap<Vertex, IndirectCmp, IndexMap> MutableQueueให้เปลี่ยนrelaxedเป็นfibonacci.) ฉันลืมที่จะคอมไพล์ด้วยการออพติไมซ์ซึ่งในกรณีนี้ฟีโบนักชีและไบนารีฮีปมีประสิทธิภาพเท่ากันโดยที่ฟีโบนัชชีฮีปมักจะมีประสิทธิภาพที่ดีกว่าด้วยจำนวนเล็กน้อย หลังจากที่ฉันคอมไพล์ด้วยการปรับให้เหมาะสมที่ดีมากแล้วฮีปไบนารีก็เพิ่มขึ้นอย่างมาก ในการทดสอบของฉันฟีโบนักชีกองเดียวดีกว่าฮีปไบนารีเมื่อกราฟมีขนาดใหญ่และหนาแน่นอย่างไม่น่าเชื่อเช่น:

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.

เท่าที่ฉันเข้าใจสิ่งนี้สัมผัสกับความแตกต่างพื้นฐานระหว่างฟีโบนักชีฮีปและฮีปไบนารี ความแตกต่างทางทฤษฎีที่แท้จริงเพียงอย่างเดียวระหว่างโครงสร้างข้อมูลทั้งสองคือฟีโบนักชีฮีปรองรับการลดลงของเวลาคงที่ (ตัดจำหน่าย) ในทางกลับกัน heap แบบไบนารีจะได้รับประสิทธิภาพอย่างมากจากการนำไปใช้เป็นอาเรย์ การใช้โครงสร้างตัวชี้ที่ชัดเจนหมายความว่าฮีพฟีโบนักชีประสบความสำเร็จอย่างมาก

ดังนั้นเพื่อให้ได้ประโยชน์จากฟีโบนักชีในทางปฏิบัติคุณต้องใช้มันในแอปพลิเคชันที่มีค่าลดลงเป็นจำนวนบ่อยครั้งอย่างไม่น่าเชื่อ ในแง่ของ Dijkstra หมายความว่ากราฟที่มีความหนาแน่นสูง แอปพลิเคชั่นบางตัวอาจมีความรุนแรงน้อยลงมาก ฉันต้องการลองอัลกอริธึมตัดขั้นต่ำของ Nagomochi-Ibarakiเพราะเห็นได้ชัดว่ามันสร้างจำนวนลดลงจำนวนมาก

คำเตือน : ฉันอาจทำสิ่งผิดปกติ คุณอาจต้องการลองทำซ้ำผลลัพธ์เหล่านี้ด้วยตัวเอง

บันทึกเชิงทฤษฎี : ประสิทธิภาพที่เพิ่มขึ้นของฟีโบนักชีฮีปบน reduction_key เป็นสิ่งสำคัญสำหรับการใช้งานเชิงทฤษฎีเช่นไทม์ของ Dijkstra ฮีปฟีโบนักชีนั้นมีประสิทธิภาพเหนือกว่าฮีปไบนารีในการแทรกและการรวม (ทั้งค่าคงที่เวลาคงที่สำหรับฟิโบนัชชีฮีป) การแทรกนั้นไม่สำคัญเพราะมันไม่ส่งผลกระทบต่อการทำงานของ Dijkstra และมันค่อนข้างง่ายที่จะแก้ไข heap แบบไบนารีเพื่อให้มีการแทรกในเวลาคงที่ที่ตัดจำหน่าย การผสานในเวลาคงที่นั้นยอดเยี่ยม แต่ไม่เกี่ยวข้องกับแอปพลิเคชันนี้

บันทึกส่วนตัว : เพื่อนของฉันและฉันเคยเขียนบทความอธิบายลำดับความสำคัญใหม่ซึ่งพยายามทำซ้ำ (ในทางทฤษฎี) เวลาทำงานของฟีโบนักชีกองโดยไม่ซับซ้อน กระดาษไม่เคยถูกตีพิมพ์ แต่ผู้เขียนร่วมของฉันใช้ไบนารีฮีปฟีโบนัชชีฮีปและคิวลำดับความสำคัญของเราเองเพื่อเปรียบเทียบโครงสร้างข้อมูล กราฟของผลการทดลองแสดงให้เห็นว่าฟีโบนัชชีกองฮีปไบนารีที่ทำออกมาเล็กน้อยในแง่ของการเปรียบเทียบทั้งหมดชี้ให้เห็นว่าฮีปฟีโบนักชีจะทำงานได้ดีขึ้นในสถานการณ์ที่ต้นทุนการเปรียบเทียบสูงกว่าค่าโสหุ้ย น่าเสียดายที่ฉันไม่ได้มีรหัสและน่าจะเป็นในการเปรียบเทียบสถานการณ์ของคุณราคาถูกดังนั้นความคิดเห็นเหล่านี้มีความเกี่ยวข้อง แต่ไม่เกี่ยวข้องโดยตรง

อนึ่งฉันขอแนะนำให้พยายามจับคู่รันไทม์ของฟีโบนักชีกองกับโครงสร้างข้อมูลของคุณเอง ฉันพบว่าฉันเพียงแค่คิดค้นฟีโบนักชีอีกครั้งให้เป็นกอง ก่อนที่ฉันจะคิดว่าความซับซ้อนทั้งหมดของกองฟีโบนักชีเป็นความคิดแบบสุ่ม แต่ต่อมาฉันก็รู้ว่าพวกเขาเป็นธรรมชาติและถูกบังคับอย่างเป็นธรรม


ขอบคุณ! คำถามนี้อยู่ในใจของฉันเป็นเวลานาน ฉันใช้ Dijkstra โดยใช้ Fibonacci-Heaps ก่อนที่ฉันจะลอง Steiner-Trees อย่างไรก็ตามดูเหมือนว่ากราฟของฉันจะมีความหนาแน่นน้อยกว่าตัวอย่างของคุณมาก พวกเขามีล้านโหนด แต่ระดับเฉลี่ยเพียง 5-6
mdm

ประสิทธิภาพของ Fib Heap สามารถคาดการณ์ได้ผ่านลำดับการปฏิบัติการ ฉันได้เขียนอัลกอริธึม Heap-heavy ที่ลงเอยเร็วกว่าด้วย Fib Heap (vs. Bin Heap) เคล็ดลับคือการรวบรวมงาน โดยไม่คำนึงถึงความถี่ของการดำเนินการใด ๆ ความแตกต่างอยู่ที่นี่: DecreaseKey - ExtractMin - DecreaseKey - ExtractMin กับ DecreaseKey - DecreaseKey - ExtractMin - ExtractMin (ต่อด้านล่าง)
Gaminic

หลังจะเร็วเป็นสองเท่าโดยประมาณเนื่องจาก ExtractMin ที่ 2 เกือบฟรี อัลกอรึทึมของเราแยกกลุ่มองค์ประกอบขั้นต่ำซึ่งหลายองค์ประกอบถูกทิ้งไป ขยะในถังขยะ แต่ดีกว่าในถังขยะ น่าเศร้าที่เรื่องนี้ไม่ได้สะท้อนให้เห็นอย่างชัดเจนในเวลาที่ผู้คนให้ความซับซ้อนเมื่อพูดถึงอัลกอริธึมที่ใช้ฮีป ด้วยค่าตัดจำหน่ายขอบเขตความซับซ้อนทั้งหมดไม่เพียงแค่การดำเนินงาน # การดำเนินการที่ซับซ้อน
Gaminic

1
มีโอกาสใดในการลองจับคู่ heaps และ / หรือ heaps ที่ผ่อนคลาย?
โทมัส Ahle

1
ฉันไม่แน่ใจว่าทำไมผลลัพธ์ของคุณปรากฏเพื่อให้ใกล้เคียงผมใช้ STL priority_queue VS ตนเองดำเนินการ fibonacci กองและกองไบนารีอยู่เบื้องหลังโดยขอบขนาดใหญ่ในของฉันทดสอบ
Nicholas Pipitone

33

Knuth ทำการเปรียบเทียบระหว่างฟีโบนักชีฮีปกับฮีปแบบไบนารีสำหรับต้นไม้ที่ขยายต่ำสุดในปี 1993 สำหรับหนังสือของเขาที่Stanford GraphbaseGraphbase เขาพบว่าฟีโบนัชชีนั้นช้ากว่าเลขฐานสองถึง 30 ถึง 60 ก่อนที่ขนาดกราฟที่เขาทดสอบนั้นมี 128 จุดยอดที่ความหนาแน่นต่างกัน

รหัสที่มาอยู่ใน C (หรือมากกว่า CWEB ซึ่งเป็นลูกผสมระหว่าง C, คณิตศาสตร์และเท็กซ์) ใน MILES_SPAN ส่วน


1

คำปฏิเสธ

ฉันรู้ว่าผลลัพธ์ค่อนข้างคล้ายกันและ "ดูเหมือนว่าเวลาทำงานนั้นเต็มไปด้วยสิ่งอื่นนอกเหนือจากฮีป" (@Alpedar) แต่ฉันไม่พบหลักฐานอะไรเลยในรหัส รหัสเปิดอยู่ดังนั้นหากคุณสามารถหาสิ่งที่มีผลต่อผลการทดสอบได้โปรดบอกฉัน


บางทีฉันอาจทำสิ่งผิดปกติ แต่ฉันเขียนการทดสอบโดยใช้A.Rex anwser เปรียบเทียบ:

  • Fibonacci-กอง
  • D-Ary-heap (4)
  • ไบนารีกอง
  • ผ่อนคลาย-กอง

เวลาดำเนินการ (สำหรับกราฟที่สมบูรณ์เท่านั้น) สำหรับกองทั้งหมดอยู่ใกล้มาก การทดสอบทำขึ้นเพื่อกราฟที่สมบูรณ์โดยมีจุดสูงสุด 1,000,2000,3000,4000,5000,6000,7,000 และ 8000 จุด สำหรับการทดสอบแต่ละ 50 กราฟสุ่มถูกสร้างขึ้นและเอาท์พุทเป็นเวลาเฉลี่ยของแต่ละกอง:

ขออภัยเกี่ยวกับผลลัพธ์ไม่มากเพราะฉันต้องการให้สร้างแผนภูมิจากไฟล์ข้อความ


นี่คือผลลัพธ์ (เป็นวินาที):

ตารางผลลัพธ์กอง


4
แต่ละกรณีมีขอบเท่าไหร่ และอัลกอริธึมอะไรที่คุณทำงานอย่างแน่นอน ผลลัพธ์ของคุณไม่สมเหตุสมผลถ้าเราไม่รู้ว่าเรากำลังทำอะไรอยู่
kokx

อย่างที่ฉันเศร้ากราฟทั้งหมดจะเสร็จสมบูรณ์ดังนั้นคุณสามารถคำนวณจำนวนขอบสำหรับแต่ละกรณี สิ่งที่คุณหมายถึง "คุณกำลังทำงานอย่างแน่นอน" พวกเขาอยู่ในหัวของตาราง
Guilherme Torres Castro

22
ดูเหมือนว่าเวลาในการทำงานจะถูกครอบงำโดยสิ่งอื่นนอกเหนือจากฮีป (อาจเป็นกราฟหรือ IO บางอย่าง) ผลลัพธ์เกือบเหมือนกันทั้งหมดนั้นไม่น่าเชื่อ
Alpedar

2
อาจจะเป็นเวลาที่ระบบปฏิบัติการครอบครองโดยอย่างอื่น แต่ฉันแน่ใจว่าไม่ใช่ IO หรือการสร้างกราฟ อย่างไรก็ตามมีซอร์สโค้ดและฉันจะดีใจมากถ้ามีคนพบข้อผิดพลาดและแก้ไข mesure
Guilherme Torres Castro

การทดสอบเหล่านั้นดูเหมือนจะวัดบางสิ่งที่แตกต่างอย่างสิ้นเชิง คุณสามารถแสดงความคิดเห็นในการทดสอบที่คุณวิ่ง? โปรดจำไว้ว่าปัญหาเส้นทางที่สั้นที่สุดบนกราฟที่สมบูรณ์คือ O (1) หากระยะทางเป็นเรขาคณิต / ยูคลีนิค
Gaminic

0

ฉันยังทำการทดลองขนาดเล็กกับกองฟีโบนักชี นี่คือลิงค์สำหรับรายละเอียดนี้: การทดสอบที่มี dijkstras ขั้นตอนวิธี ฉันเพิ่ง googled คำว่า "Fibonacci heap java" และพยายามใช้โอเพ่นซอร์สของ Fibonacci heap ดูเหมือนว่าบางคนมีปัญหาเรื่องประสิทธิภาพ แต่มีบางอย่างที่ค่อนข้างดี อย่างน้อยพวกเขาก็เต้นไร้เดียงสาและประสิทธิภาพของ PQ heap แบบไบนารีในการทดสอบของฉัน บางทีพวกเขาสามารถช่วยในการดำเนินการอย่างมีประสิทธิภาพ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.