Хтось насправді ефективно реалізував Фібоначчі-Кучку?


151

Хто-небудь з вас коли-небудь реалізував фібоначчі-купи ? Я зробив це кілька років тому, але це було на кілька порядків повільніше, ніж використання BinHeaps на основі масиву.

Тоді я вважав це цінним уроком того, як дослідження не завжди є настільки хорошими, як це стверджується. Однак багато дослідницьких робіт стверджують, що їх алгоритми працюють на основі використання Фібоначчі-Купи.

Чи вам колись вдалося створити ефективну реалізацію? Або ви працювали з наборами даних настільки великими, що Фібоначчі-Куча була більш ефективною? Якщо так, деякі деталі будуть вдячні.


25
Хіба ви не дізналися, що ці люди з алгоритму завжди ховають свої величезні константи за великим великим ох ?! :) Здається, на практиці, більшість часу, що "n" річ ніколи не наближається до "n0"!
Мехрдад Афшарі

Я знаю - зараз. Я реалізував це, коли вперше отримав свій примірник «Вступ до алгоритмів». Крім того, я не вибрав Тарджана для того, хто винайшов би марну структуру даних, тому що його Splay-Дерева насправді дуже круті.
mdm

mdm: Звичайно, це не марно, але так само, як сортування вставки, яке перемагає швидкості у невеликих наборах даних, бінарні купи можуть працювати краще за рахунок менших констант.
Мехрдад Афшарі

1
Насправді програма, для якої мені знадобилася купа, знаходила Штейнер-Дерева для маршрутизації в VLSI-чіпах, тому набори даних були не зовсім малі. Але в наш час (крім простих речей, таких як сортування) я завжди використовував простіший алгоритм, поки він не "зламається" на наборі даних.
mdm

1
Моя відповідь на це насправді "так". (Ну, мій співавтор на папері так і зробив.) У мене зараз немає коду, тому я отримаю більше інформації, перш ніж реально відповісти. Однак, дивлячись на наші графіки, зауважу, що F-купи роблять менше порівнянь, ніж b купи. Ви використовували щось там, де порівняння було дешевим?
А. Рекс

Відповіді:


136

Бібліотеки Boost C ++ включають реалізацію куб Фібоначчі в boost/pending/fibonacci_heap.hpp. Цей файл, мабуть, є pending/роками, і за моїми прогнозами, він ніколи не буде прийнятий. Також у цій реалізації були помилки, які виправляв мій знайомий та крутий хлопець Аарон Віндзор. На жаль, у більшості версій цього файлу, які я міг знайти в Інтернеті (і в пакеті libboost-dev Ubuntu), все ще були помилки; Мені довелося витягнути чисту версію з сховища Subversion.

Починаючи з версії 1.49, бібліотеки Boost C ++ додали багато нових струпінгових структур, у тому числі кучу платформ.

