複数の、または正しい正解を証明するのが困難な(決定論的な)アルゴリズムのテスト


11

この質問が似ていることを序文にしたいと思いますが、私の質問にはランダム性は関係せず、単なる決定的な決定論なので、「既知のシードを使用する」という答えは実際には当てはまりません。同様に、この質問は似ていますが、再び、アルゴリズムが失敗することを期待していません-どの方法が正しいかわかりません。

この質問は、グラフアルゴリズムのテスト中に発生しました。しかし、決してそれらに限定されません。A *などの一部のアルゴリズムには、複数の正解があります。正確な実装に応じて、いくつかの回答のいずれかが得られる場合がありますが、それぞれが同じように正しいです。ただし、どちらを先に吐き出すのかわからないため、テストを難しくする可能性があります。また、回答を手作業で計算するのは非常に時間がかかります。

私の特定のケースでは、Floyd-Warshallを修正して可能な限りすべての最短経路を吐き出すことで回避し、それを手作業でテストしました。それ自体が優れた機能であるという利点がありました。次に、FWからの既知の正しいパスに関して他の機能をテストできます(返されたパスが、その開始/終了ペアに対してFWによって返されたパスのいずれかである場合、それは正しいです)。もちろん、これは、FWの動作方法が原因で、密なグラフでのみ機能しますが、それでも優れています。

ただし、この特性を備えたすべてのアルゴリズムで常に実行できるとは限りません。これまでのところ、私が思いついた最良の答えは、正解そのものではなく、正解の特性をテストすることです。最短パスアルゴリズムに戻るには、返されたパスのコストを既知の正しいコストと比較し、パスが有効であることを確認できます。

これは機能しますが、特に検証自体が複雑な場合(たとえば、正しいアルゴリズムが存在する場合、最小スパニングツリーの検証は既知の難しい問題であり、おそらく以下よりも難しい場合)、すべてが正しく検証されないというリスクがありますMST自体の構築)、この場合、テストコードを広範囲にテストする必要があります。さらに悪いことには、MST検証アルゴリズムをテストするためにMSTを構築する必要があるため、MSTテストがMST検証アルゴリズムの動作に依存し、MST検証アルゴリズムのテストがMST生成コードの動作に依存するという素晴らしいシナリオになります。

最後に、出力を観察し、手作業で検証し、検証したばかりの出力をテストするためにテストをハードコーディングする「簡単な方法」がありますが、毎回テストを修正する必要があるため、それは素晴らしいアイデアではありません実装を少し変更します(これは自動テストで回避することになっています)。

明らかに、答えはある程度テストしている正確なアルゴリズムに依存しますが、いくつかの明確で決定的な「正しい」出力を持つアルゴリズムを検証するための「ベストプラクティス」があるかどうか疑問に思っていましたが、それらの正確な正しい出力は事前に知っていて、事実を確認することすら難しいかもしれません。


3
言語が許可されている場合、それはあなたが可能性を証明する代わりにそれをテストするの正しさを
miniBill

テキストはたくさんありますが、質問はありません。それで、あなたは正確に何を求めていますか?
BЈовић

@BЈовић「複数の、および/または正しい出力を検証するのが難しいアルゴリズムの実装をどのようにテストすればよいですか?」どうすればそれをもっと明確にするかわかりませんが、ごめんなさい。あなたの見方によっては少し広いと考えられるかもしれませんが、未定義だとは思いません。
LinearZoetrope 14

まだわかりません。アルゴリズムはランダム性に依存しませんが、それでも異なる出力を生成できます。それはまったく意味がありません。入力を設定するためのすべてのアルゴリズムには、同じ出力が必要です。そして、それがユニットテストで行われ、テストされます。リンクした論文のアルゴリズムですら。
BЈовић

@BЈовићもちろん決定論的ですが、たとえばグラフがノードの後続を返す順序にも非常に敏感です。少しのバタフライ効果を引き起こす可能性があります。頂点Bの前に頂点Aをスタックにプッシュするかどうかは、両方が最短パスにつながる場合に異なる出力につながります。非安定ソートや最小ヒープなどのライブラリ関数を使用すると、問題が悪化します。
LinearZoetrope 14

回答:


5

正しいプロパティをテストしようとしているのかどうかはわかりませんが、これによりあいまいさが生じます。

グラフアルゴリズムは、最短経路(これは副作用です)を見つけることを目的とせ、エッジと頂点のセットで定義されたコスト関数最小化または最大化すること目的としています。したがって、この機能の最終値をテストし、最初と最後のノードが実際に必要なものであると断言することにより、ソリューションの正確性を確認できます。

各可能なパスの最終コスト関数値を事前に計算できる場合(通常は非現実的)、テスト対象の実装によって提供されるソリューションのコストがこのセットの最小コストと等しいことを確認するだけです(絶対比較)。ゴールドスタンダードアルゴリズムおよび/または実装を「ちょうど」持っている場合は、その出力のコストをテスト対象のアルゴリズムの1つと比較する必要があります(相対比較)

たとえば、単純なテスト設定は次のようになります。

  1. 欲張りアルゴリズムを使用して、テストグラフのVaとVbの間のすべての可能なパスを計算します。
  2. これらの各パスのコスト関数(たとえば、すべてのエッジの重みが1に等しい場合の長さ)を計算し、最小値を見つけます。
  3. テスト対象のアルゴリズムを適用します。
  4. 単体テストで、テストしたアルゴリズムのコスト値が欲張りな解の最小値に等しいと断言します。

グラフベースの最適化について詳しく知りたい場合は、別のコンテキスト(コンピュータービジョンの問題)でも、ユーリボイコフの出版物をご覧ください


私は賛成しましたが、受け入れるまで少し待ちます。これは、質問で述べた「正解の特性のテスト」です。問題は常に、正しいことを確認していることを確認することにあります。たとえば、一度に返されたコストをチェックし、パスが有効であることを確認していました。もちろん、パスは有効でした!開始ノードのみでした!そのため、テストを変更して、パス自体に実際に返された正しいコストがあることを確認する必要がありました。確かに愚かな間違いですが、出力にこのような相互作用が多いほど、その可能性は高くなります。
LinearZoetrope 14

私の観点では@Jsorは、テストの継続的な改善の利点です。最初にソリューションのすべての正確性の特性を把握することはできません。その後、ある障害に陥り、テストを改善するなど。
山水荘14

この回答では、正解の特性をテストすることをお勧めしますが、重要なことは、どの特性が適切なテストになるかを選択することです。この例では、回答がAからBへのパスであり、コスト関数が最小値に等しいことを確認すると、すべての正しい回答が満たす2つの基準が得られますが、誤った回答は両方の基準を満たしません。この答えがまだ出されていなかったなら、私は似たようなものを勧めたでしょう。確かに、どの特性をテストするかを知るのは簡単ではありません。
デビッドK

0

あなたの質問に対する直接的な答えは、より良いテストケースを選択することだと思います。あなたが使用しているテストケースについて疑問に思います。使用するグラフは、人間が予想される応答を比較的簡単に判断できるCANNEDグラフにすることができます。アルゴリズムが確実に処理する「エッジ」ケースを把握し、特定のエッジケースごとに、人間が計算しやすい定型グラフを作成してください。たとえば、Djikstraアルゴリズムの場合、実際のシステムが500x500であっても、すべてのエッジケースをカバーする5x5または7x7グラフを作成できます。

次に、最終的な健全性チェックとして、より現実的なグラフテストケースを作成できます。しかし、いずれにしても、sansuisoには、正しいプロパティをテストしていることを確認する必要があることが指摘されている箇所にスポットがあると思います。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.