Ich habe einen gierigen Algorithmus, von dem ich vermute, dass er richtig ist, aber ich bin mir nicht sicher. Wie überprüfe ich, ob es korrekt ist? Was sind die Techniken, um zu beweisen, dass ein gieriger Algorithmus korrekt ist? Gibt es gemeinsame Muster oder Techniken?
Ich hoffe, dass dies eine Referenzfrage wird, auf die Anfänger verweisen können. daher sein weiter gefasster Anwendungsbereich. Bitte achten Sie darauf, allgemeine, didaktisch aufbereitete Antworten zu geben, die an mindestens einem Beispiel illustriert sind, aber dennoch viele Situationen abdecken. Vielen Dank!
Antworten:
Letztendlich benötigen Sie einen mathematischen Korrektheitsnachweis. Ich werde im Folgenden auf einige Beweistechniken eingehen, aber bevor ich darauf eingehe, möchte ich Ihnen einige Zeit sparen: Bevor Sie nach einem Beweis suchen, versuchen Sie es mit zufälligen Tests.
Zufällige Tests
Als ersten Schritt empfehle ich Ihnen, Ihren Algorithmus anhand von Zufallstests zu testen. Es ist erstaunlich, wie effektiv dies ist: Meiner Erfahrung nach scheint zufälliges Testen für gierige Algorithmen unangemessen effektiv zu sein. Verbringen Sie 5 Minuten damit, Ihren Algorithmus zu verschlüsseln, und sparen Sie sich möglicherweise ein oder zwei Stunden, um einen Beweis zu finden.
Die Grundidee ist einfach: Implementieren Sie Ihren Algorithmus. Implementieren Sie auch einen Referenzalgorithmus, von dem Sie wissen, dass er korrekt ist (z. B. einen, der alle Möglichkeiten ausgiebig ausprobiert und das Beste ausnutzt). Es ist in Ordnung, wenn Ihr Referenzalgorithmus asymptotisch ineffizient ist, da Sie dies nur auf kleinen Probleminstanzen ausführen. Generieren Sie dann nach dem Zufallsprinzip eine Million kleiner Probleminstanzen, führen Sie beide Algorithmen aus und überprüfen Sie, ob Ihr Kandidatenalgorithmus in jedem Fall die richtige Antwort gibt.
Empirisch werden Sie dies häufig bei zufälligen Tests feststellen, wenn der Algorithmus Ihres Kandidaten für eine Gier inkorrekt ist. Wenn es in allen Testfällen richtig zu sein scheint, sollten Sie mit dem nächsten Schritt fortfahren: der Erstellung eines mathematischen Beweises für die Richtigkeit.
Mathematische Korrektheitsnachweise
OK, wir müssen also beweisen, dass unser gieriger Algorithmus korrekt ist: dass er die optimale Lösung ausgibt (oder, wenn es mehrere optimale Lösungen gibt, die gleich gut sind, dass er eine davon ausgibt).
Das Grundprinzip ist intuitiv:
Prinzip: Wenn Sie nie eine schlechte Wahl treffen, tun Sie alles in Ordnung.
Gierige Algorithmen beinhalten normalerweise eine Folge von Auswahlmöglichkeiten. Die grundlegende Beweisstrategie ist, dass wir versuchen, zu beweisen, dass der Algorithmus niemals eine schlechte Wahl trifft. Gierige Algorithmen können nicht zurückverfolgen - sobald sie eine Entscheidung getroffen haben, sind sie festgeschrieben und werden diese Entscheidung niemals rückgängig machen -, daher ist es wichtig, dass sie niemals eine schlechte Entscheidung treffen.
Was wäre eine gute Wahl? Wenn es eine einzige optimale Lösung gibt, ist es leicht zu erkennen, was eine gute Wahl ist: jede Wahl, die mit der von der optimalen Lösung getroffenen identisch ist. Mit anderen Worten, wir werden versuchen zu beweisen, dass zu jedem Zeitpunkt der Ausführung der Greedy-Algorithmen die bisher vom Algorithmus getroffene Auswahlsequenz genau mit einem Präfix der optimalen Lösung übereinstimmt. Wenn es mehrere gleich gute optimale Lösungen gibt, ist eine gute Wahl eine, die mit mindestens einem der Optima übereinstimmt. Mit anderen Worten, wenn die Auswahlreihenfolge des Algorithmus bisher mit einem Präfix einer der optimalen Lösungen übereinstimmt, ist bis jetzt alles in Ordnung (es ist noch nichts schiefgegangen).
Um das Leben zu vereinfachen und Ablenkungen zu vermeiden, konzentrieren wir uns auf den Fall, dass es keine Bindungen gibt: Es gibt eine einzige, einzigartige optimale Lösung. Alle Maschinen werden auf den Fall übertragen, dass es ohne grundlegende Änderungen mehrere gleich gute Optima geben kann, aber Sie müssen ein bisschen vorsichtiger mit den technischen Details umgehen. Ignorieren Sie zunächst diese Details und konzentrieren Sie sich auf den Fall, in dem die optimale Lösung einzigartig ist. So können Sie sich auf das Wesentliche konzentrieren.
Es gibt ein sehr verbreitetes Beweismuster, das wir verwenden. Wir werden hart arbeiten, um die folgende Eigenschaft des Algorithmus zu beweisen:
Behauptung: Sei die vom Algorithmus ausgegebene Lösung und OS O die optimale Lösung. Wenn unterscheidet sich von ist O , dann können wir optimieren O eine andere Lösung zu erhalten O * , die sich von ist O und streng besser als O .S O O O∗ O O
Beachten Sie, warum dies nützlich ist. Wenn die Behauptung wahr ist, folgt, dass der Algorithmus korrekt ist. Dies ist im Grunde ein Beweis durch Widerspruch. Entweder ist dasselbe wie O oder es ist anders. Wenn es anders ist, können wir eine andere Lösung findenS O , die als streng besser OO∗ O - aber das ist ein Widerspruch, wie wir definierten die optimale Lösung zu sein , und es kann keine Lösung sein , die als besser. Wir sind gezwungen zu folgern, dass S nicht anders sein kann als O ; S muss immer gleich O seinO S O S O Das heißt, der Greedy-Algorithmus gibt immer die richtige Lösung aus. Wenn wir die Behauptung oben beweisen können, haben wir unseren Algorithmus als korrekt erwiesen.
Fein. Wie beweisen wir die Behauptung? Wir denken an eine Lösung als einen Vektor ( S 1 , … , S n ), der der Folge von n Auswahlen entspricht, die vom Algorithmus getroffen wurden, und ebenso denken wir an die optimale Lösung O als einen Vektor ( O 1 , … , O n ) entsprechend der Reihenfolge der Entscheidungen, die zu O führen würden . Wenn S von O verschieden ist , muss ein Index i existieren, bei dem S i ≠ istS ( S1, … , Sn) n O ( O1, … , On) O S O ich ; wir werden uns auf das kleinste konzentrieren, wie ich . Dannwir zwicken O , indem O ein wenig in der i - ten Position Spiel S i ,heißt, werden wir die optimale Lösung optimieren O durch die Änderung i - te Wahl auf die von der GreedyAlgorithmus Auserwählte, und dann Wir werden zeigen, dass dies zu einer noch besseren Lösung führt. Insbesondere definieren wir O ∗ als so etwas wieSich≠ Oich ich O O ich Sich O ich O∗
mit der Ausnahme, dass wir den -Teil häufig leicht ändern müssen, um die globale Konsistenz zu gewährleisten. Ein Teil der Beweisstrategie beinhaltet ein gewisses Maß an Klugheit bei der Definition von O ∗ . Dann wird das Fleisch des Beweises darin bestehen, Fakten über den Algorithmus und das Problem zu verwenden, um zu zeigen, dass O ∗ streng besser als O istOi + 1, Oi + 2, … , On O∗ O∗ O ; Hier benötigen Sie einige problemspezifische Einblicke. Irgendwann müssen Sie sich mit den Details Ihres spezifischen Problems befassen. Dies vermittelt Ihnen jedoch einen Eindruck von der Struktur eines typischen Korrektheitsnachweises für einen gierigen Algorithmus.
Ein einfaches Beispiel: Teilmenge mit maximaler Summe
Dies ist möglicherweise einfacher zu verstehen, wenn Sie ein einfaches Beispiel im Detail durcharbeiten. Betrachten wir das folgende Problem:
Eingabe: Eine Menge von ganzen Zahlen, eine ganze Zahl k Ausgabe: Eine Menge S ⊆ U der Größe k, deren Summe so groß wie möglich istU k
S⊆ U k
Es gibt einen natürlichen Greedy-Algorithmus für dieses Problem:
Zufällige Tests legen nahe, dass dies immer die optimale Lösung ergibt. Lassen Sie uns also formal beweisen, dass dieser Algorithmus korrekt ist. Beachten Sie, dass die optimale Lösung einzigartig ist, sodass wir uns nicht um Krawatten kümmern müssen. Lassen Sie uns die oben skizzierte Behauptung beweisen:
Behauptung: Sei die von diesem Algorithmus ausgegebene Lösung am Eingang U , k und O die optimale Lösung. Wenn SS U,k O , können wir eine andere Lösung konstruierenS≠O deren Summe noch größer als O ist .O∗ O
Beweis. Angenommen, , und sei i der Index der ersten Iteration, in der x i ∉ O ist . (Ein solcher Index i muss existieren, da wir S ≠ O angenommen haben und nach der Definition des Algorithmus S = { x 1 , … , x k } haben .) Da (nach Annahme) i minimal ist, müssen wir haben x 1 , … , xS≠O i xi∉O i S≠O S={x1,…,xk} i und insbesonderex1,…,xi−1∈O hat die Form O = { x 1 , x 2 , ... , x i - 1 , x ' i , x ' i + 1 , ... , x ' n } , wobei die Zahlen x 1 , ... , x i - 1 , x ' i , ... , x ' nO O={x1,x2,…,xi−1,x′i,x′i+1,…,x′n} x1,…,xi−1,x′i,…,x′n sind in absteigender Reihenfolge aufgeführt. Wenn wir uns ansehen, wie der Algorithmus auswählt , sehen wir, dass wir x i > x ' j für alle j ≥ i haben müssen . Insbesondere gilt x i > x ' i . Definiere also O = O ∪ { x i } ∖ { x ′ i } , dh wir erhalten O ∗, indem wir die i- te Zahl in O löschenx1,…,xi xi>x′j j≥i xi>x′i O=O∪{xi}∖{x′i} O∗ i O und Hinzufügen von . Nun ist die Summe der Elemente von O ∗ die Summe der Elemente von O plus x i - x ' i und x i - x ' i > 0 , so dass die Summe von O ∗ streng größer als die Summe von O ist . Dies beweist die Behauptung. ◼xi O∗ O xi−x′i xi−x′i>0 O∗ O ■
Die Intuition hier ist, dass, wenn der gierige Algorithmus jemals eine Wahl trifft, die mit inkonsistent ist , wir beweisen können, dass O noch besser sein könnte, wenn es so modifiziert würde, dass es das Element enthält, das zu diesem Zeitpunkt vom gierigen Algorithmus ausgewählt wurde. Da O optimal ist, kann es unmöglich einen Weg geben, es noch besser zu machen (das wäre ein Widerspruch). Die einzige verbleibende Möglichkeit ist, dass unsere Annahme falsch war: Mit anderen Worten, der gierige Algorithmus wird niemals eine Wahl treffen das heißt nicht mit O .O O O O
Dieses Argument wird oft als Austauschargument oder Austauschlemma bezeichnet . Wir fanden den ersten Ort, an dem sich die optimale Lösung von der gierigen Lösung unterscheidet, und stellten uns vor, dieses Element von gegen die entsprechende gierige Wahl auszutauschen (ausgetauschtes x ' iO x′i gegen ). Einige Analysen haben gezeigt, dass dieser Austausch nur die optimale Lösung verbessern kann - aber per Definition kann die optimale Lösung nicht verbessert werden. Die einzige Schlussfolgerung ist also, dass es keinen Ort geben darf, an dem sich die optimale Lösung von der gierigen Lösung unterscheidet. Wenn Sie ein anderes Problem haben, suchen Sie nach Möglichkeiten, dieses Austauschprinzip in Ihrer spezifischen Situation anzuwenden.xi
quelle
then we can tweak O to get another solution O∗ that is different from O and strictly better than O
verwirrt mich. Wenn es mehrere optimale Lösungen gibt, ist es möglich, dassS != O
beide immer noch optimal sind. wir können O optimieren, um "eher wie" S zu sein (O ∗ zu erschaffen) und dennoch genauso gut zu sein wie (nichtstrictly better than
) O.a single, unique optimal solution
. Da es bei dieser Frage darum geht, jeden gierigen Algorithmus als richtig zu beweisen , möchte ich eine Antwort für Fälle geben, in denen mehrere optimale Lösungen existieren können. Es ist schon eine Weile her, dass ich all dies studiert habe, aber reicht es nicht aus, zu beweisen, dass Sie jedes Element O_i in einer optimalen Lösung O austauschen können, die sich von der alg unterscheidet. Lösung S mit S_i und noch eine Lösung O ', die nicht schlechter als O ist?Ich werde den folgenden einfachen Sortieralgorithmus als Beispiel verwenden:
Um die Richtigkeit zu beweisen, benutze ich zwei Schritte.
Für den ersten Punkt wähle ich eine geeignete Kostenfunktion aus, für die ich zeigen kann, dass der Algorithmus sie in jedem Schritt verbessert.
In diesem Beispiel wähle ich die Anzahl der Inversionen in der Eingabeliste. Eine Inversion in einer Liste ist ein Paar von Einträgen A [ i ] , A [ j ], so dass A [ i ] > A [ j ] aber i < j ist . Die Anzahl der Inversionen ist immer nicht negativ und eine sortierte Liste enthält 0 Inversionen.A A[i] A[j] A[i]>A[j] i<j
Dies beweist, dass der Algorithmus schließlich beendet wird.
Die Anzahl der Inversionen in einer sortierten Liste ist 0. Wenn alles gut geht, reduziert der Algorithmus die Anzahl der Inversionen auf 0. Wir müssen nur zeigen, dass es nicht in einem lokalen Minimum hängen bleibt.
Normalerweise beweise ich das durch Widerspruch. Ich gehe davon aus, dass der Algorithmus angehalten hat, aber die Lösung nicht korrekt ist. Im Beispiel bedeutet dies, dass die Liste noch nicht sortiert ist, aber keine benachbarten Elemente in der falschen Reihenfolge vorhanden sind.
Dies beweist, dass der Algorithmus nur stoppt, wenn die Liste sortiert ist. Und damit sind wir fertig.
quelle