Jgrapht: 非推奨のフィボナッチヒープ

作成日 2018年08月29日  ·  12コメント  ·  ソース: jgrapht/jgrapht

GenericFibonacciHeapへのすべての参照をjheapsに置き換え、廃止しました。

特に、単調なヒープの実装はDjikstra / ClosestFirstIteratorなどの使用法に最適化されるため、非ジェネリックのFibonacciHeapクラスでも同じことを行うと便利です。

ただし、これを行う一環として、パフォーマンスの低下がないことを確認するために、現在侵入性の最適化(およびネイティブダブル)に依存しているケースをパフォーマンステストする必要があります。

cleanup

最も参考になるコメント

性能比較をしたいのですが

全てのコメント12件

性能比較をしたいのですが

パフォーマンスの比較を行いました。結果は次のとおりです。
フィボナッチヒープネイティブ

|テストタイプ| ダイクストラ、us / op | 最も近い最初のイテレータ、us / op |
| --------------------- | ------------------- | ------- ------------------------ |
| 完全な100 | 165 | 165 |
| 完全な300 | 1903 | 1920 |
| 完全な500 | 9799 | 9526 |
| 完全な1000 | 54701 | 54474 |
| トライアン。 1000 | 507 | 510 |
| トライアン。 3000 | 1702 | 1695 |
| トライアン。 5000 | 3399 | 3329 |
| トライアン。 10000 | 7420 | 7386 |
| トライアン。 20000 | 17138 | 16867 |
| トライアン。 40000 | 38579 | 38707 |

JHeapsフィボナッチヒープ

|テストタイプ| ダイクストラ、us / op | 最も近い最初のイテレータ、us / op |
| --------------------- | ------------------- | ------- ------------------------ |
| 完全な100 | 172 | 173 |
| 完全な300 | 2013 | 1984 |
| 完全な500 | 11371 | 10108 |
| 完全な1000 | 56411 | 56650 |
| トライアン。 1000 | 455 | 464 |
| トライアン。 3000 | 1534 | 1595 |
| トライアン。 5000 | 2927 | 3100 |
| トライアン。 10000 | 6985 | 6892 |
| トライアン。 20000 | 15904 | 16159 |
| トライアン。 40000 | 35970 | 36313 |

JHeapsペアリングヒープ

|テストタイプ| ダイクストラ、us / op | 最も近い最初のイテレータ、us / op |
| --------------------- | --------------------- | ----- -------------------------- |
| 完全な100 | 166 | 165 |
| 完全な300 | 2017 | 2163 |
| 完全な500 | 12015 | 11453 |
| 完全な1000 | 61985 | 63824 |
| トライアン。 1000 | 373 | 375 |
| トライアン。 3000 | 1224 | 1227 |
| トライアン。 5000 | 2637 | 2895 |
| トライアン。 10000 | 5840 | 5941 |
| トライアン。 20000 | 15251 | 15217 |
| トライアン。 40000 | 30799 | 33975 |

パフォーマンスの違いはそれほど大きくありません。

現在、ダブルモノトーン基数ヒープでテストを実行することはできません。 その理由は、例外をスローするためです。 これは、最初に距離0(currentMin = 0)の開始頂点を挿入し、次にそれを削除し(現在、ヒープ内のcurrentMinはnull)、次に距離kのノードを挿入し(currentMinはkになります)、距離のあるノードを挿入すると発生します。 m <k(k <mのために例外がスローされます)。 ウィキペディアでは、「単調優先キューの必要十分条件は、最後に抽出された要素よりも低い優先度の要素を追加しようとしないことです」と述べられています。 距離0の頂点を削除した後、currentMinの値がnullになることはないと思いますが、コードでは特殊なケースとしてコメントされているため、これが正しいかどうかはわかりません。

基数ヒープはわずかに異なる方法で実装されているため、現在の最小値よりも低いキーを持つ要素を挿入することはできません。

ダイクストラを少し書き直せば、うまくいくはずです。 最初にfindMin()を呼び出し、次にエッジを緩和し、最後にdelMin()を呼び出す必要があると思います。

さらに、ダイクストラを実行する前に、すべてのエッジを反復処理し、バインドされたn Cを計算する必要があります。ここで、 Cは最大のエッジの重みであり、 nはノードの数です。 この境界は、基数ヒープを初期化するときに使用する必要があります。

