Testen von (deterministischen) Algorithmen mit mehreren oder schwer zu beweisenden richtigen Antworten

11

Ich möchte vorwegnehmen, dass diese Frage ähnlich ist, aber meine Frage beinhaltet keine Zufälligkeit, sondern nur einen heiklen Determinismus, sodass die Antwort "Verwenden Sie einen bekannten Samen" nicht wirklich zutrifft. Ebenso ist diese Frage ähnlich, aber ich erwarte auch hier nicht, dass der Algorithmus jemals fehlschlägt - ich weiß nur nicht, wie er richtig sein wird.

Diese Frage stellte sich beim Testen von Graph-Algorithmen. ist aber keineswegs auf sie beschränkt. Einige Algorithmen wie A * können mehrere richtige Antworten haben. Abhängig von Ihrer genauen Implementierung erhalten Sie möglicherweise eine von mehreren Antworten, von denen jede gleichermaßen korrekt ist. Dies kann es jedoch schwierig machen, sie zu testen, da Sie nicht wissen, welche sie im Voraus ausspucken werden, und es sehr zeitaufwändig ist, die Antworten von Hand zu berechnen.

In meinem speziellen Fall habe ich Floyd-Warshall so modifiziert, dass er jeden möglichen kürzesten Weg ausspuckt , und die Zeit damit verbracht, dies von Hand zu testen. Es hatte den Vorteil, ein gutes Feature für sich zu sein. Dann könnte ich andere Funktionen in Bezug auf die bekannten korrekten Pfade von FW testen (wenn der zurückgegebene Pfad einer der von FW für dieses Start / End-Paar zurückgegebenen Pfade ist, ist er korrekt). Natürlich funktioniert dies aufgrund der Funktionsweise von FW nur ​​für dichte Grafiken, aber es ist immer noch schön.

Dies ist jedoch möglicherweise nicht immer für alle Algorithmen mit dieser Eigenschaft möglich. Bisher ist die beste Antwort, die ich gefunden habe, die Eigenschaften einer richtigen Antwort zu testen und nicht die richtige Antwort selbst. Um zu den Algorithmen für kürzeste Pfade zurückzukehren, können Sie die Kosten des zurückgegebenen Pfads mit den bekannten richtigen Kosten vergleichen und sicherstellen, dass der Pfad gültig ist.

Dies funktioniert, aber es besteht die Gefahr, dass nicht alles korrekt überprüft wird, je mehr Kriterien für die Richtigkeit vorhanden sind, insbesondere wenn die Überprüfung selbst komplex ist (z. B. wenn korrekte Algorithmen vorhanden sind , ist die Überprüfung eines minimalen Spannbaums ein bekanntes schwieriges Problem, wahrscheinlich schwieriger als MST selbst erstellen). In diesem Fall müssen Sie Ihren Testcode jetzt ausführlich testen. Schlimmer noch: Vermutlich müssen Sie ein MST erstellen, um einen MST-Überprüfungsalgorithmus zu testen, sodass Sie jetzt ein großartiges Szenario haben, in dem Ihr MST-Test davon abhängt, dass Ihr MST-Überprüfungsalgorithmus funktioniert, und Ihr MST-Überprüfungsalgorithmus-Test von Ihrem MST-Generierungscode abhängt.

Schließlich gibt es den "billigen Weg", bei dem die Ausgabe beobachtet, von Hand überprüft und dann der Test hart codiert wird, um die gerade überprüfte Ausgabe zu testen. Dies ist jedoch keine gute Idee, da Sie den Test möglicherweise jedes Mal überarbeiten müssen Ändern Sie die Implementierung ein wenig (was durch automatisierte Tests vermieden werden soll).

Natürlich hängt die Antwort von dem genauen Algorithmus ab, den Sie bis zu einem gewissen Grad testen, aber ich habe mich gefragt, ob es "Best Practices" für die Überprüfung von Algorithmen gibt, die mehrere eindeutige, deterministische "korrekte" Ausgaben haben, aber diese genauen korrekten Ausgaben sind schwierig zu erreichen im Voraus wissen und möglicherweise schwer nachträglich zu überprüfen.

LinearZoetrope
quelle
3
Wenn die Sprache es erlaubt, können Sie die Richtigkeit beweisen, anstatt sie zu testen
miniBill
Es gibt viel Text, aber keine Frage. Also, was genau fragst du?
BЈовић
@ BЈовић "Wie soll ich Implementierungen von Algorithmen mit mehreren und / oder schwer zu überprüfenden korrekten Ausgaben testen?" Ich bin mir nicht sicher, wie ich das klarer machen soll, sorry. Ich gebe zu, dass es je nach Ihrer Perspektive als etwas weit gefasst angesehen werden kann, aber ich denke nicht, dass es undefiniert ist.
LinearZoetrope
Ich verstehe immer noch nicht. Ihr Algorithmus hängt nicht von der Zufälligkeit ab und kann dennoch unterschiedliche Ausgaben erzeugen. Das macht überhaupt keinen Sinn. Jeder Algorithmus für festgelegte Eingaben muss dieselben Ausgaben haben. Und genau das wird in Unit-Tests gemacht und getestet. Sogar der Algorithmus in dem Artikel, den Sie verlinkt haben.
BЈовић
@ BЈовић Natürlich ist es deterministisch, aber es ist auch sehr empfindlich gegenüber z. B. der Reihenfolge, in der der Graph die Nachfolger eines Knotens zurückgibt. Es kann einen Schmetterlingseffekt verursachen. Ob Sie Scheitelpunkt A auf einen Stapel vor Scheitelpunkt B verschieben, führt zu einer anderen Ausgabe, wenn beide zu einem kürzesten Pfad führen. Die Verwendung von Bibliotheksfunktionen wie instabilen Sortierungen oder Min-Heaps verschärft das Problem nur.
LinearZoetrope

