13

私は、いくつかの人気のあるpythonパッケージをベースとして使用して、グラフとネットワーク用のオープンソース近似アルゴリズムライブラリに取り組んでいます。主な目標は、グラフとネットワーク上のNP完全問題の最新の近似アルゴリズムを網羅することです。この理由は、1)これをカバーする優れた(最新の)統合パッケージを見たことがないこと、および2)NP困難最適化問題の近似アルゴリズムについて学習するための優れた教育ツールになることです。

このライブラリを構築する際に、私はユニットテストを使用して健全性チェックを行っています(適切な開発者が行うように)。ユニットテストは、その性質上、近似アルゴリズムが正しい解を返さない可能性があるため、多少注意が必要です。現在、私はいくつかの小さなインスタンスを手作業で解決し、返された結果がそれに一致することを確認していますが、これは望ましくなく、実装の意味でスケーラブルでもありません。

近似アルゴリズムをユニットテストするための最良の方法は何でしょうか?ランダムなインスタンスを生成し、返される結果がアルゴリズムによって保証された範囲よりも小さいことを確認しますか?これには誤検知があるように思われます(テストはその時点で幸運であり、すべてのインスタンスが制限を下回ることが保証されているわけではありません)。

4

3 に答える 3

4

ここで2つの懸念を分離する必要があります。近似アルゴリズムの品質とそれらのアルゴリズムの実装の正確さ。

近似アルゴリズムの品質をテストすることは、通常、ソフトウェア開発で使用される単体テスト方法には役立ちません。たとえば、問題の実際のサイズを表すランダムな問題を生成する必要があります。解決できない大きなインスタンスのアルゴリズムの品質を判断するために、上限/下限を取得するために数学的な作業を行う必要がある場合があります。または、既知または最もよく知られている解決策がある問題テストセットを使用して、結果を比較します。ただし、いずれの場合も、単体テストは近似アルゴリズムの品質を向上させるのにあまり役立ちません。これは、最適化と数学に関するドメイン知識が役立つ場所です。

実装の正確さは、単体テストが本当に役立つところです。ここでおもちゃサイズの問題を使用して、既知の結果(手動で解決するか、コードで慎重に段階的にデバッグすることで検証)をコードが生成するものと比較できます。ここでは、小さな問題があるだけで十分であるだけでなく、テストが高速に実行され、開発サイクル中に何度も実行できるようにすることが望ましいです。これらのタイプのテストは、アルゴリズム全体が正しい結果に到達していることを確認します。コードの大部分をブラックボックスとしてテストしているため、単体テストと統合テストの間のどこかにあります。しかし、私はこれらのタイプのテストが最適化ドメインで非常に役立つことを発見しました。このタイプのテストで行うことをお勧めすることの1つは、乱数ジェネレーターの固定シードを使用して、アルゴリズムのすべてのランダム性を削除することです。これらのテストは常に決定論的な方法で実行され、100%の時間でまったく同じ結果が得られる必要があります。また、アルゴリズムの下位レベルのモジュールで単体テストを行うことをお勧めします。グラフ上の円弧に重みを割り当てるメソッドを分離し、正しい重みが割り当てられているかどうかを確認します。目的関数値の計算関数を分離し、それを単体テストします。あなたは私の主張を理解します。

これらのスライスの両方をカットするもう1つの懸念は、パフォーマンスです。小さなトイプロブレムでパフォーマンスを確実にテストすることはできません。また、動作中のアルゴリズムのパフォーマンスを大幅に低下させる変更をすぐに実現することが非常に望ましいです。アルゴリズムの実行バージョンを取得したら、パフォーマンスを測定し、それを自動化してパフォーマンス/統合テストにする、より大きなテスト問題を作成できます。時間がかかるため、これらの実行頻度を減らすことができますが、少なくとも、リファクタリング中またはアルゴリズムへの新機能の追加中に、新たに導入されたパフォーマンスのボトルネックが早期に通知されます。

于 2011-09-12T18:10:05.480 に答える
2

生成されたソリューションの有効性を確認することは、明らかな最初のステップです。

さらに、1つの迎え角は、予想される近似解がわかっているインスタンスを使用した回帰テストである可能性があります(たとえば、アルゴリズムを手動で実行するか、他の誰かの同じアルゴリズムの実装を使用して取得します)。

TSPLIBTSPのような問題など、既知の(最適な)ソリューションを備えた問題インスタンスのリポジトリも存在します。おそらく、これらは何らかの用途に使用される可能性があります。

問題のアルゴリズムに既知の上限がある場合は、多くのランダムインスタンスを生成し、上限に対してヒューリスティックソリューションを検証することが有益であることがわかります。これを行う場合は、実行を再現可能にすることをお勧めします(たとえば、常に同じ乱数ジェネレーターとシードを使用することによって)。

最後の注意点:いくつかの問題については、完全にランダムなインスタンスは、平均して、の適切な近似解を見つけるのが非常に簡単です。均一かつ独立して選択されたアーク重みを持つ非対称TSPは、そのような例の1つです。テスト戦略に影響を与える可能性があるため、これについて言及します。

于 2011-09-12T17:31:16.027 に答える
1

通常、チェックできることがあります。たとえば、アルゴリズムは、最適ではない場合でも、制約を満たすソリューションを常に返すことを確認できます。また、あらゆる機会にアサーションチェックを行う必要があります。これらはプログラムに固有ですが、ある程度の量が保存されていること、増加するか、最悪の場合は同じままであることが減少しないこと、または一部のローカルと見なされることをチェックする場合があります。最適は本当に局所最適です。

これらの種類のチェックと、すでに述べた範囲のチェックを考えると、ランダムに生成された非常に多くの小さな問題に対してテストを実行することをお勧めします。ランダムシードは、問題102324で失敗した場合に繰り返すことができるように選択されます。その前に102323の問題を実行せずにデバッグを失敗しました。多数の問題があると、根本的なバグが原因で、チェックに失敗するほど明白なエラーが発生する可能性が高くなります。小さな問題では、バグを見つけて修正できる可能性が高くなります。

于 2011-09-12T18:37:23.197 に答える