Мені вдалося скласти dijkstra_heap_performance.cpp проти модифікованої версії dijkstra_shortest_paths.hpp, щоб порівняти купи Фібоначчі і бінарні купи. (У рядку 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.

Наскільки я розумію, це стосується принципових відмінностей між купами Фібоначчі та бінарними купами. Єдина реальна теоретична відмінність між двома структурами даних полягає в тому, що купи Фібоначчі підтримують постійне час (амортизованого) постійного часу. З іншого боку, бінарні купи отримують значну продуктивність від їх реалізації як масиву; використання чіткої структури вказівника означає, що купи Фібоначчі зазнають величезних результатів.

Тому, щоб отримати користь від купи Фібоначчі на практиці , вам доведеться використовувати їх у програмі, де зменшення_кілій надзвичайно часто. З точки зору Дайкстра, це означає, що основний графік щільний. Деякі додатки можуть бути суттєво зменшеними-інтенсивними; Я хотів спробувати алгоритм мінімального скорочення Нагомочі-Ібаракі, тому що, мабуть, він генерує безліч скорочень зменшення, але це було занадто багато зусиль, щоб порівняти час роботи.

Попередження : я, можливо, зробив щось не так. Ви можете спробувати відтворити ці результати самостійно.

Теоретична примітка : Покращена продуктивність куб Фібоначчі при зменшенні клавіші важлива для теоретичних застосувань, таких як час виконання Dijkstra. Купи Фібоначчі також перевершують бінарні купи під час вставки та злиття (обидва амортизовані постійного часу для купи Фібоначчі). Вставлення по суті не має значення, тому що це не впливає на час роботи Дейкстри, і досить легко модифікувати бінарні купи, щоб вони також вставляли в амортизований постійний час. Злиття в постійний час - це фантастично, але не стосується цієї програми.

Особиста примітка : Один мій друг і я одного разу написали документ, в якому пояснювали нову чергу пріоритетів, яка намагалася повторити (теоретичний) час роботи куб Фібоначчі без їх складності. Стаття ніколи не була опублікована, але мій співавтор реалізував двійкові купи, куби Фібоначчі та нашу власну чергу пріоритетів для порівняння структур даних. Графіки експериментальних результатів вказують на те, що Фібоначчі купує трохи перевиконані бінарні купи за загальним порівнянням, що дозволяє припустити, що купи Фібоначчі будуть краще працювати в ситуації, коли вартість порівняння перевищує накладні витрати. На жаль, у мене немає коду, і, мабуть, у вашій ситуації порівняння коштує дешево, тому ці коментарі є релевантними, але безпосередньо не застосовуються.

Між іншим, я настійно рекомендую спробувати співставити час виконання куб Фібоначчі з вашою власною структурою даних. Я виявив, що я просто винаходив кучки Фібоначчі. Перш ніж я подумав, що всі складності куб Фібоначчі - це деякі випадкові ідеї, але згодом я зрозумів, що всі вони природні і досить вимушені.


Дякую! Це питання давно сиділо на моїй думці. Я насправді реалізував Dijkstra, використовуючи Фібоначчі-Хеапс, перш ніж спробувати Steiner-Trees. Однак здається, що мої графіки куди набагато менш щільні, ніж у вашому прикладі. Вони мали мільйони вузлів, але середній ступінь лише 5-6.
mdm

Продуктивність Fib Heap передбачувана через послідовність операцій. Я написав важкий алгоритм, який закінчився швидше з Fib Heap (проти Bin Heap). Хитрість полягала в роботі. Незалежно від частоти будь-якої операції, різниця полягає тут: DecreaseKey - ExtractMin - DecreaseKey - ExtractMin проти DecreaseKey - DecreaseKey - ExtractMin - ExtractMin (продовження нижче)
Gaminic

Останній буде приблизно вдвічі швидшим, тому що другий ExtractMin майже безкоштовний. Наш алгоритм витягує партію елементів Min, від яких багато хто відкидається; відходи на Бін Купі, але краще на Fib Heap. На жаль, це не чітко відображається на складності часу, яку люди надають, коли говорять про алгоритми на основі Heap. З амортизованими межами загальна складність не просто # операції * складність операції.
Гамініч

1
Будь-який шанс спробувати поєднання купи та / або розслабленої купи?
Томас Ейл

1
Я не впевнений, чому ваші результати виявилися настільки близькими, я використав STL prior_queue vs власноруч реалізовану групу фільмів, а двійкова купа відстала від великих запасів у моїх тестах .
Микола Піпітон

33

Кніт зробив порівняння між кучею нагромадження і бінарними купами для мінімально розкиданих дерев ще в 1993 році для своєї книги Stanford Graphbase . Він виявив, що напруга на 30-60 відсотків повільніше, ніж бінарні купи, за розмірами граф, які він тестував, - 128 вершин різної щільності.

Вихідний код знаходиться в C (або , швидше за , CWEB який є чимось середнє між C, математики та текс) в розділі MILES_SPAN.


1

Відмова від відповідальності

Я знаю, результати дуже схожі, і "схоже, що час роботи повністю переважає щось інше, ніж купа" (@Alpedar). Але я нічого не міг знайти в цьому коді доказів. Код відкритий, тому, якщо ви зможете знайти щось, що може вплинути на результат тесту, будь ласка, скажіть мені.


Можливо, я зробив щось не так, але я написав тест на основі A.Rex anwser, порівнюючи:

  • Фібоначчі-Хіп
  • D-Ary-heap (4)
  • Бінарний-Куча
  • Розслаблена купа

Часи виконання (лише для повних графіків) для всіх груп були дуже близькими. Тест був зроблений для повних графіків з 1000,2000,3000,4000,5000,6000,7000 і 8000 вершин. Для кожного тесту було сформовано 50 випадкових графіків, а вихід - середній час кожної купи:

Вибачте за результат, він не дуже багатослівний, тому що мені знадобився він для створення деяких діаграм із текстових файлів.


Ось результати (у секундах):

таблиця результатів купи


4
Скільки країв у кожному випадку? І який алгоритм ви точно виконуєте? Ваші результати не мають сенсу, якщо ми не знаємо, з чим маємо справу.
kokx

Як мені сумно, весь графік завершений, тому ви можете обчислити кількість ребер для кожного випадку. Що ти маєш на увазі, "ти точно біжиш". Вони в голові столів.
Гільгерме Торрес Кастро

22
Це виглядає так, що час роботи повністю переважає щось інше, ніж купа (це може бути генерацією графіка або деяким введенням). Ці майже такі самі результати неймовірні.
Альпедар

2
Ну, може, час ос домінував у чомусь іншому, але я впевнений, що це не IO чи генерація графіків. У будь-якому випадку вихідний код доступний, і я буду дуже радий, якщо хтось знайде помилку і виправить мес.
Гільгерме Торрес Кастро

Ці тести, здається, вимірюють щось зовсім інше. Не могли б ви прокоментувати тест, який ви пройшли? Пам'ятайте, що найкоротша задача шляху на повному графіку дорівнює O (1), якщо відстані геометричні / евклідові.
Гамінік

0

Я також зробив невеликий експеримент з купою Фібоначчі. Ось посилання для деталей: Експериментування-з-dijkstras-алгоритм . Я просто гуглив терміни «Фібоначчі купи» і спробував декілька існуючих в реальному часі купи Фібоначчі з відкритим кодом. Здається, що деякі з них мають певні проблеми з продуктивністю, але є такі, які є досить непоганими. Принаймні, в моєму тесті вони б'ють наївну та бінарну ефективність PQ купи. Можливо, вони можуть допомогти здійснити ефективний.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.