Antworten:

5

Ich bin nicht sicher, ob Sie versuchen, die richtige Eigenschaft zu testen, und dies führt zu Ihrer Mehrdeutigkeit.

Graph-Algorithmen zielen nicht darauf ab, einen kürzesten Weg zu finden (dies ist ein Nebeneffekt), sondern darauf , eine Kostenfunktion zu minimieren oder zu maximieren, die für die Menge der Kanten und Eckpunkte definiert ist. Auf diese Weise können Sie die Richtigkeit einer Lösung überprüfen, indem Sie den Endwert dieser Funktion testen und feststellen, dass der erste und der letzte Knoten tatsächlich erforderlich sind.

Wenn Sie den endgültigen Kostenfunktionswert für jeden möglichen Pfad vorberechnen können (normalerweise unrealistisch), müssen Sie nur überprüfen, ob die Kosten der von der zu testenden Implementierung bereitgestellten Lösung den Mindestkosten in diesem Satz entsprechen (absoluter Vergleich) ). Wenn Sie "nur" einen Goldstandardalgorithmus und / oder eine Goldstandardimplementierung haben, sollten Sie die Kosten seiner Ausgabe mit denen des zu testenden Algorithmus vergleichen (relativer Vergleich).

Ein naiver Testaufbau wäre beispielsweise:

  1. Berechnen Sie alle möglichen Pfade zwischen Va und Vb im Testdiagramm mit einem Greedy-Algorithmus.
  2. Berechnen Sie für jeden dieser Pfade die Kostenfunktion (z. B. die Länge, wenn alle Kantengewichte gleich 1 sind) und ermitteln Sie den Mindestwert.
  3. Wenden Sie den zu testenden Algorithmus an.
  4. Stellen Sie in Ihrem Komponententest fest, dass der Kostenwert des getesteten Algorithmus dem Minimum der gierigen Lösungen entspricht.

Wenn Sie mehr über die graphbasierte Optimierung erfahren möchten, können Sie sich hier die Veröffentlichungen von Yuri Boykov ansehen , allerdings in einem anderen Kontext (Computer Vision-Probleme).

Sansuiso
quelle
Ich habe gestimmt, aber ich werde ein bisschen warten, um zu akzeptieren. Dies ist der "Test für die Eigenschaften einer korrekten Antwort", den ich in der Frage erwähnt habe. Das Problem besteht immer darin, sicherzustellen, dass Sie das Richtige überprüfen. Zum Beispiel überprüfte ich sofort die zurückgegebenen Kosten und stellte sicher, dass der Pfad gültig war. Natürlich war der Weg gültig! Es war nur der Startknoten! Also musste ich die Tests ändern, um sicherzustellen, dass der Pfad selbst tatsächlich die zurückgegebenen, korrekten Kosten hatte. Ein dummer Fehler, klar, aber je mehr Interaktionen wie diese Ihre Ausgabe hat, desto wahrscheinlicher sind sie.
LinearZoetrope
@Jsor aus meiner Sicht ist es der kontinuierliche Verbesserungsvorteil des Testens: Sie können zunächst nicht alle Korrektheitseigenschaften der Lösung herausfinden, dann eines Tages einen Fehler erleiden, Ihren Test verbessern und so weiter.
Sansuiso
In dieser Antwort wird empfohlen, die Merkmale der richtigen Antwort zu testen. Wichtig ist jedoch, dass Sie auswählen, welche Merkmale einen guten Test ausmachen. Wenn Sie in diesem Beispiel überprüfen, ob die Antwort ein Pfad von A nach B ist und ob die Kostenfunktion dem Mindestwert entspricht, erhalten Sie zwei Kriterien, die alle richtigen Antworten erfüllen, während keine falschen Antworten beide Kriterien erfüllen. Wenn diese Antwort nicht bereits gegeben worden wäre, hätte ich etwas Ähnliches empfohlen. Zugegeben, es ist oft nicht einfach zu wissen, welche Eigenschaften getestet werden sollen.
David K
0

Ich denke, die direkte Antwort auf Ihre Frage ist, bessere Testfälle auszuwählen. Ich frage mich über die Testfälle, die Sie verwenden. Die von Ihnen verwendeten Diagramme können CANNED-Diagramme sein, bei denen es für einen Menschen relativ einfach ist, die erwartete Reaktion zu bestimmen. Versuchen Sie, die "Rand" -Fälle herauszufinden, die Ihr Algorithmus verarbeiten soll, und erstellen Sie für jeden der bestimmten Randfälle ein vordefiniertes Diagramm, das für einen Menschen leicht zu berechnen ist. Im Fall des Djikstra-Algorithmus können Sie beispielsweise wahrscheinlich einige 5x5- oder 7x7-Diagramme erstellen, die alle Ihre Randfälle abdecken, obwohl Ihr reales System möglicherweise 500x500 ist.

Als letzte Überprüfung der Gesundheit können Sie dann ein oder zwei realistischere Graphentestfälle erstellen. Aber auf jeden Fall denke ich, dass Sansuiso genau dort ist, wo darauf hingewiesen wird, dass Sie sicher sein müssen, dass Sie auf die richtige Eigenschaft testen.

Dunk
quelle