@Toptachamann基数ヒープを変更して、現在の最小値ではなく、最後に削除されたキーに基づいて要素を分散しようとします。 そうすれば、箱から出してすぐに機能します。

@Toptachamann実装を変更したところ、箱から出してすぐに機能するはずです。 私はリリースしなかったので、maven installを使用してローカルにインストールした後、バージョン0.9-SNAPSHOTに対してテストする必要があります。

@ d-michail今ではうまく機能しません。 開始頂点が削除された後、そのバケットインデックスは-1になりますが、currentMinのままです。 すべての出力エッジを緩和し、別の最小要素を削除しようとすると、 java.lang.ArrayIndexOutOfBoundsException: -1がスローされます。

@Toptachamann申し訳ありませんが、小さなバグがありました。 テストしていただきありがとうございます。 また、いくつかのテストを行い、現在の最小更新が正しく行われるようになりました。

ダブルモノトーンヒープの結果は次のとおりです。

|テストタイプ| ダイクストラ| 最も近い最初のイテレータ|
| -------------------------------- | ---------------- | ------------------------ |
| 100まで完了します。 b。 10 | 172 | 172 |
| 300アップを完了します。 b。 10 | 2458 | 2408 |
| 500アップを完了します。 b。 10 | 11104 | 10052 |
| 1000まで完了します。 b。 10 | 57028 | 56944 |
| 100まで完了します。 b。 100 | 185 | 175 |
| 300アップを完了します。 b。 100 | 2381 | 2464 |
| 500アップを完了します。 b。 100 | 11320 | 11313 |
| 1000まで完了します。 b。 100 | 64749 | 61865 |
| 100まで完了します。 b。 1000 | 190 | 180 |
| 300アップを完了します。 b。 1000 | 2315 | 2303 |
| 500アップを完了します。 b。 1000 | 11034 | 11792 |
| 1000まで完了します。 b。 1000 | 65407 | 68292 |
| 100まで完了します。 b。 10000 | 186 | 193 |
| 300アップを完了します。 b。 10000 | 2390 | 2359 |
| 500アップを完了します。 b。 10000 | 12667 | 14156 |
| 1000まで完了します。 b。 10000 | 72096 | 71001 |
| トライアン。 1000 | 418 | 418 |
| トライアン。 3000 | 1347 | 1349 |
| トライアン。 5000 | 2426 | 2486 |
| トライアン。 10000 | 6798 | 6559 |
| トライアン。 20000 | 16375 | 16257 |
| トライアン。 40000 | 36574 | 36203 |

さまざまなエッジウェイトの上限を使用して、実行時間がどのように変化するかを確認しました。 また、ある程度のスピードアップがあり、完全グラフの最良の結果は、フィボナッチヒープの結果と同じです。 現在、ペアリングヒープは、スパースグラフ上の他のヒープよりも優れています。

@Toptachamann公開されているブランチはありますか?

@jsichiベンチマークブランチをフォークにプッシュしました。 そこでは、ダイクストラのアルゴリズムのベンチマークのみを行いました。 非推奨にする必要がありますか?

はい、廃止を進める必要があると思います。 最適なヒープ実装をどのように選択しますか(または、MaximumWeightBipartiteMatchingで行うように、ユーザーがそれを選択できるようにします)?

ダイクストラのアルゴリズムにはデフォルトのヒープを用意し、必要に応じてユーザーに別のヒープを提供させる方がよいと思います。 このアプローチは、次の2つの点でより柔軟です。1。ユーザーが独自のベンチマークを実行し、結果に基づいてヒープを選択できるようにします。 2. jheapsのヒープが何らかの方法で再実装または変更された場合、このアプローチを使用して、ダイクストラのアルゴリズムのデフォルトのヒープ実装を変更する方が便利です。

Psペアリングヒープは、ほとんどの場合、エッジウェイトの上限が低くならず、単調なヒープには利点がないため、妥当なデフォルト値のようです。 ただし、重みの範囲が大きくない場合は、ダイクストラのアルゴリズムに単調ヒープを使用することを検討することをお勧めします。

このページは役に立ちましたか?
0 / 5 - 0 評価

関連する問題

haerrel picture haerrel  ·  5コメント

jsichi picture jsichi  ·  12コメント

simlu picture simlu  ·  14コメント

hulk-baba picture hulk-baba  ·  13コメント

IngerMathilde picture IngerMathilde  ·  5コメント