[performance] 실제로 피보나치 힙을 효율적으로 구현 한 사람이 있습니까?

피보나치 힙을 구현 한 사람이 있습니까? 나는 몇 년 전에 그렇게했지만 배열 기반 BinHeaps를 사용하는 것보다 몇 배나 느 렸습니다.

당시 나는 그것이 연구가 항상 주장하는 것만 큼 좋지 않은 방법에 대한 귀중한 교훈이라고 생각했습니다. 그러나 많은 연구 논문은 피보나치 힙을 사용한 알고리즘의 실행 시간을 주장합니다.

효율적인 구현을 수행 한 적이 있습니까? 아니면 피보나치 힙이 더 효율적일 정도로 큰 데이터 세트로 작업 했습니까? 그렇다면 일부 세부 사항을 주시면 감사하겠습니다.



답변

부스트 C ++ 라이브러리 에서 피보나치 힙의 구현을 포함한다 boost/pending/fibonacci_heap.hpp. 이 파일은 pending/수년 동안 사용 되어 왔으며 내 계획으로는 결코 받아 들여지지 않을 것입니다. 또한, 그 구현에 버그가 있었는데, 내 지인과 만능의 멋진 남자 Aaron Windsor가 수정했습니다. 불행히도, 온라인에서 찾을 수있는 대부분의 파일 버전 (및 Ubuntu의 libboost-dev 패키지에있는 버전)에는 여전히 버그가있었습니다. 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.

내가 아는 한, 이것은 피보나치 힙과 이진 힙의 근본적인 차이점을 다룹니다. 두 데이터 구조 사이의 유일한 이론적 인 차이점은 피보나치 힙이 일정한 시간에 감소 키를 지원한다는 것입니다. 반면, 이진 힙은 배열로 구현하여 많은 성능을 얻습니다. 명시적인 포인터 구조를 사용한다는 것은 피보나치 힙이 큰 성능 저하를 겪음을 의미합니다.

따라서 실제로 피보나치 힙의 이점을 얻으려면 reduce_keys 가 매우 빈번한 응용 프로그램에서 사용해야합니다. Dijkstra와 관련하여 이는 기본 그래프가 밀집되어 있음을 의미합니다. 일부 응용 프로그램은 본질적으로 reduce_key-intense 일 수 있습니다. Nagomochi-Ibaraki 최소 자르기 알고리즘 을 시도 하고 싶었지만 명백히 많은 reduce_keys를 생성하기 때문에 타이밍 비교 작업을 수행하는 데 너무 많은 노력이 필요했습니다.

경고 : 뭔가 잘못했을 수 있습니다. 이러한 결과를 직접 재현 해 볼 수 있습니다.

이론적 참고 : reduce_key에서 피보나치 힙의 향상된 성능은 Dijkstra의 런타임과 같은 이론적 응용 프로그램에 중요합니다. 피보나치 힙은 삽입 및 병합시 이진 힙보다 성능이 뛰어납니다 (피보나치 힙의 상각 상수 시간 모두). 삽입은 Dijkstra의 런타임에 영향을 미치지 않기 때문에 본질적으로 무관하며, 상각 된 일정한 시간에 삽입되도록 바이너리 힙을 수정하는 것은 매우 쉽습니다. 일정한 시간에 병합하는 것은 환상적이지만이 응용 프로그램과 관련이 없습니다.

개인 메모 : 내 친구와 나는 한때 새로운 우선 순위 대기열을 설명하는 논문을 작성했는데, 복잡하지 않고 피보나치 힙의 (이론적) 실행 시간을 복제하려고 시도했습니다. 이 논문은 출판되지 않았지만 공동 저자는 이진 힙, 피보나치 힙 및 자체 우선 순위 대기열을 구현하여 데이터 구조를 비교했습니다. 실험 결과의 그래프는 피보나치 힙이 전체 비교 측면에서 이진 힙보다 약간 성능이 우수하다는 것을 나타내며, 이는 비교 비용이 오버 헤드를 초과하는 상황에서 피보나치 힙이 더 나은 성능을 나타냅니다. 불행히도, 사용할 수있는 코드가 없으며 아마도 귀하의 상황에서 비교가 저렴하기 때문에 이러한 의견은 관련이 있지만 직접 적용 할 수는 없습니다.

또한 피보나치 힙의 런타임을 자신의 데이터 구조와 일치시키는 것이 좋습니다. 나는 단순히 피보나치 더미를 재창조한다는 것을 알았습니다. 피보나치 더미의 모든 복잡성이 임의의 아이디어라고 생각하기 전에, 나는 그것들이 모두 자연스럽고 상당히 강제적이라는 것을 깨달았습니다.


답변

Knuth는 그의 책 Stanford Graphbase에 대해 1993 년에 최소 스패닝 트리에 대해 피보나치 힙과 이진 힙을 비교 했습니다 . 그는 피보나치가 테스트중인 그래프 크기에서 이진 힙보다 30 ~ 60 % 느리다는 것을 발견했습니다.

소스 코드 (C 아니라, 수학 텍 간의 크로스 CWEB 또는) 단면 MILES_SPAN의 C이다.


답변

부인 성명

나는 결과가 상당히 유사하다는 것을 알고 있으며 “런타임이 완전히 다른 것보다 우세한 것처럼 보인다”(@Alpedar). 그러나 코드에서 그 증거를 찾을 수 없었습니다. 코드가 열려 있으므로 테스트 결과에 영향을 줄 수있는 것이 있으면 알려주세요.


어쩌면 내가 뭔가 잘못을했다,하지만 난 시험을 썼다 을 기반으로, A.Rex의 비교 anwser :

  • 피보나치 힙
  • D- 아리 힙 (4)
  • 이진 힙
  • 편안한 힙

모든 힙에 대한 실행 시간 (완전한 그래프의 경우에만)은 매우 가깝습니다. 1000,2000,3000,4000,5000,6000,7000 및 8000 정점으로 완전한 그래프를 테스트했습니다. 각 테스트마다 50 개의 무작위 그래프가 생성되었으며 출력은 각 힙의 평균 시간입니다.

출력에 대해 죄송합니다. 텍스트 파일에서 일부 차트를 작성해야했기 때문에 매우 장황하지 않습니다.


결과는 초 단위입니다.

힙 결과 테이블


답변

나는 또한 피보나치 더미로 작은 실험을했습니다. 세부 사항에 대한 링크는 다음과 같습니다. Experimenting-with-dijkstras-algorithm . 방금 “Fibonacci heap java”라는 용어를 검색하고 피보나치 힙의 기존 오픈 소스 구현 몇 가지를 시도했습니다. 그들 중 일부는 성능 문제가있는 것 같지만 꽤 좋은 것이 있습니다. 적어도, 그들은 내 테스트에서 순진하고 바이너리 힙 PQ 성능을 뛰고 있습니다. 아마도 그들은 효율적인 것을 구현하는 데 도움이 될 수 있습니다.


답변