Logische Programmierung Klaus Becker 2011 2 Logische Programmierung
Logische Programmierung Klaus Becker 2011
2 Logische Programmierung Alle Menschen sind sterblich. Sokrates ist ein Mensch. Sokrates ist sterblich(X) : - mensch(X). mensch(sokrates). ? - sterblich(X). X = sokrates; No.
3 Teil 1 Modellierung von Wissen
4 Die Welt der griechischen Götter (Heaven) Uranus = Gaea (Earth) | -------------------| | | Cronus = Rhea | Coeus = Phoebe Oceanus = Tethys | | | -----------| | Leto = Zeus Iapetus | | | Hestia | Poseidon | Demeter=Zeus Hades | -------- | | | Persephone | | Prometheus | ----- | Zeus = Hera | | | Athena | | | -------| | | Ares Hebe Hephaestus Apollo | Atlas | Epimetheus Artemis | | Zeus=Maia Zeus=Dione | | Hermes Aphrodite Aufgabe Kannst du die folgenden Verwandschaftsbeziehungen klären? (a) Wer ist ein Cousin von Zeus? (b) Hat Zeus auch mit Cousinen Kinder gezeugt? (c) Welche Halbbrüder und Halbschwestern hat Hermes? Quelle: http: //www. desy. de/gna/interpedia/ greek_myth/gods. FT. html
5 Orientierung Wissensbasis Ziel ist es, mit einem Informatiksystem das Wissen über eine Miniwelt (wie die Welt der griechischen Götter) so zu erfassen, dass Anfragen an die Welt (wie "Wer ist ein Cousin von Hermes? ") von diesem Informatiksystem automatisiert ausgewertet werden können. Wir benutzen die Programmiersprache Prolog zur Wissensmodellierung und zur Formulierung von Anfragen an die Wissensbasis. Anfrage In den folgenden Abschnitten wird zunächst auf die Wissenmodellierung und die Formulierung von Anfragen an die Wissensbasis eingegangen.
6 Modellierungsansatz Eine (Mini-) Welt besteht aus Objekten (Personen, Gegenstände, . . . ), die Eigenschaften haben und in Beziehung zueinander stehen. Zeus (männlich) Hera (weiblich) ist Kind von Ares (männlich) Miniwelt "griechische Götter"
7 Konstanten, Prädikate Objekte werden mit Konstanten (allg. mit Termen) beschrieben, Eigenschaften und Beziehungen mit Hilfe von Prädikaten. Prädikat Zeus (männlich) Hera (weiblich) ist Kind von Ares (männlich) Miniwelt "griechische Götter" % Fakten weiblich(hera). maennlich(zeus). maennlich(ares). kind(ares, hera). kind(ares, zeus). Konstante Prädikat Modellierung der Miniwelt
Fakten 8 Sachverhalte der Miniwelt können direkt mit Hilfe von Fakten beschrieben werden. Zeus (männlich) Hera (weiblich) ist Kind von % Fakten weiblich(hera). maennlich(zeus). maennlich(ares). kind(ares, hera). kind(ares, zeus). Fakten Ares (männlich) Miniwelt "griechische Götter" Modellierung der Miniwelt
Regeln 9 Sachverhalte der Miniwelt können auch indirekt mit Hilfe von Regeln beschrieben werden. Cronus = Rhea | -----------| | | Hestia | Poseidon | Demeter Hades Zeus = Hera Miniwelt % Fakten: maennlich(cronus). maennlich(zeus). . . weiblich(rhea). weiblich(demeter). . kind(hestia, rhea). kind(hades, rhea). . direkte Beschreibung mit Fakten % weitere Fakten: mutter(rhea, hestia). mutter(rhea, hades). . indirekte Beschreibung mit Regeln % Regeln: vater(X, Y) : - kind(Y, X), maennlich(X). mutter(X, Y) : - kind(Y, X), weiblich(X).
Regeln 10 Regeln sind Wenn-Dann-Aussagen. Implikation Und Variable % Regeln: mutter(X, Y) : - kind(Y, X), weiblich(X). vater(X, Y) : - kind(Y, X), maennlich(X). Regelkopf (Folgerung) Regelrumpf (Bedingungen) informelle Beschreibung: X ist Mutter von Y, wenn Y Kind von X ist und X weiblich ist. X ist Vater von Y, wenn Y Kind von X ist und X männlich ist.
Rekursive Regeln 11 Das Prädikat im Regelkopf darf im Regelrumpf vorkommen. % Regeln: vorfahr(X, Y) : - kind(Y, X). vorfahr(X, Y) : - kind(Y, Z), vorfahr(X, Z). Regelkopf (Folgerung) Regelrumpf (Bedingungen) informelle Beschreibung: X ist Vorfahr von Y, wenn Y Kind von Z und X Vorfahr von Z ist.
12 Aufgaben Aufgabe 1 Vervollständige die Regeln. elternteil(X, Y) : sohn(X, Y) : oma(X, Y) : Aufgabe 2 Warum muss man in der folgenden Regel die Bedingung X == Y (für X und Y sind ungleich) mit aufnehmen? bruder(X, Y) : maennlich(X), elternteil(E, Y), X == Y. Aufgabe 3 Entwickle weitere Regeln. onkel(X, Y) : tante(X, Y) : cousin(X, Y) : . . .
13 Logik-Programme Ein Logik-Programm besteht aus einer Wissensbasis und einer Anfrage. % Fakten maennlich(cronus). maennlich(zeus). . . weiblich(rhea). weiblich(demeter). weiblich(hera). weiblich(hestia). kind(hestia, rhea). kind(hades, rhea). . . % Regeln vater(X, Y) : - kind(Y, X), maennlich(X). mutter(X, Y) : - kind(Y, X), weiblich(X). Wissensbasis ? - weiblich(hera). Anfrage
14 SWI-Prolog-Editor Wissensbasis Anfrage
15 PROLOG steht für „Programming in Logic“. Die Programmiersprache PROLOG wurde Anfang der siebziger Jahre (des 20. Jahrhunderts) von Alain Colmerauer und Robert Kowalski konzipiert. SWI-PROLOG ist ein freies und professionelles PROLOG-System, das seit 1987 an der Universität Amsterdam entwickelt und gepflegt wird. Der SWI-PROLOG-Editor ist eine für den Unterricht geeignete Entwicklungsumgebung zur Erstellung von PROLOG-Programmen, die von G. Röhner entwickelt wurde. Installationshinweise: Installieren Sie zunächst SWI-PROLOG. Installieren Sie anschließend den SWI-PROLOG-Editor.
16 Eine Wissensbasis erzeugen Geben Sie die Fakten und Regeln zur Beschreibung der Miniwelt ein oder laden Sie die entsprechende Quelldatei. Bevor Sie Anfragen an die Wissensbasis stellen können, muss diese Wissensbasis erst erzeugt werden. Rufen Sie hierzu das Systemprädikat "consult" auf. Consultieren Wenn der PROLOG-Compiler keine Syntaxfehler gefunden hat, bestätigt er die erfolgreiche Erzeugung der Wissensbasis mit "Yes". Mit consult(<Datei>). werden aus der angegebenen Datei die Fakten und Regeln in die Wissensbasis eingelesen.
17 Eine Anfrage stellen Geben Sie jetzt die Anfrage im unteren Fenster (hinter "? -") ein. Mit der "Return"-Taste erhält man das erste Ergebnis (falls es eines gibt), mit jedem weiteren "Return" ggf. weitere Ergebnisse. Findet der PROLOGInterpreter keine weiteren Ergebnisse, so zeigt er dies mit "No" an. Das trennende Semikolon kann als "oder" gedeutet werden. Anfrage Ergebnisse Anfrage
18 Ja-Nein-Anfragen % Wissensbasis Ist Hera maennlich(cronus). weiblich? maennlich(zeus). maennlich(poseidon). maennlich(hades). Ist Zeus weiblich(rhea). weiblich? weiblich(demeter). weiblich(hera). weiblich(hestia). kind(hestia, rhea). kind(hades, rhea). kind(poseidon, rhea). kind(zeus, rhea). kind(hera, rhea). kind(demeter, rhea). kind(hestia, cronus). kind(hades, cronus). kind(poseidon, cronus). kind(zeus, cronus). kind(hera, cronus). kind(demeter, cronus). mutter(X, Y) : - kind(Y, X), weiblich(X). vater(X, Y) : - kind(Y, X), maennlich(X). ? - weiblich(hera). Yes ? - weiblich(zeus). No
19 Ergänzungsanfragen % Wissensbasis Wer ist Vater maennlich(cronus). von Zeus? maennlich(zeus). maennlich(poseidon). maennlich(hades). weiblich(rhea). weiblich(demeter). Wer ist Kind von weiblich(hera). Rhea? weiblich(hestia). kind(hestia, rhea). kind(hades, rhea). kind(poseidon, rhea). kind(zeus, rhea). kind(hera, rhea). kind(demeter, rhea). kind(hestia, cronus). kind(hades, cronus). kind(poseidon, cronus). kind(zeus, cronus). kind(hera, cronus). kind(demeter, cronus). mutter(X, Y) : - kind(Y, X), weiblich(X). vater(X, Y) : - kind(Y, X), maennlich(X). ? - vater(V, zeus). V = cronus ; No ? - kind(K, rhea). K = hestia ; K = hades ; K = poseidon ; K = zeus ; K = hera ; K = demeter ; No
20 Ergänzungsanfragen % Wissensbasis Wer ist Mutter maennlich(cronus). von wem? maennlich(zeus). maennlich(poseidon). maennlich(hades). weiblich(rhea). weiblich(demeter). weiblich(hera). weiblich(hestia). kind(hestia, rhea). kind(hades, rhea). kind(poseidon, rhea). kind(zeus, rhea). kind(hera, rhea). kind(demeter, rhea). kind(hestia, cronus). kind(hades, cronus). kind(poseidon, cronus). kind(zeus, cronus). kind(hera, cronus). kind(demeter, cronus). mutter(X, Y) : - kind(Y, X), weiblich(X). vater(X, Y) : - kind(Y, X), maennlich(X). ? - mutter(X, Y). X = rhea Y = hestia ; X = rhea Y = hades ; X = rhea Y = poseidon ; X = rhea Y = zeus ; X = rhea Y = hera ; X = rhea Y = demeter ; No
21 Anfragen mit anonymen Variablen % Wissensbasis Wer ist Vater maennlich(cronus). (von einem Kind)? maennlich(zeus). maennlich(poseidon). maennlich(hades). weiblich(rhea). weiblich(demeter). weiblich(hera). weiblich(hestia). kind(hestia, rhea). kind(hades, rhea). kind(poseidon, rhea). kind(zeus, rhea). kind(hera, rhea). kind(demeter, rhea). kind(hestia, cronus). kind(hades, cronus). kind(poseidon, cronus). kind(zeus, cronus). kind(hera, cronus). kind(demeter, cronus). mutter(X, Y) : - kind(Y, X), weiblich(X). vater(X, Y) : - kind(Y, X), maennlich(X). ? - vater(V, _Kind). V = cronus ; V = cronus ; No Anonyme Variablen beginnen mit einem Unterstrich. Anonyme Variablen werden benutzt, wenn man an den Variablenwerten selbst nicht interessiert ist.
22 Zusammengesetzte Anfragen % Wissensbasis Wer ist weiblich maennlich(cronus). und maennlich(zeus). hat einen Vater? maennlich(poseidon). maennlich(hades). weiblich(rhea). weiblich(demeter). weiblich(hera). weiblich(hestia). kind(hestia, rhea). kind(hades, rhea). kind(poseidon, rhea). kind(zeus, rhea). kind(hera, rhea). kind(demeter, rhea). kind(hestia, cronus). kind(hades, cronus). kind(poseidon, cronus). kind(zeus, cronus). kind(hera, cronus). kind(demeter, cronus). mutter(X, Y) : - kind(Y, X), weiblich(X). vater(X, Y) : - kind(Y, X), maennlich(X). ? - weiblich(Tochter), vater(_Vater, Tochter). Tochter = demeter ; Tochter = hera ; Tochter = hestia ; No Eine Anfrage kann auch aus mehreren Teilanfragen bestehen. Diese werden mit einem Komma (zu deuten als logisches Und) abgetrennt.
23 Fazit: Programmieren mit Logik Ein Logik-Programm besteht aus einer Wissensbasis und einer Anfrage. % Fakten maennlich(cronus). maennlich(zeus). . . weiblich(rhea). weiblich(demeter). weiblich(hera). weiblich(hestia). kind(hestia, rhea). kind(hades, rhea). . . % Regeln vater(X, Y) : - kind(Y, X), maennlich(X). mutter(X, Y) : - kind(Y, X), weiblich(X). ? - weiblich(hera). Bei der Programmentwicklung steht logische Modellierung im Vordergrund. Aufgabe des Programmentwicklers ist es, das Wissen und die Anfragen an das Wissen in der Sprache der Logik zu modellieren.
24 Fazit: Programmieren mit Logik Ein Logik-Programm besteht aus einer Wissensbasis und einer Anfrage. % Fakten maennlich(cronus). . . weiblich(rhea). weiblich(demeter). weiblich(hera). weiblich(hestia). kind(hestia, rhea). . . % Regeln vater(X, Y) : - kind(Y, X), maennlich(X). mutter(X, Y) : - kind(Y, X), weiblich(X). ? - weiblich(hera). Yes Zur Auswertung von Logikprogrammen benötigt man eine sog. Inferenzmaschine, die in der Lage ist, aus der Wissensbasis und der Anfrage an die Wissenbasis die Ergebnisse mit Hilfe logischer Schlüsse zu erschließen.
25 Aufgaben Erweitere die oben gezeigte Wissensbasis um folgende Fakten und Regeln. . . maennlich(ares). weiblich(hebe). maennlich(hephaestus). kind(ares, hera). kind(ares, zeus). kind(hebe, hera). kind(hebe, zeus). kind(hephaestus, hera). kind(hephaestus, zeus). vorfahr(X, Y) : - kind(Y, X). vorfahr(X, Y) : - kind(Y, Z), vorfahr(X, Z). Entwickle geeignete Anfragen und teste sie. (a) Wer ist ein männlicher Vorfahr von Hebe? (b) Wer ist Mutter und hat einen weiblichen Vorfahr? (c) Wer ist Vorfahr eines Vaters?
26 Aufgaben Vervollständige die Wissensbasis und kläre mit geeigneten Anfragen die folgenden Verwandschaftsbeziehungen: (a) Wer ist ein Cousin von Zeus? (b) Hat Zeus auch mit Cousinen Kinder gezeugt? (c) Welche Halbbrüder und Halbschwestern hat Hermes? alternativ: Erstelle eine Wissensbasis und geeignete Anfragen zu deiner Familie.
27 Aufgaben Eine Miniwelt "Unterricht" ist wie folgt gegeben: Petra Schmitt (Kürzel: scm) unterrichtet die 6 b in Mathematik. Der Unterricht findet montags in 6. Stunde, dienstags in der 3. Stunde, mittwochs in der 1. Stunde und freitags in der 3. Stunde statt. Wolfgang Degen (Kürzel: deg) unterrichtet die 6 b in Deutsch. Der Unterricht findet dienstags in der 5. und 6. Stunde, donnerstags in der 2. Stunde und freitags in der 5. Stunde statt. Karin Engel (Kürzel: eng) unterrichtet die 6 b in Musik. Der Unterricht findet mittwochs in der 4. Stunde und freitags in der 6. Stunde statt. . Der Unterricht in einer Klasse in einem zweistündigen Fach ist "verteilt", wenn die beiden Stunden nicht am selben Tag stattfinden. Mögliche Anfragen wären hier: Wer unterrichtet die 6 b? Wann findet der Deutschunterricht statt? Hat die 6 b freitags in der 6. Stunde Sport? Ist der Musikunterricht in der 6 b verteilt? . . . (a) Entwickle zunächst eine geeignete Wissensbasis, in der die oben beschriebenen Sachverhalte gelten. Entwickle anschließend Anfragen an die wissensbasis. (b) Erweitere die Wissensbasis in sinnvoller Weise. Formuliere selbst in Worten weitere Anfragen und übersetze sie dann in die Sprache von Prolog.
28 Aufgaben Wir betrachte eine Miniwelt "Sitzplan": Entwickle eine Wissensbasis zu diesem Sitzplan. Folgende Anfragen soll dann gestellt werden: (a) Wer sitzt direkt neben Pia? (b) Welches Mädchen sitzt neben einem Jungen? (c) Wer sitzt in derselben Reihe wie Anja?
29 Teil 2 Auswertung von Anfragen
30 Modus Ponens Zur Herleitung der Sachverhalte der Modellwelt wird die logische Schlussregel modus ponens benutzt. Regeln werden dabei als Wenn-Dann-Aussagen interpretiert. Die in der Regel vorkommenden Variablen sind Platzhalter für alle Objekte der Modellwelt. Alle Menschen sind sterblich. Sokrates ist ein Mensch. Sokrates ist sterblich(X) : - mensch(X). mensch(sokrates). ? - sterblich(X). X = sokrates; No.
Modus Ponens 31 Die Schlussregel modus ponens erlaubt es, aus wahren Aussagen weitere wahre Aussagen herzuleiten. Man schließt dabei folgendermaßen: Wenn die Aussage α → β wahr ist und wenn zusätzlich die Aussage α wahr ist, dann muss auch die Aussage β wahr sein. Platz Mannschaft Spiele Punkte . . . 11 1. FC Kaiserslautern 32 33 . . . α→β α β Wenn Kaiserslautern das Spiel gewinnt, dann kann Kaiserslautern nicht mehr absteigen. Kaiserslautern gewinnt das Spiel. 16 FC St. Pauli 32 29 17 Vf. L Wolfsburg 32 28 18 1. FC Nürnberg 32 26 Kaiserslautern kann nicht mehr absteigen.
Modus Ponens 32 Verallgemeinerung der Schlussregel modus ponens: Hier geht man von einer Wenn-Dann-Aussage mit mehreren, durch ein logisches Und verknüpften Bedingungen aus. Die Schlussregel besagt: Wenn die Wenn-Dann-Aussage wahr ist und alle Bedingungen dieser Aussage wahr sind, dann ist auch die Folgerung dieser Aussage wahr. Platz Mannschaft Spiele Punkte . . . 11 1. FC Kaiserslautern 32 33 . . . 16 FC St. Pauli 32 29 17 Vf. L Wolfsburg 32 28 18 1. FC Nürnberg 32 26 α 1, . . . αn -> β α 1. . . αn β Wenn St. Pauli verliert und Wolfburg unentschieden spielt, dann kann Kaiserslautern nicht mehr absteigen. St. Pauli verliert das vorletzte Spiel. Wolfburg spielt nur uentschieden. Kaiserslautern kann nicht mehr absteigen.
33 Spezialisierung bei Allaussagen machen - wie der Name es sagt - Aussagen für alle (in dem Gegenstandsbereich erlaubten) Objekte. Die folgende Schlussregel besagt, dass man aus einer wahren Allaussage eine wahre Aussage erhält, wenn man sie nur für spezielle Objekte formuliert. Für alle X: mensch(X) -> sterblich(X). mensch(sokrates) -> sterblich(sokrates) Für alle X 1, . . . , Xk: γ (X 1, . . . , Xk) γ(c 1, . . . , ck) Spezialisierung bei Allaussagen {X -> sokrates} {X 1 -> c 1, . . . , Xk -> ck}
Modus Ponens 34 Häufig (wie im Beispiel unten) tritt die Situation ein, dass man zwei Schlussregeln - Regel zur Spezialisierung von Allaussagen und die modus-ponens-Regel - bei einer logischen Herleitung anwenden muss. Zur Vereinfachung von logischen Herleitungen ist es daher sinnvoll, aus den beiden Regeln eine zusätzliche logische Schlussregel zu formulieren. α 1(X 1, . . . , Xk), . . . αn(X 1, . . . , Xk) -> β(X 1, . . . , Xk) α 1(c 1, . . . , ck). . . αn(c 1, . . . , ck) β(c 1, . . . , ck) modus ponens bei Allaussagen Spezialisierung bei Allaussagen Für alle X: mensch(X) -> sterblich(X). Alle Menschen sind sterblich. Sokrates ist ein Mensch. Sokrates ist sterblich. modus ponens mensch(sokrates) -> sterblich(sokrates) mensch(sokrates) sterblich(sokrates) {X -> sokrates}
35 Suche nach logischen Herleitungen es_gibt_fleisch. es_gibt_suppe. es_gibt_pudding es_gibt_eis es_gibt_pudding es_gibt_kartoffeln : : - es_gibt_fleisch, es_gibt_kartoffeln. es_gibt_pizza. es gibt pizza. Wissensbasis ohne Variablen es_gibt_suppe. ? - es_gibt_pudding. es_gibt_kartoffeln : - es_gibt_suppe. ------------------es_gibt_kartoffeln. Anfrage ohne Variablen logische Herleitung es_gibt_pudding : - es_gibt_fleisch, es_gibt_kartoffeln. es_gibt_fleisch. es_gibt_kartoffeln. -----------------------------logische Herleitung es_gibt_pudding. Yes. Ergebnis der Anfrage
36 Suche nach logischen Herleitungen es_gibt_kartoffeln : - es_gibt_suppe. ------------------es_gibt_kartoffeln. logische Herleitung es_gibt_pudding : - es_gibt_fleisch, es_gibt_kartoffeln. es_gibt_fleisch. es_gibt_kartoffeln. -----------------------------logische Herleitung es_gibt_pudding. ? - es_gibt_pudding. benutze: es_gibt_pudding : - es_gibt_fleisch, es_gibt_kartoffeln. ? - es_gibt_fleisch, es_gibt_kartoffeln. benutze: es_gibt_fleisch. ? - es_gibt_kartoffeln. benutze: es_gibt_kartoffeln : - es_gibt_suppe. ? - es_gibt_suppe. benutze: es_gibt_suppe. ? Yes Rückwärtsherleitung
37 Suche nach logischen Herleitungen weiblich(hera). weiblich(hebe). maennlich(zeus). maennlich(ares). maennlich(hephaestus). kind(ares, hera). kind(hebe, hera). kind(hephaestus, hera). kind(ares, zeus). kind(hebe, zeus). kind(hephaestus, zeus). vater(X, Y) : - kind(Y, X), maennlich(X). mutter(X, Y) : = kind(Y, X), weiblich(X). ? - vater(V, hebe). Wissensbasis mit Variablen Anfrage mit Variablen vater(X, Y) : - kind(Y, X), maennlich(X). logische Herleitung kind(hebe, zeus). maennlich(zeus). -------------------- {X -> zeus; Y -> hebe} vater(zeus, hebe). V = zeus Ergebnis der Anfrage
38 Suche nach logischen Herleitungen vater(X, Y) : - kind(Y, X), maennlich(X). logische Herleitung kind(hebe, zeus). maennlich(zeus). -------------------- {X -> zeus; Y -> hebe} vater(zeus, hebe). ? - vater(V, hebe). benutze: vater(X, Y) : - kind(Y, X), maennlich(X). {X -> V; Y -> hebe} ? - kind(hebe, V), maennlich(V). benutze: kind(hebe, zeus). {V -> zeus} ? - maennlich(zeus). benutze: maennlich(zeus). ? V = zeus Rückwärtsherleitung
39 Herleitungen ohne Erfolg es_gibt_fleisch. es_gibt_suppe. es_gibt_pudding es_gibt_eis es_gibt_pudding es_gibt_kartoffeln ? - es_gibt_eis. : : - es_gibt_fleisch, es_gibt_kartoffeln. es_gibt_pizza. es gibt pizza. Wissensbasis ohne Variablen es_gibt_suppe. Anfrage ohne Variablen ? - es_gibt_eis. benutze: es_gibt_eis : - es gibt pizza. ? - es_gibt_pizza. keine Fortsetzung der Rückwärtsherleitung möglich! No Rückwärtsherleitung
40 Herleitungen ohne Erfolg weiblich(hera). weiblich(hebe). maennlich(zeus). maennlich(ares). maennlich(hephaestus). kind(ares, hera). kind(hebe, hera). kind(hephaestus, hera). kind(ares, zeus). kind(hebe, zeus). kind(hephaestus, zeus). vater(X, Y) : - kind(Y, X), maennlich(X). mutter(X, Y) : = kind(Y, X), weiblich(X). ? - vater(V, hebe). Wissensbasis mit Variablen Anfrage mit Variablen ? - vater(V, hebe). benutze: vater(X, Y) : - kind(Y, X), maennlich(X). {X -> V; Y -> hebe} Rückwärtsherleitung ? - kind(hebe, V), maennlich(V). benutze: kind(hebe, zeus). {V -> zeus} ? - maennlich(zeus). keine Fortsetzung der Rückwärtsherleitung möglich! No
41 Zwischenfazit: Auswertung v. Anfragen an eine Wissensbasis lassen sich über logische Herleitungen mit der verallgemeinerten modus-ponens-Schlussregel (und der Regel zur Spezialisierung von Allaussagen) auswerten. Eine Ja-Nein-Anfrage liefert das Ergebnis Yes genau dann, wenn es eine Herleitung zu den Fakten der Anfrage aus der Wissensbasis gibt. Eine Variablenbelegung ist ein Ergebnis zu einer Anfrage mit Variablen genau dann, wenn es eine Herleitung aus der Wissensbasis zu den - mit der Variablenbelegung konkretisierten Fakten der Anfrage gibt. Wenn keine erfolgreiche Herleitung der (ggf. konkretisierten) Fakten der Anfrage möglich ist, wird das Ergebnis No geliefert (negation by failure!). ? - vater(V, hebe). benutze: vater(X, Y) : - kind(Y, X), maennlich(X). {X -> V; Y -> hebe} ? - kind(hebe, V), maennlich(V). benutze: kind(hebe, zeus). {V -> zeus} ? - maennlich(zeus). benutze: maennlich(zeus). ? V = zeus
Aufgaben 42 kind(hera, kind(hebe, vorfahr(X, rhea). hera). Y) : - kind(Y, X). Y) : - kind(Y, Z), vorfahr(X, Z). ? - vorfahr(V, hebe). Welche Ergebnisse lassen sich hier mit logischen Herleitungen erzielen? Verwende zunächst Vorwärtsherleitungen. Verwende anschließend auch Rückwärtsherleitungen.
43 Automatisierung d. logischen Schließens es_gibt_fleisch. es_gibt_suppe. es_gibt_pudding es_gibt_eis es_gibt_kartoffeln : : - es gibt pizza. es_gibt_fleisch, es_gibt_kartoffeln. es_gibt_pizza. es_gibt_suppe. ? - es_gibt_pudding. es_gibt_kartoffeln : - es_gibt_suppe. ------------------es_gibt_kartoffeln. Herleitung mit nichtdeterministische Auswahl der Regeln logische Herleitung es_gibt_pudding : - es_gibt_fleisch, es_gibt_kartoffeln. es_gibt_fleisch. es_gibt_kartoffeln. -----------------------------logische Herleitung es_gibt_pudding. Yes.
44 Automatisierung d. logischen Schließens es_gibt_fleisch. es_gibt_suppe. es_gibt_pudding es_gibt_eis es_gibt_kartoffeln : : - ? - es_gibt_pudding. es gibt pizza. es_gibt_fleisch, es_gibt_kartoffeln. es_gibt_pizza. es_gibt_suppe. Herleitung mit Auswahl der Regeln nach einer vorgegebenen Reihenfolge (von oben nach unten) ? - es_gibt_pudding. benutze: es_gibt_pudding : - es gibt pizza. Sackgasse ? - es_gibt_pizza. keine Fortsetzung der Rückwärtsherleitung möglich! Backtracking benutze: es_gibt_pudding : - es_gibt_fleisch, es_gibt_kartoffeln. ? - es_gibt_fleisch, es_gibt_kartoffeln. benutze: es_gibt_fleisch. ? - es_gibt_kartoffeln. benutze: es_gibt_kartoffeln : - es_gibt_suppe. ? - es_gibt_suppe. benutze: es_gibt_suppe. ? Yes
Logische Herleitbarkeit 45 kind(hera, kind(hebe, vorfahr(X, rhea). hera). Y) : - kind(Y, X). Y) : - kind(Y, Z), vorfahr(X, Z). kind(hera, kind(hebe, vorfahr(X, rhea). hera). Y) : - vorfahr(X, Z), kind(Y, Z). Y) : - kind(Y, X). ? - vorfahr(V, hebe). vorfahr(X, Y) : - kind(Y, X). kind(hebe, hera). ---------------------------vorfahr(hera, hebe). {X -> hera; Y -> hebe} V = hera vorfahr(X, Y) : - kind(Y, X). kind(hera, rhea). ---------------------------vorfahr(rhea, hera). {X -> hebe; Y -> hera} {X -> hera; Y -> hebe} {X -> hebe; Y -> hera} vorfahr(X, Y) : - kind(Y, Z), vorfahr(X, Z). kind(hebe, hera). vorfahr(rhea, hera). {X -> rhea; --------------Y -> hebe; vorfahr(rhea, hebe). Z -> hera} vorfahr(X, Y) : - kind(Y, Z), vorfahr(X, Z). vorfahr(rhea, hera). kind(hebe, hera). {X -> rhea; --------------Y -> hebe; vorfahr(rhea, hebe). Z -> hera} V = rhea hängt nicht von der Reihenfolge der Regeln, Bedingungen ab
46 Herleitbarkeit bzgl. Abarbeitungsreihenf. kind(hera, kind(hebe, vorfahr(X, rhea). hera). Y) : - kind(Y, X). Y) : - kind(Y, Z), vorfahr(X, Z). hängt von der Reihenfolge der Regeln, Bedingungen ab ? - vorfahr(V, hebe). benutze: vorfahr(X, Y) : - kind(Y, X). {X -> V; Y -> hebe} ? - kind(hebe, V). benutze: kind(hebe, hera). {V -> hera} ? V = hera benutze: vorfahr(X, Y) : - kind(Y, Z), vorfahr(X, Z). {X -> V; Y -> hebe} ? - kind(hebe, Z), vorfahr(V, Z). benutze: kind(hebe, hera). {Z -> hera} ? - vorfahr(V, hera). benutze vorfahr(X, Y) : - kind(Y, X). {X -> V; Y -> hera} ? - kind(hera, V). benutze kind(hera, rhea). {V -> rhea} ? V = rhea benutze vorfahr(X, Y) : - kind(Y, Z), vorfahr(X, Z). {X -> V; Y -> hera} ? - kind(hera, Z), vorfahr(V, Z). benutze kind(hera, rhea). {Z -> rhea} ? - vorfahr(V, rhea). benutze vorfahr(X, Y) : - kind(Y, X). {X -> V; Y -> rhea} ? - kind(rhea, V). keine Fortsetzung der Rückwärtsherleitung möglich! benutze vorfahr(X, Y) : - kind(Y, Z), vorfahr(X, Z). {X -> V; Y -> rhea} ? - kind(rhea, Z), vorfahr(V, Z). keine Fortsetzung der Rückwärtsherleitung möglich!
47 Herleitbarkeit bzgl. Abarbeitungsreihenf. kind(hera, kind(hebe, vorfahr(X, rhea). hera). Y) : - vorfahr(X, Z), kind(Y, Z). Y) : - kind(Y, X). hängt von der Reihenfolge der Regeln, Bedingungen ab ? - vorfahr(V, hebe). benutze: vorfahr(X, Y) : - vorfahr(X, Z), kind(Y, Z). {X -> V; Y -> hebe} ? - vorfahr(V, Z), kind(hebe, Z). benutze: vorfahr(X, Y) : - vorfahr(X, Z 1), kind(Y, Z 1). {X -> V; Y -> Z} ? - vorfahr(V, Z 1), kind(Z, Z 1), kind(hebe, Z). benutze: vorfahr(X, Y) : - vorfahr(X, Z 2), kind(Y, Z 2). {X -> V; Y -> Z 1} ? - vorfahr(V, Z 2), kind(Z 1, Z 2), kind(Z, Z 1), kind(hebe, Z). . endlose Regelanwendung Die Logik-Programme sind logisch äquivalent. Aus beiden Programmen lassen sich dieselben logischen Herleitungen erzeugen. Die Herleitung bzgl. einer Abarbeitungsreihenfolge liefert jedoch unterschiedliche Berechnungsergebnisse. Diese werden durch die Algorithmen zur automatisierten Erzeugung von logischen Herleitungen festgelegt. Die Reihenfolge der Regeln und der beteiligten Bedingungen spielen hierbei eine entscheidende Rolle.
48 Fazit: Auswertung von Anfragen Ergebnisse zu Anfragen an eine Wissensbasis lassen sich durch systematisches Erzeugen von logischen Herleitungen bestimmen. Im Zentrum steht dabei eine logische Schlussregel. Mit Hilfe der verallgemeinerten modusponens-Schlussregel (und der Schlussregel zur Spezialisierung von Allaussagen) werden die logischen Herleitungen erzeugt. Zur Automatisierung der Anwendung von Schlussregeln werden Vereinbarungen zur Auswertungsreihenfolge getroffen. Zur Anwendung von Regeln mit Variablen benötigt man zusätzlich einen Algorithmus zur Erzeugung von Variablenbindungen. Wir haben Variablenbindungen in den bisher gezeigten Beispielen jeweils vorgegeben und uns um die systematische Erzeugung und Verwaltung dieser Bindungen nicht gekümmert. Schließlich benötigt man ein Verfahren zur Bearbeitung von Herleitungssackgassen. Man benutzt hier Backtracking, um systematisch an geeignete Verzweigungspunkte von Herleitungen zurückzugehen. Ein Softwaresystem, das alle diese Verfahren zur automatisierten Erzeugung von logischen herleitungen umsetzt, nennt man auch Inferenzmaschine.
Experimente mit Prolog 49 Wissensbasis: es_gibt_fleisch. es_gibt_suppe. es_gibt_pudding es_gibt_eis es_gibt_pudding es_gibt_kartoffeln : : - es_gibt_fleisch, es_gibt_kartoffeln. es_gibt_pizza. es gibt pizza. es_gibt_suppe. Prolog stellt einen sog. Trace-Modus bereit, bei dem die Zwischenschritte bei der Auswertung einer Anfrage mitprotokolliert werden. ? - trace. Yes [trace] Call: Exit: ? - es_gibt_pudding. (6) es_gibt_pudding ? creep (7) es_gibt_fleisch ? creep (7) es_gibt_kartoffeln ? creep (8) es_gibt_suppe ? creep (7) es_gibt_kartoffeln ? creep (6) es_gibt_pudding ? creep Yes Aufgabe: Gib für alle Call-Aufrufe an, welches Faktum / welche Regel angewandt wird.
Experimente mit Prolog 50 Wissensbasis: kind(hera, kind(hebe, vorfahr(X, rhea). hera). Y) : - kind(Y, X). Y) : - kind(Y, Z), vorfahr(X, Z). [trace] Call: Exit: ? - vorfahr(V, hebe). (7) vorfahr(_G 286, hebe) ? creep (8) kind(hebe, _G 286) ? creep (8) kind(hebe, hera) ? creep (7) vorfahr(hera, hebe) ? creep V = hera Fail: Redo: Call: Exit: Exit: ; (8) (7) (8) (8) (9) (8) (7) . . . kind(hebe, _G 286) ? creep vorfahr(_G 286, hebe) ? creep kind(hebe, _G 341) ? creep kind(hebe, hera) ? creep vorfahr(_G 286, hera) ? creep kind(hera, _G 286) ? creep kind(hera, rhea) ? creep vorfahr(rhea, hera) ? creep vorfahr(rhea, hebe) ? creep V = rhea Fail: Redo: Call: Exit: Call: Fail: Redo: Call: Fail: Fail: ; (9) kind(hera, _G 286) ? creep (8) vorfahr(_G 286, hera) ? creep (9) kind(hera, _G 341) ? creep (9) kind(hera, rhea) ? creep (9) vorfahr(_G 286, rhea) ? creep (10) kind(rhea, _G 286) ? creep (9) vorfahr(_G 286, rhea) ? creep (10) kind(rhea, _G 341) ? creep (9) vorfahr(_G 286, rhea) ? creep (9) kind(hera, _G 341) ? creep (8) vorfahr(_G 286, hera) ? creep (8) kind(hebe, _G 341) ? creep (7) vorfahr(_G 286, hebe) ? creep No Aufgabe: Vergleiche das von Prolog erzeugte Herleitungsprotokoll mit dem Herleitungsprotokoll auf Folie 46.
Aufgabe 51 Gegeben ist das folgende Logikprogramm. kind(hera, kind(hebe, vorfahr(X, rhea). hera). Y) : - kind(Y, Z), vorfahr(X, Z). Y) : - kind(Y, X). ? - vorfahr(V, hebe). Welches Ergebnis liefert die Prolog-Inferenzmaschine? Überprüfe deine Vermutung.
Aufgabe 52 Gegeben ist das folgende Logikprogramm. kind(hera, kind(hebe, vorfahr(X, rhea). hera). Y) : - kind(Y, X). Y) : - vorfahr(X, Z), kind(Y, Z). ? - vorfahr(V, hebe). Welches Ergebnis liefert die Prolog-Inferenzmaschine? Überprüfe deine Vermutung.
53 Teil 3 Verwaltung von Daten
54 Konstanten % Stadt Konstante stadt(trier). stadt(mainz). stadt(koblenz). stadt(berlin). Konstante stadt('Köln'). stadt('München'). % Land land('D'). land(deutschland). land('A'). land(oesterreich). % Fluss fluss(mosel). fluss(rhein). fluss(spree). Konstante % Eigenschaften flaeche(deutschland, 357111. 91). flaeche(oesterreich, 83879). % Beziehungen liegt_am_fluss(trier, mosel). liegt_am_fluss(mainz, rhein). liegt_am_fluss('Köln', rhein). Die einfachste Möglichkeit, Objekte einer Miniwelt darzustellen, besteht darin, passende Bezeichner für die Objekte einzuführen. Solche Bezeichner werden dann als Konstanten(symbole) behandelt. Konstanten sind demnach Symbole, die stellvertretend für Objekte einer Miniwelt stehen und benutzt werden. Konstanten - Zeichenketten, die mit einem Kleinbuchstaben beginnen und nur aus Klein- oder Großbuchstaben oder Ziffern oder dem Unterstreichungszeichen bestehen - Zeichenketten, die in Hochkommata eingeschlossen sind - Zahlen
55 Terme % Einwohnerzahl eines Landes einwohnerzahl(deutschland, 8. 403, datum(1, 10, 2010)). einwohnerzahl(oesterreich, 81. 751, datum(30, 6, 2010)). % Nationalfeiertag eines Landes zusammennationalfeiertag(deutschland, datum(3, 10, Jahr)). gesetzter Term nationalfeiertag(oesterreich, datum(26, 10, Jahr)). % Geografische Lage einer Stadt lage(berlin, nord(52), ost(13)). lage('Köln', nord(51), ost(7)). % Städte am Fluss staedte_am_fluss(mosel, [metz, trier, bernkastel, cochem, koblenz]). staedte_am_fluss(saar, ['Saarbrücken', saarburg, konz]). staedte_am_fluss(rhein, [basel, mannheim, mainz, koblenz, 'Köln', 'Düsseldorf']). staedte_am_fluss(donau, [ulm, ingolstadt, regensburg, wien, budapest]). Terme werden mit Hilfe von Konstanten, Variablen und Funktionssymbolen aufgebaut. Die Menge der Terme lässt sich so charakterisieren: Alle Konstanten und Variablen sind Terme. Wenn f ein n-stelliges Funktionssymbol ist und t 1. . . tn Terme sind, dann ist auch f(t 1. . . tn) ein Term.
56 Listen ? - display([]). [] Yes ? - display([a]). . (a, []) Yes ? - display([a, b]). . (a, . (b, [])) Liste als zusammengesetzter Term Yes ? - display([a, [1, 2], [d]]). . (a, . (. (1, . (2, [])), . ([], . (. (d, [])))) Yes Listen werden in Prolog ebenfalls als Terme behandelt. Zur Darstestellung von Listen benutzt man normalerweise die Notation mit eckigen Klammern. So sind [], [a, b] und [a, [1, 2], [d]] Beispiele für Listen. Die Punktnotation zeigt, dass Listen letztlich zusammengesetzte Einheiten sind, die den Punkt. als Funktionssymbol zum Aufbau der Terme benutzen.
57 Aufgabe Welche Ergebnisse liefert Prolog? Stelle Vermutungen auf und überprüfe sie anschließend. (a) Datum - Version 1 geburtstag(datum(13, 6, 2011)). ? - geburtstag(X). ? - geburtstag(datum(13, 6, Jahr)). (b) Datum - Version 2 geburtstag(date(y(2011), m(june), d(13))). ? - geburtstag(X). ? - geburtstag(date(y(2011), m(june), d(Tag))). ? - geburtstag(date(Y, M, T)).
58 Aufgabe Ein Dreieck besteht aus den Punkten A(2|3), B(4|7) und C(3|5). Gib verschiedene Möglichkeiten an, wie man dieses Wissen darstellen kann. Dabei soll auch eine Version mit komplexeren Termen vorkommen.
59 Eine Bootstour über Flüsse % Fakten zu Städten an Flüssen staedte_am_fluss(mosel, [metz, konz, trier, bernkastel, cochem, koblenz]). staedte_am_fluss(saar, ['Saarbrücken', saarburg, konz]). staedte_am_fluss(rhein, [basel, mannheim, mainz, koblenz, 'Köln', 'Düsseldorf']). staedte_am_fluss(donau, [ulm, ingolstadt, regensburg, wien, budapest]). staedte_am_fluss(main, [schweinfurt, 'Würzburg', offenbach, frankfurt, mainz]). Aufgabe: Erstelle zunächst eine vereinfachte Skizze, in der die Flüsse und Städte strukturgetreu abgebildet sind. Es geht dabei insbesondere um die Frage "Welcher Fluss mündet bei welcher Stadt in welchen anderen Fluss? "
60 Eine Bootstour über Flüsse % Fakten zu Städten an Flüssen staedte_am_fluss(mosel, [metz, konz, trier, bernkastel, cochem, koblenz]). staedte_am_fluss(saar, ['Saarbrücken', saarburg, konz]). staedte_am_fluss(rhein, [basel, mannheim, mainz, koblenz, 'Köln', 'Düsseldorf']). staedte_am_fluss(donau, [ulm, ingolstadt, regensburg, wien, budapest]). staedte_am_fluss(main, [schweinfurt, 'Würzburg', offenbach, frankfurt, mainz]). Aufgabe: Du sollst eine Bootstour von Saarbrücken nach Köln / Würzburg / Regensburg planen. (a) Erstelle selbst (ohne Prolog) Listen mit allen Stationen der Bootstouren. (b) Welche Listenoperationen sollte man ausführen können, um das "Bootstourproblem" automatisiert lösen zu können? Ergänze hierzu die folgende Aufzählung. - überprüfen, ob ein Element (Stadt) in einer Liste vorkommt -. . .
61 Kopf-Rest-Methode Eine Liste ist entweder eine leere Liste, oder besteht aus einem ersten Element (dem sogenannten Kopfelement) und einer Restliste. Die leere Liste wird in Prolog mit leeren eckigen Klammern [] dargestellt. Eine Aufteilung in ein Kopfelement K und eine Restliste R kann in Prolog in der Form [K|R] dargestellt werden. Bei der Festlegung von Prädikaten verwendet man häufig die Fälle "leere Liste" - dargestellt durch [] - und "nicht-leere Liste" - dargestellt durch [K|R]. leer([]). nichtleer([K|R]). ? - leer([]). Yes ? - leer([a, b, c]). No ? - nichtleer([a, b, c]). Yes
62 Kopf-Rest-Methode Bei der Auswertung von Anfragen müssen u. a. Variablenbindungen erzeugt werden. Wie geht die (Prolog-) Inferenzmaschine vor, wenn das Listenmuster [K|R] in der Wissensbasis benutzt wird? Die folgenden Anfragen zeigen einige Ergebnisse. ? - [K|R] = [a, b, c]. K = a R = [b, c] ; No ? - [K|R] = [5]. K = 5 R = [] ; No ? - [K|R] = [[1], [3]]. K = [1] R = [[3]] ; No ? - [E 1, E 2 | R] = [a, b, c]. E 1 = a E 2 = b R = [c] ; No ? - [E 1, E 2 | R] = [a]. No Aufgabe: Analysiere die gezeigten Ergebnisse und stelle Vermutungen auf, wie die folgenden Anfragen ausgewertet werden. Überprüfe anschließend deine Vermutungen. ? - [E|L] = [1, 2]. ? - [K|R] = [[], [1], [2, 3]]. ? - [E 1, E 2, E 3 | R] = [1, 2, 3]. ? - [E 1, E 2, E 3 | R] = [1, [2, 3]].
63 Rekursive Verarbeitung von Listen Beispiel: Zusammenfügen von Listen ? - zusammenfuegen([a, b], [a, c, d], L). L = [a, b, a, c, d] ; No ? - zusammenfuegen([], [a, c, d], L). L = [a, c, d] ; No ? - zusammenfuegen(A, B, [a, b, c]). A = [] B = [a, b, c] ; A = [a] B = [b, c] ; A = [a, b] B = [c] ; A = [a, b, c] B = [] ; No gewünschtes Verhalten
64 Rekursive Verarbeitung von Listen Beispiel: Zusammenfügen von Listen Regel 1: [] und L zusammengefügt ergibt l. Regel 2: [K|R] und L zusammengefügt ergibt [K|N], wenn R und L zusammengefügt die Liste N ergibt. Idee: Problemreduktion zusammenfuegen([], L, L). zusammenfuegen([K|R], L, [K|N]) : - zusammenfuegen(R, L, N). Umsetzung in Prolog
65 Rekursive Verarbeitung von Listen Beispiel: Elementbeziehung ? - element(b, [a, b, c, d]). Yes ? - element(e, [a, b, c, d]). No ? - element(E, [a, b, c, d]). E = a ; E = b ; E = c ; E = d ; No gewünschtes Verhalten
66 Rekursive Verarbeitung von Listen Beispiel: Zusammenfügen von Listen Idee: Problemreduktion Regel 1: E ist Element von L, wenn L aus dem Kopfelement K und der Restliste R besteht und wenn E gleich dem Kopfelement K ist. Regel 2: E ist Element von L, wenn L aus dem Kopfelement K und der Restliste R besteht und wenn E ungleich dem Kopfelement K ist und wenn E Element der Restliste R ist. element(E, L) : - L = [K|R], E = K. element(E, L) : - L = [K|R], E == K, element(E, R). element(E, [E|R]). element(E, [K|R]) : - element(E, R). Umsetzung in Prolog
67 Aufgabe Beispiel: Letztes Element Regel 1: Idee: Problemreduktion Regel 2: letztes_element([E], ). letztes_element([K|R], E) : - . Umsetzung in Prolog
68 Beispiel: Mit letztem Element Aufgabe Idee: Problemreduktion Regel 1: Ein Liste bestehend aus der leeren Liste [] und dem letzten Element E ergibt die Liste [E]. Regel 2: Eine Liste bestend aus [K|R] und dem letztem Element E ergibt eine Liste [K|L], wenn die Liste bestehend aus R und dem letzten Element K die Liste L ergibt. Umsetzung in Prolog
69 Rekursive Verarbeitung von Listen Beispiel: Umkehren Idee: Problemreduktion Regel 1: [] umgekehren ergibt []. Regel 2: [K|R] umgekehren ergibt die Liste L, wenn R umgekehren die Liste U ergibt und wenn U mit zusätzlichem letzten Element K die Liste L ergibt. mit_letztem_element([], E, [E]). mit_letztem_element([K|R], E, [K|L]) : - mit_letztem_element(R, E, L). umkehren([], []). umkehren([K|R], L) : - umkehren(R, U), mit_letztem_element(U, K, L). Umsetzung in Prolog
70 Rekursive Verarbeitung von Listen Beispiel: Umkehren ? - umkehren([a, b, c], U) ? - umkehren_mit_akkumulator([a, b, c], [], U) ? - umkehren_mit_akkumulator([b, c], [a], U) ? - umkehren_mit_akkumulator([c], [b, a], U) ? - umkehren_mit_akkumulator([], [c, b, a], U) U = [c, b, a] Idee: Verwendung einer Sammelliste umkehren(L, U) : umkehren_mit_akkumulator(L, [], U). umkehren_mit_akkumulator([], A, A). umkehren_mit_akkumulator([K|R], A, U) : umkehren_mit_akkumulator(R, [K|A], U). Umsetzung in Prolog
71 Komplexere Aufgabe Beispiel: Teilliste ? - teilliste_bis_element([3, 4, 5, 6, 7], 4, L). L = [3, 4] ; No ? - teilliste_bis_element([3, 4, 5, 6, 7], 8, L). L = [] ; No ? - teilliste_bis_element([3, 4, 5, 6, 5, 7], 5, L). L = [3, 4, 5] ; No gewünschtes Verhalten
72 Komplexere Aufgabe Beispiel: Teilliste ? - teilliste_von_element_bis_element([3, 4, 5, 6, 7, 8], 4, 6, L). L = [4, 5, 6] ; No ? - teilliste_von_element_bis_element([3, 4, 5, 6, 7, 8], 4, 9, L). L = [] ; No ? - teilliste_von_element_bis_element([3, 4, 5, 6, 7, 8], 2, 5, L). L = [] ; No ? - teilliste_von_element_bis_element([3, 4, 5, 6, 7, 8], 5, 5, L). L = [5] ; No ? - teilliste_von_element_bis_element([3, 4, 5, 6, 7, 8], 5, 3, L). L = [] ; No gewünschtes Verhalten
73 Bootstourproblem Es ist gar nicht so einfach, Bootstouren auf Flüssen zu ermitteln. Man muss eine Reihe von Fällen und Schwierigkeiten beachten, z. B. : Liegen Start und Ziel am selben Fluss, oder gelangt man nur über verschiedene Flüsse ans Ziel? Erfolgt die Bootsfahrt flussabwärts oder flussaufwärts oder erst flussabwärts und dann flussaufwärts? Die folgenden Prädikate können dich schrittweise zur Lösung des Bootstourproblems führen. liegen_am_selben_flussabwaerts(Stadt. A, Stadt. B) liegen_flussaufwaerts(Stadt. A, Stadt. B) liegen_flussabwaerts_flussaufwaerts(Stadt. A, Stadt. B, Stadt. C) fahrt_abwaerts_ueber_denselben_fluss(Stadt. A, Stadt. B, Liste. Staedte. AB) fahrt_abwaerts(Stadt. A, Stadt. B, Liste. Staedte. AB) fahrt_aufwaerts(Stadt. A, Stadt. B, Liste. Staedte. AB) fahrt(Stadt. A, Stadt. B, Liste. Staedte. AB)
74 Bootstourproblem Weitere Hinweise findest du auf den Seiten von inf-schule (1. 23. 3. 2. 6).
75 Zahlen Die Lage eines Punktes auf der Erde lässt sich mit Hilfe seiner geografischen Koordinaten (kurz: Geokoordinaten) eindeutig bestimmen. Man nutzt dabei ein Koordinatensystem, das durch die Einteilung der Erde in Breiten- und Längengrade gebildet wird. % Städte mit Geokoordinaten - Version 1 lage(berlin, nord(52, 30), ost(13, 0)). lage('Köln', nord(50, 56), ost(6, 57)). lage(mainz, nord(50, 0), ost(8, 16)). lage(frankfurt, nord(50, 6), ost(8, 41)). lage('München', nord(48, 8), ost(11, 34)). lage(hamburg, nord(53, 30), ost(10, 0)). % Städte mit Geokoordinaten - Version 2 lage(berlin, nord(52. 5), ost(13. 0)). lage('Köln', nord(50. 93), ost(6. 95)). lage(mainz, nord(50), ost(8. 27)). lage(frankfurt, nord(50. 1), ost(8. 68)). lage('München', nord(48. 13), ost(11. 57)). lage(hamburg, nord(53. 5), ost(10. 0)). Zahlen vom Datentyp integer ? - integer(3). Yes ? - float(3). No ? - float(3. 0). Yes Zahlen vom Datentyp float
76 Vergleiche von Zahlen Liegt Köln südlich von Frankfurt? Mit den Geokoordinaten der beiden Städte lässt sich diese Frage direkt beantworten. Vergeich Bedeutung X<Y X ist kleiner als Y X>Y X ist größer als Y X =< Y X ist kleiner oder gleich Y % Städte mit Geokoordinaten - Version 2 X >= Y lage(berlin, nord(52. 5), ost(13. 0)). lage('Köln', nord(50. 93), ost(6. 95)). X =: = Y lage(mainz, nord(50), ost(8. 27)). lage(frankfurt, nord(50. 1), ost(8. 68)). lage('München', nord(48. 13), ost(11. 57)). X == Y lage(hamburg, nord(53. 5), ost(10. 0)). liegt_suedlich_von(Stadt. A, Stadt. B) : lage(Stadt. A, nord(NA), ost(_OA)), lage(Stadt. B, nord(NB), ost(_OB)), NA < NB. ? - liegt_suedlich_von('Köln', frankfurt). No X ist größer oder gleich Y X und Y sind numerisch gleich X und Y sind numerisch ungleich Vergleich von Zahlen
77 Berechnungen mit Zahlen Liegt Köln südlich von Frankfurt? Mit den Geokoordinaten der beiden Städte lässt sich diese Frage direkt beantworten. Rechenoperator Bedeutung X+Y Addition X-Y Subtraktion X*Y Multiplikation % Städte mit Geokoordinaten - Version 2 X/Y lage(berlin, nord(52. 5), ost(13. 0)). lage('Köln', nord(50. 93), ost(6. 95)). X // Y lage(mainz, nord(50), ost(8. 27)). lage(frankfurt, nord(50. 1), ost(8. 68)). lage('München', nord(48. 13), ost(11. 57)). X mod Y lage(hamburg, nord(53. 5), ost(10. 0)). abstand(Stadt. A, Stadt. B, A) : lage(Stadt. A, nord(NA), ost(OA)), lage(Stadt. B, nord(NB), ost(OB)), A is sqrt(((NA-NB)*111)^2 + ((OA-OB)*71)^2). ? - abstand(mainz, 'Köln', A). A = 139. 427 ; No Float-Division Integer-Division Rest bei der Integer-Division Näherungsweise Berechnung des Abstands
78 is-Operator Beim =-Operator werden die Variablen so belegt, dass Termgleichheit entsteht. Der is-Operator führt dagegen zu einer numerischen Auswertung von Rechentermen. % Summenberechnung summe 1(X, Y, Z) : - Z = X + Y. summe 2(X, Y, Z) : - Z is X + Y. ? - summe 1(2, 3, S). S = 2+3 ; No ? - summe 2(2, 3, S). S = 5 ; No
79 Ausgabe von Daten Das vordefinierten Prädikat write/1 dient dazu, einen Term auf dem Bildschirm auszugeben. Das vordefinierte Prädikat nl/0 dient dazu, einen Zeilenvorschub auszulösen. write_liste([]). write_liste([K|R]) : - write(K), nl, write_liste(R). ? - write_liste([diese, liste, enthaelt, eine, ganze, reihe, elemente]). diese liste enthaelt eine ganze reihe elemente Yes
80 Aufgaben Mit Hilfe des abstand-Prädikats soll ein Prädikat laenge_der_route/2 festgelegt werden, mit dem man die Länge einer Route über mehrere Städte der Wissensbasis bestimmen kann. ? - laenge_der_route([frankfurt, mainz, 'Köln', hamburg], L). L = 528. 733 ; No
81 Teil 4 Deklarative Programmierung
82 Ein Graphenproblem "Die Leute vom Planeten Chator schreiben gern Schlechtes übereinander. Wer vielen über andere Schlechtes schreibt, gilt als besonders charmant. Aber natürlich nur, wenn die Kompromittierten nichts davon erfahren. Chatonen schreiben nur an Leute, die ihnen sympathisch sind. Doch die können den Tratsch weitertragen, und eventuell genau an den Falschen. Ein Chatone muss also gut aufpassen, dass er keinen Charmefehler macht. Dieses Missgeschick passierte unlängst Ator, als er Btor Schlechtes über Dtor schrieb. Zu dumm: Dtor ist dem Ctor sympathisch, der wiederum Btor sympathisch ist. Und so landete der Tratsch bei Dtor, der über Ator verständlicherweise sehr verärgert war. Dies hätte Ator mit ein wenig Übersicht vermeiden können, denn schließlich wissen alle Chatonen voneinander, wer wem sympathisch ist. " (Quelle: Bundeswettbewerb Informatik 2004/2005 - 1. Runde) (a) Stelle die Sympathiebeziehungen der Chatonen mit einem gerichteten Graphen dar. (b) Welches Problem muss hier gelöst werden. Beschreibe es mit Hilfe der Graphenterminologie.
83 Graphen Ein Graph besteht aus einer Menge von Knoten und einer Menge von Kanten (die jeweils zwei Knoten miteinander verbinden). gerichteter, unbewerteter Graph
84 Das Wegsucheproblem: Gibt es einen Weg von einem vorgegebnenen Startknoten zu einem vorgegebenen Zielknoten? Spezielle Probleme: (a) Darf A etwas Schlechtes über D an B schreiben? Gibt es einen Weg (längs der Kanten des Graphen) vom Startknoten B zum Zielknoten D? (b) Über wen H etwas Schlechtes an D schreiben? Zu welchen Zielknoten gibt es einen Weg vom Startknoten D? . . .
85 Lösung des Wegsucheproblems ALGORITHMUS: Wegsuche in gerichteten Graphen Eingabe: gerichteter Graph, Startknoten, Zielknoten Markiere den Startknoten. Füge den Startknoten in eine leere Liste ein. Solange die Liste nicht leer ist und den Zielknoten nicht enthält: Wähle einen Knoten aus der Liste aus. Für alle Nachbarknoten des gewählten Knotens: Falls der Nachbarknoten noch nicht markiert ist: Markiere ihn, vermerke als Herkunft den gewählten Knoten und. . füge ihn in die Liste ein. Entferne den gewählten Knoten aus der Liste. Starte mit einem "leeren Weg". Wenn die Liste den Zielknoten enthält: Aktueller Knoten ist der Zielknoten. Solange der Startknoten nicht erreicht ist: Der Weg wird um d. Verbindung zwischen d. aktuellen Knoten. . und dem vermerkten Herkunftsknoten erweitert. Aktueller Knoten ist der vermerkte Herkunftsknoten. . des bisherigen aktuellen Knotens. Ausgabe: Weg imperative Lösung: Beschreibung, wie man einen Weg findet
86 Lösung des Wegsucheproblems Regel 1: Ein Weg zwischen einem Startknoten und einem Zielknoten besteht aus der Verbindung Startknoten - Zielknoten, wenn der Zielknoten ein Nachbarknoten des Startknotens ist. Regel 2: Ein Weg zwischen einem Startknoten und einem Zielknoten besteht (für einen bestimmten Nachbarknoten des Startknotens) aus der Verbindung Startknoten - Nachbarknoten und einem Weg zwischen dem Nachbarknoten und dem Zielknoten. deklarative Lösung: Beschreibung, was einen Weg ausmacht Imperative Problemlöseverfahren schreiben vor, wie man zu einer Lösung gelangt. Deklarative Problemlöseverfahren beschreiben, was das Problem ausmacht.
87 Vereinfachung des Wegsucheproblem: Zur Vereinfachung des Graphenproblems betrachten wir vorerst nur Graphen, die keine Kreise enthalten. % Graph kante(a, kante(b, kante(c, kante(d, kante(f, kante(h, kante(i, kante(h, b). c). d). e). f). g). e). b). i). e). h). b). e). gerichteter Graph ohne Kreise Beschreibung des Graphen mit Fakten
Aufgabe 88 kante(a, kante(b, kante(c, kante(d, kante(f, kante(h, kante(i, kante(h, b). c). d). e). f). g). e). b). i). e). h). b). e). Aufgabe: Entwickle geeignete Prolog-Regeln zur Festlegung des weg-Prädikats. Regel 1: Es gibt einen Weg zwischen einem Knoten X und einem Knoten Y, wenn es eine Kante von X nach Y gibt. Regel 2: Es gibt einen Weg zwischen einem Knoten X und einem Knoten Y, wenn es eine Kante von X zu einem Knoten Z und einen Weg vom Knoten Z zum Knoten Y gibt.
Aufgabe 89 kante(a, b). kante(a, c). gerichteter Graph ohne Kreise kante(b, d). kante(b, e). kante(c, f). kante(d, g). kante(d, e). kante(f, b). kante(f, i). kante(h, e). kante(i, h). kante(h, b). kante(h, e). weg(X, Y) : - kante(X, Y), print(Y). weg(X, Y) : - kante(X, Z), print(Z), weg(Z, Y). ? - weg(a, h). bdgeecefbdgeeih Yes Aufgabe: Kannst du erklären, wie die Ausgaben zu Stande kommen? Warum bezeichnet man die Suche hier auch als "Tiefensuche"?
90 Aufgabe kante(a, b). kante(a, c). kante(b, d). kante(b, e). kante(c, f). kante(d, g). kante(d, e). kante(f, b). kante(f, i). kante(h, e). kante(i, h). kante(h, b). kante(h, e). weg(X, X). weg(X, Y) : - kante(X, Z), weg(Z, Y). gerichteter Graph ohne Kreise Aufgabe: Teste auch die oben gezeigte Festlegung des weg-Prädikats. Warum funktioniert die Tiefensuche mit den bisher gezeigten Regeln nicht bei Graphen mit Kreisen? Probiere es ggf. aus, indem du eine zusätzliche Kante im Graphen einführst.
91 Aufsammeln der Wegknoten kante(a, b). kante(a, c). gerichteter Graph ohne Kreise kante(b, d). kante(b, e). kante(c, f). kante(d, g). kante(d, e). kante(f, b). kante(f, i). kante(h, e). kante(i, h). kante(h, b). kante(h, e). weg 0(X, X, []). weg 0(X, Y, [Z|W]) : - kante(X, Z), weg 0(Z, Y, W). ? - weg 0(a, b, W). . Aufgabe: Teste zunächst die Regeln mit Anfragen wie der folgenden. Kannst du erklären, wie die Ausgaben zu Stande kommen?
92 Aufsammeln in einer Akkumulatorliste kante(a, b). kante(a, c). gerichteter Graph ohne Kreise kante(b, d). kante(b, e). kante(c, f). kante(d, g). kante(d, e). kante(f, b). kante(f, i). kante(h, e). kante(i, h). kante(h, b). kante(h, e). weg 1(X, X, W, W). weg 1(X, Y, A, W) : - kante(X, Z), weg 1(Z, Y, [Z|A], W). weg(X, Y, W) : - weg 1(X, Y, [X], W). ? - weg 1(a, b, [a], W). . Aufgabe: Teste zunächst das weg 1 -(Hilfs-)Prädikat mit Anfragen. Beschreibe die "Logik" der beiden Regeln in Worten.
93 Lösung des Wegsucheproblems kante(a, b). kante(a, e). gerichteter Graph mit Kreisen kante(b, c). kante(c, e). kante(c, f). kante(d, g). kante(d, e). kante(e, f). kante(f, b). kante(f, i). kante(g, h). kante(h, e). kante(i, h). kante(h, b). kante(h, e). weg 2(X, X, W, W). weg 2(X, Y, A, W) : kante(X, Z), not(member(Z, A)), weg 2(Z, Y, [Z|A], W). weg(X, Y, W) : - weg 2(X, Y, [X], W). ? - weg(a, b, [a], W). .
94 Lösung des Tratsch-Problems % Anfrage: Wer darf an wen etwas Schlechtes über Btor schreiben? ? - darf_tratschen_wer_anwen_ueberwen(X, Y, b). X = c Y = d ; X = c Y = g ; X = d Y = c ; X = f Y = g ; X = g Y = h ; X = h Y = d ; No Aufgabe: Entwickle ein geeignetes Logikprogramm zur Lösung des Tratsch-Problems. Benutze die erzielten Ergebnisse zur Lösung des Graphenproblems.
95 Anwendung: Umfüllproblem Zum Nudelkochen im Ferienlager werden genau 2 Liter Wasser benötigt. Zum Abmessen stehen nur ein kleiner Eimer, der 3 Liter fasst, und einen etwas größerer Eimer, der 4 Liter fasst, zur Verfügung. Kann das funktionieren? Um systematisch alle durch Umfüllen erzeugbaren Wassermengen zu bestimmen, kann man einen Zustandsgraphen erstellen. Die Knoten des Graphen sind die aktuellen Füllinhalte der beiden Eimer. Die Kanten des Graphen stellen die Umfüllvorgänge dar. Aufgabe: Entwickle ein geeignetes Logikprogramm zur Lösung des Umfüllproblems. Die folgende Wissensbasis zeigt einen Weg auf, wie man die Umfüllvorgänge modellieren kann. Es fehlen aber noch eine Reihe von Regeln.
96 Anwendung: Umfüllproblem % Graph kante(X, Y) : - zustandsuebergang(X, Y). % 3 -l-Eimer füllen zustandsuebergang((Eimer 4, Eimer 3), (Eimer 4, 3)) : Eimer 3 == 3. % 4 -l-Eimer füllen. . . % 3 -l-Eimer leeren zustandsuebergang((Eimer 4, Eimer 3), (Eimer 4, 0)) : Eimer 3 == 0. % 4 -l-Eimer leeren. . . % 3 -l-Eimer umfüllen in 4 -l-Eimer zustandsuebergang((Eimer 4, Eimer 3), (Eimer 41, 0)) : Eimer 3 == 0, Eimer 3 + Eimer 4 =< 4, Eimer 41 is Eimer 3+Eimer 4. % 4 -l-Eimer umfüllen in 3 -l-Eimer. . . % 4 -l-Eimer teilw. umfüllen in 3 -l-Eimer. . . % 3 -l-Eimer teilw. umfüllen in 3 -l-Eimer zustandsuebergang((Eimer 4, Eimer 3), (4, Eimer 31)) : Eimer 4 == 4, Eimer 3 + Eimer 4 >4, Eimer 31 is Eimer 3+Eimer 4 -4. .
97 Deklarative Programmierung Ansatz: Beschreiben, was in der Modellwelt gelten soll Anfrage ? - zusammenfuegen([a, b], [c, a, d], Z). Wissensbasis zusammenfuegen([], Y, Y). zusammenfuegen([E|RX], Y, [E|RZ]) : fuegezusammen(RX, Y, RZ). Ergebnis Z = [a, b, c, a, d] Inferenzmaschine Deklarative Programmierung besteht darin, den Problemkontext (Miniwelt) mit gegebenen Mitteln (hier: Fakten und Regeln) zu beschreiben.
98 Imperative Programmierung Ansatz: Beschreiben, wie die Ergebnisse berechnet werden sollen A. -Zustand {X: [a, b]; Y: [c, a, d]} Z : = [] solange X nicht leer ist: E : = erstes. Element(X) Z : = mit. Letztem(Z, E) X : = ohne. Estes(X) Anweisungen solange Y nicht leer ist: E : = erstes. Element(Y) Z : = mit. Letztem(Z, E) Y : = ohne. Estes(Y) E. -Zustand Registermaschine {Z: [a, b, c, a, d]} Imperative Programmierung besteht darin, eine (mehr oder weniger abstrakte) Maschine mit Hilfe von Anweisungen zu steuern.
99 Literaturhinweise Gerhard Röhner: Informatik mit Prolog. Hessisches Landesinstitut für Pädagogik 2002. (He. LP Best. -Nr. : 06000). Rüdeger Baumann: PROLOG Einführungskurs. Klett-Verlag 1991. H. M. Otto: Pro. Log-Puzzles. Dümmler-Verlag 1991. Gregor Noll: PROLOG – eine Einführung in deklaratives Programmieren. http: //informatikag. bildung-rp. de/assets/download/Prolog. pps Herbert Drumm u. Hermann Stimm: Wissensverarbeitung mit PROLOG – Einstieg in die Algorithmik. Handreichung zum Lehrplan Informatik 1995. Klaus Merkert: Prolog. siehe http: //www. hsg-kl. de/faecher/inf/prolog/index. php Uwe Schöning: Logik für Informatiker. BI-Wissenschaftsverlag 1987.
- Slides: 99