Theoretische Grenzen und spezielle Suchprobleme induktiver Inferenz David Böhme Mat.Nr. 716071 7. September 2005 Diese Arbeit befasst sich im Rahmen des Seminars “Inferenzmethoden” mit Fragestellungen zur Induktion in automatischen Beweisern, konkrekt mit den theoretischen Grenzen der Induktion sowie speziellen Suchproblemen. Der Text orientiert sich dabei weitgehend an den Kapiteln 5 und 6 aus [1]. 1 Theoretische Grenzen induktiver Inferenz Es wäre natürlich wünschenswert, mit der Induktion ein Mittel zum Beweis aller gültiger Formeln beliebiger arithmetischer Theorien an der Hand zu haben. Doch die Erkenntisse der mathematischen Logik, insbesondere von Gödel und Kreisel, zeigen, dass es nicht möglich ist, einen vollständigen induktiven Theorembeweiser zu konsruieren. 1.1 Unvollständigkeit Der Unvollständigkeitssatz von Gödel besagt, dass jedes hinreichend mächtige formale System – insbesondere, wenn es mindestens gleichmächtig zur Peano-Arithmetik ist – unvollständig (oder widersprüchlich) ist. Das heißt, dass es in einem solchen System wahre Aussagen gibt, die sich innerhalb des Systems nicht beweisen lassen. Auch das Hinzufügen der unbeweisbaren Aussagen zur Axiomenbasis des Systems würde nicht helfen, da es laut Gödel trotzdem unvollständig bleibt. Der Gödelsche Unvollständigkeitssatz setzt der Mächtigkeit der Induktion also eine absolute Grenze. Das Problem äußert sich beispielsweise bei der Konstruktion der Induktionsregel für den Beweis einer Vermutung. Es gibt unendlich viele unterschiedliche Induktionsregeln, und für jeden Algorithmus zur Konstruktion von Induktionsregeln gibt es wahre Aussagen, für die der Algorithmus nicht die richtige Regel findet. 1.2 Das Problem der Schnittregel Der Sequenzenkalkül enthält die Schnittregel (cut rule) A, Γ ` ∆, Γ ` A Γ`∆ Wenn ∆ aus A folgt und A sich aus Γ herleiten lässt, dann gilt ∆. Auf diese Weise lässt sich ∆ mit Hilfe von A beweisen. Die Schnittformel genannte Formel A ist anschließend überflüssig und kann “abgeschnitten” werden. Wenn die Schnittregel rückwärts verwendet wird, führt sie zu unendlicher Verzweigung im Suchraum – die Schnittformel kann irgendeine Formel sein. Der Schnittregelsatz (cut elimination theorem) von Gentzen besagt, dass die Schnittregel für Logik erster Stufe redundant ist. Leider gilt das nicht für induktive Theorien – die Schnittregel wird gebraucht. Das Problem lässt sich auch nicht durch Verwendung eines anderen Kalküls wie Resolution umgehen, es taucht in anderer Form erneut auf. Leider handelt es sich auch nicht um ein rein theoretisches Problem mit geringen praktischen Auswirkungen, die Schnittregel wird schon bei recht einfachen Vermutungen gebraucht. 3 2 Suchprobleme induktiver Inferenz Leider genügt es nicht, einfach einige Induktionsregeln zu einem klassischen Beweiser hinzuzufügen – es wird eine unbegrenzte Anzahl an Induktionsregeln benötigt. Auch die Schnittregel wird gebraucht. All das führt zu unendlicher Verzweigung im Suchbaum. Die Automatisierung induktiver Inferenz erfordert also einige zusätzliche Heuristiken, die für klassische Logik nicht benötigt werden. Einige der auftretenden Suchprobleme werden in diesem Abschnitt vorgestellt. 2.1 Konstruktion der Induktionsregel Das Finden einer geeigneten Induktionsregel ist essentiel für den Induktionsbeweis. Eine gute Induktionsregel führt zu einem kurzen Beweis, eine schlechte kann den Beweis scheitern lassen. Da es unendlich viele mögliche Induktionsregeln gibt, lassen sie sich nicht vorausberechnen – sie müssen dynamisch erzeugt werden. Das Standardverfahren zur Bestimmung der Induktionsregel ist die Rekursionsanalyse. 2.1.1 Rekursionsanalyse Die Rekursionsanalyse erzeugt eine Induktionsregel anhand der Definition rekursiver Funktionen, die in der zu beweisenden Vermutung vorkommen. Zunächst wird nach Vorkommen rekursiver Funktionen mit universell quantifizierten Variablen in den Rekursionsargumenten gesucht. Diese Variablen kommen als mögliche Induktionsvariablen in Frage. Aus der rekursiven Definition kann eine Induktionsregel abgeleitet werden (Rekursions/Induktions-Dualismus). Die Konstruktion der Induktionsregel aus der rekursiven Definition hat das Ziel, ebendiese Definition dann im Beweis anwenden zu können. Als Beispiel wird die Vermutung ∀x : nat.∀y : nat.even(x) ∧ even(y) → even(x + y) mit den rekursiven Definitionen even(0) ↔ > even(s(0)) ↔ ⊥ even(s(s(N )) ↔ even(N ) und 4 (2.1) 0+Y ⇒Y s(X) + Y ⇒ s(X + Y ) betrachtet. Aus dem Auftreten von even(x) in der Vermutung kann die Induktionsregel P (0), P (s(0)), ∀x : nat(P (x) → P (s(s(x)))) ∀x : natP (x) (2.2) mit x als Induktionsvariable abgeleitet werden. Durch even(y) ist die gleiche Induktionsregel mit y als Induktionsvariable gegeben. Aus even(x + y) kann keine Regel abgeleitet werden, da das rekursive Argument keine Variable ist. Dafür kommt durch x + y noch P (0), ∀x : nat(P (x) → P (s(x))) ∀x : natP (x) (2.3) als weitere Induktionsregel in Betracht. Da + auf dem ersten Argument definiert ist, kommt hier nur x als Induktionsvariable in Frage, y ist kein rekursives Argument. Welche der Alternativen ist nun die beste? Bei der Frage nach der Induktionsvariablen fällt die Wahl auf x, da es ausschließlich an Stellen vorkommt, in denen es als Rekursionsargument dient. Dadurch werden im Beweisprozess rewriting-Regeln aus den rekursiven Definitionen anwendbar. Solche Stellen heißen unflawed. Variablen wie x im vorliegenden Beispiel, die nur an unflawed-Postitionen vorkommen, heißen selbst unflawed. Dagegen steht das zweite Vorkommen von y in (2.1) nicht an der Stelle eines Rekursionsarguments. Im Beweisprozess würde es (zum Beispiel) durch s(s(y)) ersetzt – darauf ist aber keine rewriting-Regel anwendbar, der Beweis würde steckenbleiben. Dieses Vorkommen von y heißt flawed, entsprechend heißen Variablen, die an flawed-Positionen vorkommen, ebenfalls flawed. 2.1.2 Subsummierung von Induktionsregeln Die Induktionsvariable steht nun fest, doch es bleib die Frage nach der Induktionsregel. Zur Auswahl stehen Regel (2.2) und (2.3). Im vorliegenden Fall wird Regel (2.3) aber von Regel (2.2) subsummiert. Eine Regel A subsummiert Regel B genau dann, wenn der Induktionsterm von A aus wiederholten Anwendungen des Induktionsterms von B besteht. Im vorliegenden Fall ist genau das gegeben, der Term s(s(x)) aus (2.2) ist eine wiederholte Anwendung von s(x) aus (2.3). Da eine subsummierende Regel die subsummierten “enthält”, kann sie diese ersetzen. Subsummierende Induktionsregeln sind also immer vorzuziehen. Die Anwendung von Regel (2.2) auf das Beispiel ergibt nun ∀y : nat.even(s(s(x))) ∧ even(y) → even(s(s(x)) + y) Aus even(s(s(x)) erhält man even(x) durch Anwendung der rekursiven Definition von even. Anwendung der Definition von + auf even(s(s(x) + y)) ergibt even(s(s(x) + y)), 5 im nächsten Schritt even(s(s(x + y))) und schließlich even(x + y) mit der Definition von even. Insgesamt ergibt sich also die Vermutung und der Induktionsschritt ist erfolgreich beendet. Durch die Verwendung der subsummierenden Regel ließ sich die Definition von + zweimal anwenden. Hätte man stattdessen Regel (2.3) verwendet, erhielte man ∀y : nat.even(s(x)) ∧ even(y) → even(s(x) + y) Für even(s(x)) ist aber keine Regel anwendbar, der Beweis bliebe stecken. Eine subsummierte Regel kann eine subsummierende also nicht ersetzen. 2.1.3 Containment von Induktionsregeln Eine andere Methode, aus mehreren alternativen Induktionsregeln die optimale zu bestimmen, ist das containment (Enthaltensein). Eine Induktionsregel A enthält Induktionsregel B genau dann, wenn jeder Induktionsschritt von B in einem Induktionsschritt von A enthalten ist. Ein Induktionsschritt A CondA ∧ IH1A ∧ · · · ∧ IHm → IC enthält einen Induktionsschritt CondB ∧ IH1B ∧ · · · ∧ IHnB → IC genau dann, wenn CondB → CondA gilt und für jedes IHjB ein i mit IHjB = IHiA existiert. In einem solchen Fall ist Induktionsregel A einfacher zu beweisen als B. A ist also vorzuziehen. 2.1.4 Kombinieren von Induktionsregeln Es kann vorkommen, dass keine der in der Rekursionsanalyse generierten Induktionsregeln die anderen subsummiert oder enthält. In diesem Fall müssen die gegebenen Regeln so zu einer einzigen Regel kombiniert werden, dass diese alle anderen enthält oder subsummiert. Das kann beispielsweise durch Vereinigung der Induktionsvorraussetzungen der generierten Regeln erreicht werden. 2.2 Lemmata erzeugen Beim nicht-induktiven Beweisen stellt das explizite Erzeugen von Zwischenlemmata kein großes Problem dar, da eventuell benötigte Lemmata automatisch aus den vorhandenen Regeln generiert werden können. Bei einem induktiven Beweis kann es aber sein, dass sich ein benötigtes Lemma nicht ohne verschachtelte Anwendung von Induktion aus der bestehenden Theorie ableiten lässt – eine Konsequenz der Nichtgültigkeit des Schnittregelsatzes. Ein solches Lemma muss explizit hergeleitet und als Zwischenziel bewiesen werden. 6 2.2.1 Ein Beispiel: Doppelte Spiegelung Dieses Problem soll an einem einfachen Beispiel dargestellt werden. Gegeben sei die Vermutung ∀l : list(τ ).rev(rev(l)) = l (2.4) wobei rev eine Liste spiegelt. Es ist wie folgt definiert: rev(nil) ⇒ nil rev(H :: T ) ⇒ rev(T ) <> (H :: nil) Die Rekursionsanalyse liefert die einschrittige Induktionsregel für Listen P (nil), ∀h : τ.∀t : list(τ ).P (t) → P (h :: t) ∀l : list(τ )P (l) mit l als Induktionsvariable. Damit läuft der Induktionsschritt wie folgt: (2.5) rev(rev(t)) = t ` rev(rev(h :: t)) = h :: t ` rev(rev(t) <> (h :: nil)) = h :: t Hier bleibt der Beweis jedoch stecken, da keine Regeln anwendbar sind. Starke Fertilisierung ist ebenfalls nicht anwendbar. Eine mögliche Lösung des Problems bietet die Einführung eines Zwischenlemmas, im gegebenen Fall ein Distributivgesetz von rev: rev(X <> Y ) ⇒ rev(Y ) <> rev(X) (2.6) Damit kann der Beweis fortgesetzt werden: rev(rev(t)) = t ` rev(rev(t) <> (h :: nil)) = h :: t ` rev(h :: nil) <> rev(rev(t)) = h :: t ` (rev(nil) <> (h :: nil)) <> rev(rev(t)) = h :: t ` (nil <> (h :: nil)) <> rev(rev(t)) = h :: t ` (h :: nil) <> rev(rev(t)) = h :: t ` h :: (nil <> rev(rev(t))) = h :: t ` h :: rev(rev(t)) = h :: t ` h = h ∧ rev(rev(t)) = t Der letzte Schritt enthält die Vermutung. Die Fertilisierung führt zu h = h ∧ >, was sich trivial beweisen lässt. Damit ist natürlich das Suchproblem an sich nicht gelöst. Eine Heuristik, die automatisch die benötigten Lemmata erzeugt, wird benötigt. Dafür sei an dieser Stelle auf weiterführende Literatur verwiesen. 7 2.2.2 Ein zweites Beispiel Als weiteres Beispiel sei die Vermutung ∀l : list(τ ).∀k : list(τ ).rotate(length(l), l <> k) = k <> l (2.7) gegeben. Dabei entfernt rotate(n, l) die ersten n Elemente der Liste l und hängt sie am Ende an. length bestimmt die Länge einer Liste. Die Vermutung besagt, dass wenn length(l) Elemente der Liste l <> k rotiert werden, die Liste k <> l entsteht. Die rekursive Definition von length lautet length(nil) ⇒ 0 length(H :: T ) ⇒ s(length(T )) und die von rotate rotate(0, L) ⇒ L rotate(s(N ), nil) ⇒ nil rotate(s(N ), H :: R) ⇒ rotate(N, T <> (H :: nil) Die Rekursionsanalyse liefert wieder die Induktionsregel (2.5) mit entweder l oder k als Induktionsvariable. l tritt zweimal unflawed und einmal flawed auf, k je einmal flawed und unflawed. Wegen des kleinen Vorteils wird l die Induktionsvariable. Der Beweis entwickelt sich damit wie folgt: rotate(length(t), t <> K) = K <> t ` rotate(length(h :: t), (h :: t) <> k) = k <> (h :: t) ` rotate(s(length(t)), h :: (t <> k)) = k <> (h :: t) ` rotate(length(t), (t <> k) <> (h :: nil)) = k <> (h :: t) An dieser Stelle bleibt der Beweis stecken, weder rewrite-Regeln noch Fertilisierung sind anwendbar. Um fortzufahren, werden zwei Lemmata gebraucht. Für die linke Seite der Gleichung wird das Assoziativitätsgesetz für Listen benötigt: (X <> Y ) <> Z ⇒ X <> (Y <> Z) Für die rechte Seite ist ein Spezialfall der Assoziativität vonnöten: L <> (H :: T ) ⇒ (L <> (H :: nil)) <> T Beide Lemmata werden in der angegebenen Richtung gebraucht, wobei sie in der anderen Richtung natürlich genauso gültig sind. Damit kann der Beweis nun fortgesetzt werden: 8 rotate(length(t), t <> K) = K <> t ` rotate(length(t), (t <> k) <> (h :: nil)) = k <> (h :: t) ` rotate(length(t), t <> (k <> (h :: nil))) = (k <> (h :: nil)) <> t Jetzt ist Fertilisierung anwendbar. Um die Schlussfolgerung mit der Vermutung in Übereinstimmung zu bringen, wird K mit k <> (h :: nil) instanziiert. Universelle Variablen in der Vermutung, die wie hier k nicht als Induktionsvariablen benötigt werden, werden zu freien Variablen und können mit zusammengesetzten Termen instanziiert werden, um später Vermutung und Schlussfolgerung zu unifizieren. 2.3 Generalisierung Es gibt Vermutungen, die nicht ohne Generalisierung bewiesen werden können. Auch das ist eine Konsequenz aus der Ungültigkeit des Schnittregelsatzes. Bei der Generalisierung wird aus einer Vermutung V eine generalisierte Vermutung G konstruiert und dann sowohl G als auch G → V bewiesen. Die Generalisierung muss stark genug sein, um die Schlussfolgerung aus der Induktionsvermutung beweisen zu können, aber auch nicht so stark, dass das Resultat kein Satz mehr ist. 2.3.1 Auseinandergeneralisieren Auch für einfache Vermutungen kann Generalisierung nötig werden, wie beispielsweise für den folgenden Spezialfall des Assoziativgesetzes für die Konnektion von Listen, ∀l : list(τ ).l <> (l <> l) = (l <> l) <> l (2.8) wobei nur die Gleichheitsaxiome und die rekursiven Definitionen verfügbar sind. Rekursionsanalyse liefert wieder (2.5) als Induktionsregel. Mangels Alternative wird l die Induktionsvariable, obwohl es flawed ist. Dadurch schlägt der Beweis fehl. An der 3., 5. und 6. Stelle ist l nicht in der Position eines rekursiven Arguments, trotzdem wird es durch den Induktionsterm ersetzt. Es entsteht (h :: t) <> ((h :: t) <> (h :: t)) = ((h :: t) <> (h :: t)) <> (h :: t) Nur auf das 1., 2. und 4. Vorkommen lässt sich die rekursive Definition von <> anwenden. Der Beweis bleibt stecken: h :: (t <> (h :: (t <> (h :: t)))) = h :: ((t <> (h :: t)) <> (h :: t)) Um hier weiterzukommen, müssen die Vorkommen von l auseinandergeneralisiert werden, so dass die generalisierte Vermutung ∀l : list(τ ).l <> (k <> k) = (l <> k) <> k 9 entsteht. Auch hier wird die Rekursionsanalyse (2.5) als Induktionsregel und l als Induktionsvariable liefern, aber jetzt ist l unflawed. Damit kann der Beweis durchgeführt werden: t <> (k <> k) = (t <> k) <> k ` (h :: t) <> (k <> k) = ((h :: t) <> k) <> k ` h :: (t <> (k <> k)) = (h :: (t <> k)) <> k ` h :: (t <> (k <> k)) = h :: ((t <> k) <> k) ` h = h ∧ t <> (k <> k) = (t <> k) <> k Ab hier kann der Beweis durch Fertilisierung abgeschlossen werden. In diesem Beispiel wurde die Vermutung durch das Beschränken der Induktionsvariablen auf unflawed Vorkommen generalisiert. Dabei wurde auch das zweite Vorkommen von l durch k ersetzt, obwohl es unflawed war. Das hat zwei Gründe. Erstens wäre eine falsche Aussage entstanden: ∀l : list(τ ).l <> (l <> k) = (l <> k) <> k Zweitens wäre auch hier der Beweis nach einem Schritt steckengeblieben. Das Problem, welches Vorkommen der Induktionsvariable generalisiert werden soll, ist nicht trivial. Bislang gibt es keine Heuristik, die immer die richtige Kombination liefert. Es wird auch eine Heuristik benötigt, die bestimmt, ob Auseinandegeneralisieren überhaupt erforderlich ist. Dazu gibt es Ansätze, die auf der Analyse anfänglich fehlgeschlagener Beweise basieren. 2.3.2 Generalisierung von Untertermen Eine weitere Variante der Generalisierung ist die Generalisierung von Untertermen. Als Beispiel dient wieder die rev − rev Vermutung ∀l : list(τ ).rev(rev(l)) = l deren Beweis an der Stelle rev(rev(t)) = t ` rev(rev(t) <> (h :: nil)) = h :: t steckenblieb. An dieser Stelle lässt sich auch schwache Fertilisierung anwenden, um weiterzukommen. Dabei wird die Induktionsvorraussetzung in umgekehrter Richtung als rewrite-Regel auf die rechte Seite der Gleichung angewandt und man erhält rev(rev(t) <> (h :: nil)) = h :: rev(rev(t)) was nun als neues Beweisziel dient. Allerdings bleibt der Beweis wegen der verschachtelten rev-Funktionen erneut stecken. Auf beiden Seiten der Gleichung taucht jedoch der Term rev(t) auf. Er kann durch eine neue Variable, zum Beispiel k ersetzt werden. Man erhält 10 rev(k <> (h :: nil)) = h :: rev(k) Der so generalisierte Ausdruck ist immer noch wahr und die verschachtelten revs sind verschwunden. Der Beweis ist nun deutlich einfacher und führt zum Erfolg. Üblicherweise werden Unterterme nur dan generalisiert, wenn alle Vorkommen einer Variablen, beispielsweise x, in einem gemeinsamen Term, wie f (x) auftreten. Dieser Term wird dann durch eine neue Variable ersetzt. Eine andere Heuristik beschränkt die Auswahl auf Variablen in rekursiven Argumenten. Dadurch kommt die neu eingeführte Variable auch als mögliche Induktionsvariable in Betracht. 2.3.3 Einführen neuer Variablen Eine dritte Generalisierungstechnik ist die Einführung neuer universeller Variablen. Zur Illustration dient ein Spezialfall von Vermutung (2.7) ∀l : list(τ ).rotate(length(l), l) = l Wenn length(l) Elemente am Anfang von l entfernt und am Ende wieder angehängt werden, ist das Resultat wieder die Liste l. Die Rekursionsanalyse liefert wie gehabt (2.5) als Induktionsregel mit l als Induktionsvariable. Damit entwickelt sich der Beweis wie folgt: rotate(length(t), t) = t ` rotate(length(h :: t), h :: t) = h :: t ` rotate(s(length(t)), h :: t) = h :: t ` rotate(length(t), t <> (h :: nil)) = h :: t An dieser Stelle bleibt der Beweis stecken. Als Lösung bietet sich die Einführung einer neuen universellen Variable an. Die generalisierte Vermutung lautet dann ∀l : list(τ ).∀k : list(τ ).rotate(length(l), l <> k) = k <> l Das ist genau die bereits bewiesene Vermutung (2.7). 2.3.4 Übergeneralisierung Ein großes Problem bei der Anwendung von Generalisierungstechniken stellt die Übergeneralisierung dar, also die Generalisierung einer Formel in eine falsche Aussage. Als Beispiel sei die Vermutung ∀l : list(nat).sort(sort(l)) = sort(l) gegeben, wobei sort eine Funktion zum Sortieren einer Liste natürlicher Zahlen ist. Ein automatischer Beweiser könnte hier durch Generalisieren von Untertermen leicht folgende, offensichtlich falsche Aussage generieren 11 ∀k : list(nat).sort(k) = k (2.9) indem der auf beiden Seiten der Gleichung auftretende Term sort(l) durch die neue Variable k ersetzt wird. Eine Teillösung für das Problem wäre, die generierte Formel mit einem GegenbeispielChecker zu prüfen. Diese einfache Technik funktioniert überraschend gut, denn Fehler durch Übergeneralisierung sind im allgemeinen nicht besonders subtil. Eine andere Möglichkeit ist zu versuchen, den übergeneralisierten Ausdruck in eine wahre Aussage umzuwandeln. Beispielsweise kann (2.9) auf diese Weise modifiziert werden: ∀k : list(nat).ordered(k) → sort(k) = k wobei ordered(k) bedeuted, dass k eine geordnete Liste ist. Solche Bedingungen können oft automatisch generiert werden, so dass sich die Methode gut in automatischen Beweisern einsetzen lässt. Leider ist es nicht immer möglich, eine falsche Aussage so zu modifizieren, dass das Resultat noch die ursprüngliche Vermutung subsummiert. 12 Literaturverzeichnis [1] Alan Bundy. The automation of proof by mathematical induction. In Alan Robinson and Andrei Voronkov, editors, Handbook of Automated Reasoning. Elsevier Science Publishers, 2001. [2] Christoph Kreitz. Inferenzmethoden. Vorlesungsskript, 2004. [3] Wikipedia. http://www.wikipedia.de. 13