Programmieren mit Prädikatenlogik Klaus Becker 2004
Programmieren mit Logik Alle Menschen sind sterblich. Sokrates ist ein Mensch. Sokrates ist sterblich. sterblich(X) :- mensch(X). mensch(sokrates). sterblich(sokrates). sterblich(X) :- mensch(X). mensch(sokrates). ?- sterblich(X). X = sokrates; No.
Teil 1 Fakten und Regeln
Die Welt der griechischen Götter (Heaven) Uranus = Gaea (Earth) | --------------------------------------- | | | | | Cronus = Rhea Coeus = Phoebe Oceanus = Tethys | | | ---------------------- Leto = Zeus Iapetus | | | | | | | Hestia | Poseidon | Demeter=Zeus | ---------------- Hades Zeus = Hera | | | | | | | Persephone | | Prometheus | Athena | --------- | | | | | Atlas Epimetheus --------------- Apollo Artemis | | | | | | | Ares Hebe Hephaestus Zeus=Maia Zeus=Dione | | From Edith Hamiltion's Mythology Hermes Aphrodite
Modellierungsansatz Eine (Mini)Welt besteht aus Objekten (Personen, Gegenstände, ...), die Eigenschaften haben und in Beziehung zueinander stehen. Hera (weiblich) Zeus (männlich) ist verheiratet mit
Modellierungsansatz Objekte werden mit Konstanten (Termen) beschrieben, Eigenschaften und Beziehungen mit Hilfe von Prädikaten. Fakten: weiblich(hera). maennlich(zeus). verheiratet(zeus, hera). Prädikat Konstante Konstante Hera (weiblich) Zeus (männlich) ist verheiratet mit
Modellierungsansatz Sachverhalte der Miniwelt können direkt mit Hilfe von Fakten beschrieben werden. Fakten: weiblich(hera). maennlich(zeus). verheiratet(zeus, hera). Hera (weiblich) Zeus (männlich) ist verheiratet mit Miniwelt
Modellierungsansatz Sachverhalte der Miniwelt können auch indirekt mit Hilfe von Regeln beschrieben werden. Fakten: weiblich(maia). maennlich(zeus). kind(hermes, zeus). kind(hermes, maia). Zeus=Maia Zeus=Dione | | Hermes Aphrodite Miniwelt Regeln: vater(X, Y) :- kind(Y, X), maennlich(X). mutter(X, Y) :- kind(Y, X), weiblich(X).
Regelkopf (Folgerung) Regeln Regeln sind Wenn-Dann-Aussagen. Implikation Und Variable Regeln: vater(X, Y) :- kind(Y, X), maennlich(X). mutter(X, Y) :- kind(Y, X), weiblich(X). Regelkopf (Folgerung) Regelrumpf (Bedingung) informelle Beschreibung: X ist Vater von Y, wenn Y Kind von X ist und X männlich ist. X ist Mutter von Y, wenn Y Kind von X ist und X weiblich ist.
Regelkopf (Folgerung) Rekursive Regeln Das Prädikat im Regelkopf kann im Regelrumpf vorkommen. Regeln: vorfahr(X, Y) :- kind(Y, X). vorfahr(X, Y) :- kind(Y, Z), vorfahr(X, Z). Regelkopf (Folgerung) Regelrumpf (Bedingung) informelle Beschreibung: X ist Vorfahr von Y, wenn Y Kind von X ist. X ist Vorfahr von Y, wenn Y Kind von Z und X Vorfahr von Z ist.
Von der Miniwelt zur Modellwelt Uranus | Rhea | Zeus | Hebe ... Miniwelt Modellwelt vorfahr(zeus, hebe). vorfahr(rhea, hebe). vorfahr(uranus, hebe). ... Fakten und Regeln: kind(hebe, zeus). kind(hebe, hera). kind(zeus, rhea). kind(zeus, cronus). kind(rhea, uranus). ... vorfahr(X, Y) :- kind(Y, X). vorfahr(X, Y) :- kind(Y, Z), vorfahr(X, Z). Beschreibung der Miniwelt
Logische Herleitung der Modellwelt kind(hebe, zeus). kind(hebe, hera). kind(zeus, rhea). kind(zeus, cronus). kind(rhea, uranus). ... vorfahr(X, Y) :- kind(Y, X). vorfahr(X, Y) :- kind(Y, Z), vorfahr(X, Z). Beschreibung der Miniwelt Logische Herleitung kind(hebe, zeus). vorfahr(X, Y) :- kind(Y, X). vorfahr(zeus, hebe). kind(zeus, rhea). vorfahr(zeus, hebe). vorfahr(X, Y) :- kind(Y, Z), vorfahr(X, Z). vorfahr(rhea, hebe). vorfahr(zeus, hebe). vorfahr(rhea, hebe). ... Modellwelt
Modus Ponens Zur Festlegung 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. Für alle X: mensch(X) sterblich(X). mensch(sokrates). sterblich(sokrates). sterblich(X) :- mensch(X). mensch(sokrates). sterblich(sokrates).
Modellierungskonzept Das gesamte Wissen über die Welt wird mit Fakten und Regeln modelliert. In der Modellwelt gelten nur die „Sachverhalte“, die mit Hilfe der gegebenen Fakten und Regeln logisch abgeleitet werden können. Dies sind die direkt genannten Fakten und die mit Hilfe der logischen Schlussregel abgeleiteten Fakten (closed-world-assumption).
Anfragen maennlich(zeus). weiblich(hera). weiblich(maia). kind(apollo, zeus). kind(hermes, maia). kind(hermes, zeus). vater(X, Y) :- kind(Y, X), maennlich(X). ?- maennlich(zeus). % Ist Zeus männlich? Yes. ?- maennlich(hera). % Ist Hera männlich? No. Ja-Nein-Anfrage
Anfragen maennlich(zeus). weiblich(hera). weiblich(maia). kind(apollo, zeus). kind(hermes, maia). kind(hermes, zeus). vater(X, Y) :- kind(Y, X), maennlich(X). ?- vater(W, hermes). % Wer ist Vater von Hermes? W = zeus; No. ?- weiblich(Frau). % Wer ist weiblich? Frau = hera; Frau = maia; No. Ergänzungsanfrage
Anfragen mit anonymen Variablen maennlich(zeus). weiblich(hera). weiblich(maia). kind(apollo, zeus). kind(hermes, maia). kind(hermes, zeus). vater(X, Y) :- kind(Y, X), maennlich(X). mutter(X) :- weiblich(X), kind(_, X). ?- vater(V, _Kind) % Wer ist Vater? ?- mutter(M) % Wer ist Mutter? Anonyme Variable Anonyme Variablen werden nicht instanziert.
Datenflussrichtung maennlich(zeus). weiblich(hera). weiblich(maia). kind(apollo, zeus). kind(hermes, maia). kind(hermes, zeus). vater(X, Y) :- kind(Y, X), maennlich(X). ?- vater(maia, hermes). % Ist Maia der Vater von Hermes? ?- vater(V, hermes). % Wer ist der Vater von Hermes? ?- vater(zeus, K). % Von wem ist Zeus der Vater? ?- vater(V, K). % Wer ist Vater von wem?
Kann in beiden Rollen (+ / -) verwendet werden Datenflussrichtung maennlich(zeus). weiblich(hera). weiblich(maia). kind(apollo, zeus). kind(hermes, maia). kind(hermes, zeus). vater(X, Y) :- % vater(?Vater, ?Kind) kind(Y, X), maennlich(X). Kann in beiden Rollen (+ / -) verwendet werden ?- vater(maia, hermes). % vater(+Vater, +Kind) instanziert ?- vater(V, hermes). % vater(-Vater, +Kind) ?- vater(zeus, K). % vater(+Vater, -Kind) offen ?- vater(V, K). % vater(-Vater, -Kind) Die Datenflussrichtung kann flexibel gestaltet werden.
Logik-Programm maennlich(zeus). weiblich(hera). weiblich(maia). kind(apollo, zeus). kind(hermes, maia). kind(hermes, zeus). vater(X, Y) :- kind(Y, X), maennlich(X). Wissensbasis ?- weiblich(Frau). Anfrage Ein Logik-Programm besteht aus einer Wissensbasis und einer Anfrage.
Hinweise zur Syntax maennlich(zeus). weiblich(hera). weiblich(maia). kind(apollo, zeus). kind(hermes, maia). kind(hermes, zeus). vater(X, Y) :- kind(Y, X), maennlich(X). ?- weiblich(Frau). Jede Deklaration der Wissensbasis und jede Anfrage schließt mit einem Punkt ab. Variablenbezeichner beginnen mit einem Großbuchstaben (oder anonym mit _), Konstanten- und Prädikatenbezeichner mit Kleinbuchstaben.
PROLOG PROLOG („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 (unterrichtsgeeignete) Entwicklungsumgebung zur Erstellung von PROLOG-Programmen (Autor: G. Röhner).
SWI-Prolog-Editor Wissensbasis Anfrage
SWI-Prolog-Editor Consultieren Mit consult(<Datei>) werden aus der angegebenen Datei die Fakten und Regeln in die Wissensbasis eingelesen.
Übungen Aufgabe 1: Familie Entwickeln Sie eine Wissensbasis zu einer Familien-Welt. Folgende Prädikate können festgelegt werden: maennlich, weiblich, kind, vater, mutter, vorfahr, sohn, tochter, grossvater, grossmutter, enkel, geschwister, bruder, schwester, onkel, tante, ... Testen Sie ihre Wissensbasis mit Hilfe geeigneter Anfragen.
Übungen Aufgabe 2: Wir betrachten die unten abgebildete Blockwelt. Wie könnte man die Strukrur dieser Blockwelt mit Hilfe von Fakten und Regeln beschreiben? d g c f a e b p1 p2 p3
Das Berechnungskonzept Teil 2 Das Berechnungskonzept
Berechnungsproblem Gegeben: Logik-Programm (Wissensbasis + Anfrage) maennlich(zeus). weiblich(hera). weiblich(maia). kind(apollo, zeus). kind(hermes, maia). kind(hermes, zeus). vater(X, Y) :- kind(Y, X), maennlich(X). maennlich(zeus). weiblich(hera). weiblich(maia). kind(apollo, zeus). kind(hermes, maia). kind(hermes, zeus). vater(zeus, apollo). vater(zeus, hermes). ... ?- vater(V, hermes). Gesucht: Instanzen der Anfrage, die zur Modellwelt gehören V = zeus. Problem: Wie erzeugt man systematisch Anfrageergebnisse?
Berechnungsproblem Wissensbasis maennlich(zeus). weiblich(hera). weiblich(maia). kind(apollo, zeus). kind(hermes, maia). kind(hermes, zeus). vater(X, Y) :- kind(Y, X), maennlich(X). ... Herleitung (Beweis) kind(hermes, zeus). maennlich(zeus). vater(X, Y) :- kind(Y, X), maennlich(X). ------------------------------------ vater(zeus, hermes). Anfrage ?- vater(V, hermes). Ergebnis V = zeus. /* Substitution */ Problem: Wie erzeugt man systematisch logische Herleitungen?
Auswertung von Anfragen /*1*/ maennlich(zeus). /*2*/ weiblich(hera). /*3*/ weiblich(maia). /*4*/ kind(apollo, zeus). /*5*/ kind(hermes, maia). /*6*/ kind(hermes, zeus). /*7*/ vater(X, Y) :- kind(Y, X), maennlich(X). Regel 7 Substitution X = V, Y = hermes. Ziel ?- vater(V, hermes). ?- kind(hermes, V), maennlich(V). Unifikation: Suche einen Fakt / Regelkopf, der mit dem ersten Term des Ziels unifiziert (d. h. durch eine Substitution gleichgemacht werden kann). Resolution (bei Regel): Ersetze den ersten Term des Ziels durch den Regelrumpf und wende auf alle Terme des Ziels die Substitution an.
Auswertung von Anfragen /*1*/ maennlich(zeus). /*2*/ weiblich(hera). /*3*/ weiblich(maia). /*4*/ kind(apollo, zeus). /*5*/ kind(hermes, maia). /*6*/ kind(hermes, zeus). /*7*/ vater(X, Y) :- kind(Y, X), maennlich(X). Regel 7 5 Substitution X = V, Y = hermes. V = maia. Ziel ?- vater(V, hermes). ?- kind(hermes, V), maennlich(V). ?- maennlich(maia). Unifikation: Suche einen Fakt / Regelkopf, der mit dem ersten Term des Ziels unifiziert (d. h. durch eine Substitution gleichgemacht werden kann). Resolution (bei Regel): Ersetze den ersten Term des Ziels durch den Regelrumpf und wende auf alle Terme des Ziels die Substitution an.
Auswertung von Anfragen /*1*/ maennlich(zeus). /*2*/ weiblich(hera). /*3*/ weiblich(maia). /*4*/ kind(apollo, zeus). /*5*/ kind(hermes, maia). /*6*/ kind(hermes, zeus). /*7*/ vater(X, Y) :- kind(Y, X), maennlich(X). Regel 7 5 No Substitution V = maia. Ziel ?- vater(V, hermes). ?- kind(hermes, V), maennlich(V). ?- maennlich(maia). Backtracking: Wenn der erste Term des Ziels mit keinem Fakt / Regelkopf unifiziert, dann geh zurück zu dem Ziel, bei dem als letztes eine Auswahlmöglichkeit bestand und treffe eine neue Auswahl.
Auswertung von Anfragen /*1*/ maennlich(zeus). /*2*/ weiblich(hera). /*3*/ weiblich(maia). /*4*/ kind(apollo, zeus). /*5*/ kind(hermes, maia). /*6*/ kind(hermes, zeus). /*7*/ vater(X, Y) :- kind(Y, X), maennlich(X). Regel 7 5 No 6 Substitution V = maia. V = zeus. Ziel ?- vater(V, hermes). ?- kind(hermes, V), maennlich(V). ?- maennlich(maia). ?- maennlich(zeus).
Auswertung von Anfragen /*1*/ maennlich(zeus). /*2*/ weiblich(hera). /*3*/ weiblich(maia). /*4*/ kind(apollo, zeus). /*5*/ kind(hermes, maia). /*6*/ kind(hermes, zeus). /*7*/ vater(X, Y) :- kind(Y, X), maennlich(X). Regel 7 5 No 6 1 Substitution V = maia. V = zeus. Ziel ?- vater(V, hermes). ?- kind(hermes, V), maennlich(V). ?- maennlich(maia). ?- maennlich(zeus). Ergebnis: Ist keine Zielklausel mehr vorhanden, so liefert die Substitution das gesuchte Ergebnis.
Beweisbaum UND-Knoten ODER-Knoten /*1*/ maennlich(zeus). /*2*/ weiblich(hera). /*3*/ weiblich(maia). /*4*/ kind(apollo, zeus). /*5*/ kind(hermes, maia). /*6*/ kind(hermes, zeus). /*7*/ vater(X, Y) :- kind(Y, X), maennlich(X). vater(V, hermes) kind(hermes, V) maennlich(V) kind(hermes, maia) kind(hermes, zeus) maennlich(zeus) UND-Knoten X = V, Y = hermes. ODER-Knoten V = maia. V = zeus. V = zeus. Veranschaulichung: Die Herleitung eines Berechnungsergebnisses kann mit Hilfe eines Beweisbaumes verdeutlicht werden.
Trace einer Beweissuche vater(V, hermes) kind(hermes, V) maennlich(V) kind(hermes, maia) kind(hermes, zeus) maennlich(zeus) UND-Knoten ODER-Knoten ?- vater(V, hermes). CALL: vater(V, hermes) CALL: kind(hermes, V) CALL: kind(hermes, maia) EXIT: kind(hermes, maia) CALL: maennlich(maia) FAIL: maennlich(maia) CALL: Teilziel aufrufen EXIT: Zeilziel erfolgr. b. REDO: Teilziel nochmal b. FAIL: Teilziel erfolglos b. REDO: kind(hermes, V) CALL: kind(hermes, zeus) EXIT: kind(hermes, zeus) CALL: maennlich(zeus) EXIT: maennlich(zeus) EXIT: vater(V, hermes) V = zeus.
Das Berechnungskonzept Das Berechnungskonzept bei der logischen Programmierung beruht auf „maschinellem“ logischen Schließen. Hierzu werden die folgenden Algorithmen von einer sog. Inferenzmaschine geeignet kombiniert: Unifikationsalgorithmus (erzeugt Variablenbindung) Inferenzalgorithmus (führt Resolution durch) Suchalgorithmus (benutzt Backtracking)
Das Berechnungskonzept Die Inferenzmaschine versucht, logische Ableitungen zur Anfrage aus der Wissensbasis zu erstellen. Anfrage ?- vorfahr(A, B). kind(hermes, maia). vorfahr(X, Y) :- kind(Y, X). vorfahr(X, Y) :- kind(Y, Z), vorfahr(X, Z). Inferenz-maschine Wissensbasis Ergebnis X = maia, Y = hermes.
Deklarative Semantik Logisches Programm (Wissensbasis + Anfrage) maennlich(zeus). weiblich(hera). weiblich(maia). kind(apollo, zeus). kind(hermes, maia). kind(hermes, zeus). vater(X, Y) :- kind(Y, X), maennlich(X). ?- vater(V, hermes). Deklarative Semantik eines Logik-Programms Menge der Instanzen der Anfrageklausel, die zur Modellwelt gehören bzw. die aus der Wissensbasis mit Hilfe der Schlussregel „modus ponens“ hergeleitet werden können.
Prozedurale Semantik Logisches Programm (Wissensbasis + Anfrage) maennlich(zeus). weiblich(hera). weiblich(maia). kind(apollo, zeus). kind(hermes, maia). kind(hermes, zeus). vater(X, Y) :- kind(Y, X), maennlich(X). ?- vater(V, hermes). Prozedurale Semantik des Programms Menge der Instanzen der Anfrageklausel, die die Inferenzmaschine mittels Unifikations-, Inferenz- und Suchalgorithmus erzeugt.
Übungen Aufgabe 3: Berechnungskonzept Wir betrachten das folgende Logik-Programm zur Blockwelt: auf(a, p1). auf(c, a). auf(e, p2). auf(b, p3). auf(f, b). auf(g, f). auf(d, g). ueber(X, Y) :- auf(X, Y). ueber(X, Y) :- auf(X, Z), ueber(Z, Y). d g c f a e b p1 p2 p3 ?- ueber(X, g). Schalten Sie den Trace-Modus ein und verfolgen Sie die Erzeugung der Berechnungsergebnisse. Erstellen Sie auch einen Beweisbaum.
Übungen Aufgabe 4: Berechnungskonzept Wir betrachten die beiden folgenden Logik-Programme: Wissensbasis - Version 1: kind(hermes, maia). vorfahr(X, Y) :- kind(Y, X). vorfahr(X, Y) :- kind(Y, Z), vorfahr(X, Z). Wissensbasis - Version 2: kind(hermes, maia). vorfahr(X, Y) :- vorfahr(X, Z), kind(Y, Z). vorfahr(X, Y) :- kind(Y, X). ?- vorfahr(A, B). Welche Berechnungsergebnisse erwarten Sie? Bestimmen Sie die Ergebnisse mit Hilfe von PROLOG. Verfolgen Sie die Berechnung der Ergebnisse mit Hilfe einer Trace. Wie lässt sich das Verhalten von PROLOG erklären?
Grenzen der Logik Logisches Programm (Wissensbasis + Anfrage) Wissensbasis - Version 1: kind(hermes, maia). vorfahr(X, Y) :- kind(Y, X). vorfahr(X, Y) :- kind(Y, Z), vorfahr(X, Z). Wissensbasis - Version 2: kind(hermes, maia). vorfahr(X, Y) :- vorfahr(X, Z), kind(Y, Z). vorfahr(X, Y) :- kind(Y, X). ?- vorfahr(A, B). kind(hermes, maia). vorfahr(X, Y) :- kind(Y, X). vorfahr(maia, hermes). Die Modellierungen sind logisch äquivalent – die Logik-Programme haben dieselbe deklarative Semantik.
Grenzen der Logik Logisches Programm (Wissensbasis + Anfrage) Wissensbasis - Version 1: /*1*/ kind(hermes, maia). /*2*/ vorfahr(X, Y) :- kind(Y, X). /*3*/ vorfahr(X, Y) :- kind(Y, Z), vorfahr(X, Z). Regel 2 1 Substitution X = A, Y = B B = hermes, A = maia. Ziel ?- vorfahr(A, B). ?- kind(B, A).
Grenzen der Logik Logisches Programm (Wissensbasis + Anfrage) Wissensbasis - Version 2: /*1*/ kind(hermes, maia). /*2*/ vorfahr(X, Y) :- vorfahr(X, Z), kind(Y, Z). /*3*/ vorfahr(X, Y) :- kind(Y, X). Regel 2 Substitution X = A, Y = B X = A, Y = Z. ... Ziel ?- vorfahr(A, B). ?- vorfahr(A, Z), kind(B, Z). ?- vorfahr(A, U), kind(Z, U), kind... ... Die Inferenzmaschine liefert unterschiedliche Berechnungsergebnisse – die Logik-Programme haben eine unterschiedliche prozedurale Semantik.
Grenzen der Logik Logisches Programm (Wissensbasis + Anfrage) Wissensbasis - Version 1: kind(hermes, maia). vorfahr(X, Y) :- kind(Y, X). vorfahr(X, Y) :- kind(Y, Z), vorfahr(X, Z). Wissensbasis - Version 2: kind(hermes, maia). vorfahr(X, Y) :- vorfahr(X, Z), kind(Y, Z). vorfahr(X, Y) :- kind(Y, X). ?- vorfahr(A, B). Beachte: Die prozedurale Semantik wird durch die Algorithmen der Inferenzmaschine festgelegt. Die Reihenfolge der Programmklauseln und Zielklauseln können hierbei eine entscheidende Rolle spielen.
Deklarative Programmierung Beschreiben, was in der Modellwelt gelten soll Anfrage ?- vorfahr(A, B). kind(hermes, maia). vorfahr(X, Y) :- kind(Y, X). vorfahr(X, Y) :- kind(Y, Z), vorfahr(X, Z). Inferenz-maschine Wissensbasis Ergebnis X = maia, Y = hermes. Deklarative Programmierung besteht darin, den Problemkontext (Miniwelt) mit gegebenen Mitteln (hier: Fakten und Regeln) zu beschreiben.
Imperative Programmierung Beschreiben, wie die Ergebnisse berechnet werden sollen A.-Zustand {x: 3; y: 5} z := x; x := y; y := z; Register-maschine Anweisungen E.-Zustand {x: 5; y: 3; z: ...} Imperative Programmierung besteht darin, eine (mehr oder weniger abstrakte) Maschine mit Hilfe von Anweisungen zu steuern.
Anwendung: Datenbanken Teil 3 Anwendung: Datenbanken
Eine einfache Bibliothekswelt
ER-Modellierung Leser Ausleihe Buch LNr Name ... Datum Sig Autor ... LNr: 3 Name: Müller Vorname: Peter ... Sig: Rel1 Autor: Titel: Bibel ... 8.1.2002 LNr: 6 Name: Schmitt Vorname: Otto ... Sig: M1 Autor: Euklid Titel: Elemente ... LNr: 1 Name: Meier Vorname: Karla ... 16.2.2002 Sig: P1 Autor: Einstein Titel: Relativität ... Leser Ausleihe Buch LNr Name ... Datum Sig Autor ...
Relationales Datenmodell Leser Buch Ausleihe
Beschreibung mit Fakten % Leser ... leser(15, 'Wollenweber', 'Lisa', 84, tm). % Bücher buch('ph1', 'Garder', 'Sofies Welt', 1995, 'Philosophie'). % Ausleihen ausleihe(15, 'm3', datum(12,10,2001)).
Eine Anfrage % Welche Leser haben ein Buch ausgeliehen? ?- ausleihe(Nr, Sig, _Datum), leser(Nr, Name, Vorname, _GebJahr, _StK). Nr = 3 Sig = 'Ph1' Name = 'Frisch' Vorname = 'Johannes' ; Nr = 4 Sig = 'D2' Name = 'Frölich' Vorname = 'Daniel' ; Sig = 'P2' ...
Übungen Aufgabe 5: Bibliothek Laden Sie die Fakten zur Beschreibung der Bibliothekswelt. Erstellen Sie zu den folgenden Aufgaben entsprechende Abfragen. - Welche Leser gibt es? - Welche Leser sind 84 geboren? - Welche Leser sind vor 84 geboren? - Welche Bücher von Goethe sind in der Bibliothek vorhanden? - Welche Bücher sind ausgeliehen? - Welche Bücher hat die Leserin Lisa Wollenweber ausgeliehen? - Welche Leser haben ein Buch ausgeliehen? ...
Eine Regel für Mahnungen Ein Leser soll eine Mahnung erhalten, wenn er/sie ein Buch länger als einen Monat ausgeliehen hat. % Leser mahnung(Name, Vorname, Sig, datum(Takt, Makt, Jakt)) :- leser(LNr, Name, Vorname, _, _), ausleihe(LNr, Sig, datum(Taus, Maus, Jaus)), monatspaeter(datum(Taus, Maus, Jaus), datum(Takt, Makt, Jakt)).
Eine Regel für Mahnungen Spezifikation: monatspaeter(datum(Taus, Maus, Jaus), datum(Takt, Makt, Jakt)) soll gelten, wenn das Datum „Takt.Makt.Jakt“ mehr als ein Monat später als das Datum „Taus.Maus.Jaus“ ist. Beispiele: monatspaeter(datum(11, 7, 2001), datum(20, 9, 2001)) monatspaeter(datum(17, 4, 2001), datum(1, 1, 2002)) ...
Eine Regel für Mahnungen monatspaeter(datum(T1,M1,J1), datum(T2,M2,J2)) :- T2 >= T1, M2 >= M1+1, J2 >= J1. M2 >= M1+2, J2 >= J1. T2 >= T1, J2 >= J1+1. (12-M1)+M2 >= 2, J2 >= J1+1. J2 >= J1+2.
Ausleihen und Zurückgeben Bücher können ausgeliehen und zurückgegeben werden. % Ausleihen ausleihe(3,'Ph1',datum(30,12,2001)). ausleihe(4,'D2',datum(16,9,2001)). ausleihe(4,'P2',datum(30,12,2001)). ausleihe(6,'D3',datum(30,12,2001)). ausleihe(8,'M1',datum(23,10,2001)). ausleihe(11,'P1',datum(14,12,2001)). % löschen ausleihe(12,'M2',datum(30,12,2001)). ausleihe(13,'D5',datum(30,8,2001)). ausleihe(13,'Ph2',datum(11,7,2001)). ausleihe(14,'D1',datum(13,12,2001)). ausleihe(15,'M3',datum(1,11,2001)). ausleihe(2,'P1',datum(10,1,2002)). % einfügen
Veränderung der Wissensbasis % Ausleihen :- dynamic ausleihe/3. % Achtung ausleihe(3,'Ph1',datum(30,12,2001)). ausleihe(4,'D2',datum(16,9,2001)). ausleihe(4,'P2',datum(30,12,2001)). ausleihe(6,'D3',datum(30,12,2001)). ausleihe(8,'M1',datum(23,10,2001)). ausleihe(11,'P1',datum(14,12,2001)). ausleihe(12,'M2',datum(30,12,2001)). ausleihe(13,'D5',datum(30,8,2001)). ausleihe(13,'Ph2',datum(11,7,2001)). ausleihe(14,'D1',datum(13,12,2001)). ausleihe(15,'M3',datum(1,11,2001)). Beachte: Damit die Prädikate verändert werden können, müssen sie als dynamisch deklariert werden.
Veränderung der Wissensbasis Prädikate zur Manipulation der Wissensbasis: asserta(+Klausel) fügt die Klausel vor den bereits bestehenden Klauseln ein assertz(+Klausel) fügt die Klausel hinter die bereits bestehenden Klauseln ein retract(+Klausel) löscht die Klausel
Veränderung der Wissensbasis % zurueckgeben zurueckgeben(Sig) :- retract(ausleihe(LNr, Sig, datum(T,M,J))). % ausleihen ausleihen(LNr, Sig, Tag, Monat, Jahr) :- assertz(ausleihe(LNr, Sig, datum(Tag,Monat,Jahr)))
Laden und Speichern Prädikate zur Verwaltung der Wissensbasis: consult(+Dateiname) liest die Fakten und Regeln der Datei ein und ergänzt die aktuelle Wissensbasis listing listet alle Klauseln auf listing(+Prädikat) listet alle Fakten zum betreffenden Prädikat auf tell(+Dateiname) legt das Ausgabemedium fest told schließt das aktuelle Ausgabemedium
Laden und Speichern % Bibliotheksdaten laden :- consult('BibliothekDaten.pl'). % Bibliotheksdaten speichern speichern :- tell('BibliothekDaten.pl'), listing(leser), listing(buch), listing(ausleihe), told.
Teil 4 Listenverarbeitung
email-Adressbuch Petra Schmitt pm@aol.com Walter Meier meier@t-online.de, walter@gmx.de Sandra Roth sroth@gmx.de, sandra@roth.de, rosa@web.de ...
Beschreibung der Miniwelt Email-Adressbuch Miniwelt: Adressbuch Petra Schmitt pm@aol.com Walter Meier meier@t-online.de, walter@gmx.de Sandra Roth sroth@gmx.de, sandra@roth.de, rosa@web.de ... Beschreibung der Miniwelt email(petraSchmitt, [ 'pm@aol.com' ] ). email(walterMeier, [ 'meier@t-online.de', 'walter@gmx.de' ] ). email(sandraRoth, [ 'sroth@gmx.de', 'sandra@roth', 'rosa@web.de' ] ). ... % addemail(...). % delemail(...).
Listen Eine Liste ist eine geordnete Folge von Elementen beliebiger Länge. Die Elemente der Liste können beliebige Terme sein: Konstanten, Zahlen, Variablen, Strukturen und auch wieder Listen. Die Listenelemente können dabei unterschiedliche Datentypen aufweisen. Beispiele: [ 'lisa@gmx.de', 'lisa@wollenweber.de', 'lw@web.de' ] ...
Listenkonstruktoren Alle Listen können mit Hilfe der beiden Konstruktoren [] („leere Liste“) und . („Einfügoperator“) aufgebaut werden. Beispiel: . (a, . (b, . (c, []))) [a, b, c] . (c, []) [c] . (b, [c]) [b, c] . (a, [b, c]) [a, b, c] Struktur: .(Element, Liste) NeueListe
Unifikation bei Listen Jede Liste lässt sich in der Form [Kopfelement | Restliste] darstellen. Beispiele: [K | R] = [a, b, c] K = a, R = [b, c] [K | R] = [5] K = 5, R = [] [K | R] = [[1], [3]] K = [1], R = [[3]] [E1, E2 | R] = [a, b, c] E1 = a, E2 = b, R = [c] [E1, E2 | R] = [a] Unifikation nicht möglich ...
Hinzufügen Aufgabe: Es soll ein Prolog-Programm entwickelt werden, mit dessen Hilfe ein Element in eine Liste eingefügt werden kann. Spezifikation: add1/3 Semantik: add1(E, AlteListe, NeueListe) gilt in der Modellwelt, wenn NeueListe = [E | AlteListe]. Beispiel: add1(a, [b, c, d], [a, b, c, d])
Hinzufügen Spezifikation: add1/3 Semantik: add1(E, AlteListe, NeueListe) gilt in der Modellwelt, wenn NeueListe = [E | AlteListe]. Beispiel: add1(a, [b, c, d], [a, b, c, d]) Programm (Version1: mit Regel): add1(E, AlteListe, NeueListe) :- NeueListe = [E | AlteListe]. Programm (Version2: mit Faktum): add1(E, AlteListe, [E | AlteListe]).
Hinzufügen Programm (Version1: mit Regel): add1(E, AlteListe, NeueListe) :- NeueListe = [E | AlteListe]. Programmtest: ?- add1(a, [b, c, d], L). L = [a, b, c, d] ; No ?- add1(b, [b, c, d], L). L = [b, b, c, d] ; ?- add1(c, [b, c, d], L). L = [c, b, c, d] ; Programm (Version2: mit Faktum): add1(E, AlteListe, [E | AlteListe]).
Hinzufügen Aufgabe: Es soll ein Prolog-Programm entwickelt werden, mit dessen Hilfe ein Element in eine Liste eingefügt werden kann, die das Element eventuell bereits enthält. Spezifikation: add2/3 Semantik: add2(E, AlteListe, NeueListe) gilt in der Modellwelt, wenn entweder AlteListe E bereits enthält und dann NeueListe = AlteListe gilt, oder wenn AlteListe E nicht enthält und NeueListe sowohl E als auch alle Elemente von AlteListe enthält.
Hinzufügen Fallunterscheidung gemäß der Struktur der Liste, in die das neue Element eingefügt werden soll: % Einfügen in eine leere Liste: add2(E, [], [E]). % Einfügen in eine nichtleere Liste, deren erstes Element dem einzufügenden entspricht: add2(E, [E|X], [E|X]). % Einfügen in eine nichtleere Liste, deren erstes Element dem einzufügenden nicht entspricht: add2(E, [A|X], L) :- ???
Rekursive Problemreduktion % Einfügen in eine nichtleere Liste, deren erstes Element dem einzufügenden nicht entspricht: add2(E, [A|X], L) :- ??? Rekursives Problemreduktion: E eingefügt in [A|X] ergibt [A|M], wenn E \= A und wenn E eingefügt in X die Liste M ergibt. % Einfügen in eine nichtleere Liste, deren erstes Element dem einzufügenden nicht entspricht: add2(E, [A|X], [A|M]) :- E \= A, add2(E, X, M).
Auswertung einer Anfrage Wissensbasis (mit rekursiver Problemreduktion): /* 1 */ add2(E, [], [E]). /* 2 */ add2(E, [E|X], [E|X]). /* 3 */ add2(E, [A|X], [A|M]) :- E \= A, add2(E, X, M). Anfrage: ?- add(a, [b, c], L). Regel 3 1 Substitution E0 = a, A0 = b, X0 = [c], L = [A0|M0]. E1 = a, A1 = c, X1 = [], M0 = [A1|M1] E2 = a, M1 = [E2] Ziel ?- add2(a, [b, c], L). ?- add2(a, [c], M0). ?- add2(a, [], M1). Ergebnis: ?- L = [A0|M0] = [b|[A1|M1]] = [b|[c|[E2]]] = [b|[c|[a]]] = [b, c, a]
Deklaratives Denken Wissensbasis (mit rekursiver Problemreduktion): /* 1 */ add2(E, [], [E]). /* 2 */ add2(E, [E|X], [E|X]). /* 3 */ add2(E, [A|X], [A|M]) :- E \= A, add2(E, X, M). Anfrage: ?- add(a, [b, c], L). Muss vom Entwickler geleistet werden Wird von der Inferenzmaschine geleistet Regel 3 1 Substitution E0 = a, A0 = b, X0 = [c], L = [A0|M0]. E1 = a, A1 = c, X1 = [], M0 = [A1|M1] E2 = a, M1 = [E2] Ziel ?- add2(a, [b, c], L). ?- add2(a, [c], M0). ?- add2(a, [], M1). Man beschreibt nicht Schritt für Schritt einen Einfügevorgang, sondern man beschreibt das Ergebnis eines Einfügevorgangs.
Löschen Aufgabe: Es soll ein Prolog-Programm entwickelt werden, mit dessen Hilfe ein Element aus einer Liste gelöscht werden kann. Spezifikation: del/3 Semantik: del(E, AlteListe, NeueListe) gilt in der Modellwelt, wenn entweder AlteListe E nicht enthält und dann NeueListe = AlteListe gilt, oder wenn AlteListe E enthält und NeueListe aus AlteListe durch Entfernen von E entsteht.
Übungen Aufgabe 6: Listenverarbeitung Entwerfen Sie zunächst eine Fallunterscheidung gemäß der Struktur der Liste, aus der das Element gelöscht werden soll. Entwickeln Sie dann passende Fakten und Regeln zur Beschreibung des Ergebnisses eines Löschvorgangs.
Übungen Aufgabe 7: Listenverarbeitung Ergänzen Sie die Fakten bzw. Regeln. Lösen Sie Fall 3 mit Hilfe einer rekursiven Problemreduktion % Löschen aus einer leeren Liste: del(E, [], ). % Löschen aus einer (nichtleeren) Liste, deren erstes Element dem zu löschenden entspricht: del(E, [E|X], ). % Löschen aus einer (nichtleeren) Liste, deren erstes Element dem zu löschenden nicht entspricht: del(E, [A|X], ) :- E \= A, .
Lösung Wissensbasis (mit rekursiver Problemreduktion): del(E, [], []). del(E, [E|X], X). del(E, [A|X], [A|M]) :- E \= A, del(E, X, M).
Sortieren Aufgabe: Es soll ein Prolog-Programm entwickelt werden, mit dessen Hilfe eine Liste (bestehend aus Konstanten) sortiert werden kann. Spezifikation: inssort/2 Semantik: inssort(AlteListe, NeueListe) gilt in der Modellwelt, wenn NeueListe aus AlteListe durch Sortieren der Elemente entsteht.
Vorbereitung Bearbeitung von Atomen: name(?Atom, ?ASCIIListe) wandelt ein Atom in eine Liste von ASCII-Codes um und umgekehrt Test: ?- name(hallo, L). L = [104, 97, 108, 108, 111] ; No ?- name(N, [104, 97, 108, 108, 111]). N = hallo ;
Übungen Aufgabe 8: Listenvergleich Entwickeln Sie die Fakten bzw. Regeln, mit denen man zwei Listen mit ASCII-Codes (Zahlen) vergleichen kann. Überlegen Sie sich hierzu, in welchen Fällen eine Liste „kleiner“ ist als eine andere. % ASCII-Listen vergleichen kleiner([], L) :- kleiner([K|R], [K1|R1]) :- kleiner([K|R], [K1|R1]) :- % Atome vergleichen vor(A, B) :- name(A, LA), name(B, LB), kleiner(LA, LB).
Übungen Aufgabe 9: Einfügen in eine sortierte Liste ins(E, AlteListe, NeueListe) gilt in der Modellwelt, wenn NeueListe aus einer sortierten Liste AlteListe entsteht, indem das Element E an der „richtigen“ Stelle einsortiert wird.
Lösung Aufgabe 8: Listenvergleich Entwickeln Sie die Fakten bzw. Regeln, mit denen man zwei Listen mit ASCII-Codes (Zahlen) vergleichen kann. Überlegen Sie sich hierzu, in welchen Fällen eine Liste „kleiner“ ist als eine andere. % ASCII-Listen vergleichen kleiner([], L) :- L \= []. kleiner([K|R], [K1|R1]) :- K < K1. kleiner([K|R], [K1|R1]) :- K = K1, kleiner(R, R1). % Atome vergleichen vor(A, B) :- name(A, LA), name(B, LB), kleiner(LA, LB).
Lösung Aufgabe 9: Einfügen in eine sortierte Liste ins(E, AlteListe, NeueListe) gilt in der Modellwelt, wenn NeueListe aus einer sortierten Liste AlteListe entsteht, indem das Element E an der „richtigen“ Stelle einsortiert wird. % Einfügen ins(E, [], [E]). ins(E, [E|R], [E | [E |R]]). ins(E, [K|R], [E | [K |R]]) :- vor(E, K). ins(E, [K|R], [K|M]) :- vor(K, E), ins(E, R, M).
Übungen Aufgabe 10: Sortieren durch Einfügen Erklären Sie die aufgelisteten Fakten und Regeln. Erklären Sie insbesondere auch die rekursive Problemreduktion. % Sortieren durch Einfügen inssort([], []). inssort([K|R], L) :- inssort(R, M), ins(K, M, L). %Test ?- inssort([kain, abel, eva, adam], L). L = [abel, adam, eva, kain] ; No
Sortierprogramm % ASCII-Listen vergleichen kleiner([], L) :- L \= []. kleiner([K|R], [K1|R1]) :- K < K1. kleiner([K|R], [K1|R1]) :- K = K1, kleiner(R, R1). % Atome vergleichen vor(A, B) :- name(A, LA), name(B, LB), kleiner(LA, LB). % Einfügen ins(E, [], [E]). ins(E, [E|R], [E | [E |R]]). ins(E, [K|R], [E | [K |R]]) :- vor(E, K). ins(E, [K|R], [K|M]) :- vor(K, E), ins(E, R, M). % Sortieren durch Einfügen inssort([], []). inssort([K|R], L) :- inssort(R, M), ins(K, M, L).
Anwendung: Formale Sprachen Teil 4 Anwendung: Formale Sprachen
Wortproblem Parser aabbcc S aSBC S aBC CB BC aB ab bB bb bC bc cC cc Parser yes
Worterzeugung aabbcc S aSBC S aBC CB BC aB ab bB bb bC bc cC cc S aSBC aaBCBC aaBBCC aabBCC aabbCC aabbcC aabbcc yes
Repräsentation der Grammatik S aSBC S aBC CB BC aB ab bB bb bC bc cC cc startsymbol([vS]). produktion([vS], [a,vS,vB,vC]). produktion([vS], [a,vB,vC]). produktion([vC,vB], [vB,vC]). produktion([a,vB], [a,b]). produktion([b,vB], [b,b]). produktion([b,vC], [b,c]). produktion([c,vC], [c,c]).
Ableitungsschritt Spezifikation: ableitungsschritt/2 S aSBC aaB(CB)C aaB(BC)C aabBCC aabbCC aabbcC aabbcc CB BC Spezifikation: ableitungsschritt/2 ableitungsschritt(AltesWort, NeuesWort) gilt in der Modellwelt, wenn NeuesWort aus AltesWort entsteht, indem ein Teilwort mit Hilfe einer Produktion ersetzt wird. Z. B.: ableitungsschritt([a,a,vB,vC,vB,vC], [a,a,vB,vB,vC,vC])
Ableitungsschritt S aSBC aaB(CB)C aaB(BC)C aabBCC aabbCC aabbcC aabbcc CB BC ableitungsschritt(AltesWort, NeuesWort) :- produktion(L,R), append(L,RestWort,AltesWort), append(R,RestWort,NeuesWort). ableitungsschritt([B|AltesWort], [B|NeuesWort]) :- ableitungsschritt(AltesWort, NeuesWort).
Ableitungskette Spezifikation: ableitungskette/2 S aSBC aaBCBC aaBBCC aabBCC aabbCC aabbcC aabbcc Spezifikation: ableitungskette/2 ableitungskette(NeuesWort, AltesWort) gilt in der Modellwelt, wenn NeuesWort sich aus AltesWort mit Hilfe von Ableitungsschritten erzeugen lässt. Z. B.: ableitungskette([a,a,b,b,c,c], [vS])
Suche im Ableitungsbaum aabbcc aaBbcc aabBcc aabbCc aabbcC aaBbcc ... ... aabbCC aaBbCc aabBCC aaBBCC aaBCBC aSBC S
Ableitungskette S aSBC aaBCBC aaBBCC aabBCC aabbCC aabbcC aabbcc ableitungskette(NeuesWort, AltesWort) :- NeuesWort = AltesWort. ableitungskette(NeuesWort, AltesWort) :- ableitungsschritt(ZwischenWort, NeuesWort), ableitungskette(ZwischenWort, AltesWort).
Ableitung ableitung(Wort) :- ableitungskette(Wort, S), startsymbol(S). S aSBC aaBCBC aaBBCC aabBCC aabbCC aabbcC aabbcc ableitung(Wort) :- ableitungskette(Wort, S), startsymbol(S).
Ausgabe der Ableitungskette ableitungsschritt(AltesWort, L, R, NeuesWort) :- produktion(L,R), append(L,B,AltesWort), append(R,B,NeuesWort). ableitungsschritt([E|AltesWort], L, R, [E|NeuesWort]) :- ableitungsschritt(AltesWort, L, R, NeuesWort). ableitungskette(NeuesWort, AltesWort,[]) :- AltesWort = NeuesWort. ableitungskette(NeuesWort, AltesWort, [regel(L,R), ZwischenWort |A]) :- ableitungsschritt(ZwischenWort, L, R, NeuesWort), ableitungskette(ZwischenWort, AltesWort, A. ableitung(Wort) :- ableitungskette(Wort, S, A), startsymbol(S), write(A).
Ausgabe der Ableitungskette ?- ableitung([a, a,b, b, c, c]). [ regel([c, vC], [c, c]), [a, a, b, b, c, vC], regel([b, vC], [b, c]), [a, a, b, b, vC, vC], regel([b, vB], [b, b]), [a, a, b, vB, vC, vC], regel([a, vB], [a, b]), [a, a, vB, vB, vC, vC], regel([vC, vB], [vB, vC]), [a, a, vB, vC, vB, vC], regel([vS], [a, vB, vC]), [a, vS, vB, vC], regel([vS], [a, vS, vB, vC]), [vS] ] Yes
Ausgabe aller Ableitungsversuche ableitungsschritt(AltesWort, L, R, NeuesWort) :- produktion(L,R), append(L,B,AltesWort), append(R,B,NeuesWort). ableitungsschritt([E|AltesWort], L, R, [E|NeuesWort]) :- ableitungsschritt(AltesWort, L, R, NeuesWort). ableitungskette(NeuesWort, AltesWort,[]) :- AltesWort = NeuesWort. ableitungskette(NeuesWort, AltesWort, [regel(L,R), ZwischenWort |A]) :- ableitungsschritt(ZwischenWort, L, R, NeuesWort), ableitungskette(ZwischenWort, AltesWort, A, write([regel(L,R), ZwischenWort |A]), nl. ableitung(Wort) :- ableitungskette(Wort, S, _), startsymbol(S).
Anwendung: While-Interpreter Teil 5 Anwendung: While-Interpreter
While-Interpreter Interpreter {b: 2; u: 5} BEGIN p := 1; WHILE u > 0 DO BEGIN IF u mod 2 = 1 THEN BEGIN u := u – 1; p := p * b; END; u := u div 2; b := b* b; END END Interpreter {b: 256; u: 0; p: 32}
While-Programme Wiederholung Fallunterscheidung Sequenzbildung BEGIN p := 1; WHILE u > 0 DO BEGIN IF u mod 2 = 1 THEN BEGIN u := u – 1; p := p * b; END; u := u div 2; b := b* b; END END Wiederholung Fallunterscheidung Sequenzbildung Wertzuweisung
Interpreter-Prädikat Ausgangs-zustand {b: 2; u: 5} BEGIN p := 1; WHILE u > 0 DO BEGIN IF u mod 2 = 1 THEN BEGIN u := u – 1; p := p * b; END; u := u div 2; b := b* b; END END While-Programm Interpreter End- zustand {b: 256; u: 0; p: 32} ausfuehren(+Programm, +Ausgangszustand, -Endzustand)
Problemvereinfachung Ausgangs-zustand {x: 2; y: 5} BEGIN z := x; x := y; y := z END Zuweisungs-programm Interpreter End- zustand {x: 5; y: 2; z: 5} Wir betrachten zunächst nur sehr einfache Programme: Sequenzen von Zuweisungen vom Typ <Var> := <Var>.
Variablenzustände Interpreter Ausgangs-zustand Zuweisungs-programm {x: 2; y: 5} BEGIN z := x; x := y; y := z END Zuweisungs-programm Interpreter End- zustand {x: 5; y: 2; z: 5} Repräsentation von Variablenzuständen: [wert(x, 2), wert(y, 5)] % Ausgangszustand [wert(x, 5), wert(y, 2), wert(z, 5)] % Endzustand Liste mit Termen
Variablenzustände Interpreter Ausgangs-zustand Zuweisungs-programm {x: 2; y: 5} BEGIN z := x; x := y; y := z END Zuweisungs-programm Interpreter End- zustand {x: 5; y: 2; z: 5} Spezifikation der Prädikate varWert(+Variable, +Zustand, -Variablenwert) ?- varWert(y, [wert(x, 2), wert(y, 5)], W). W = 5
Variablenzustände Interpreter Ausgangs-zustand Zuweisungs-programm {x: 2; y: 5} BEGIN z := x; x := y; y := z END Zuweisungs-programm Interpreter End- zustand {x: 5; y: 2; z: 5} Spezifikation der Prädikate neuerZustand(+Variable, +Wert, +ZAlt, -ZNeu) ?- neuerZustand(y, 4, [wert(x, 2), wert(y, 5)], Z). Z = [wert(x, 2), wert(y, 4)]
Variablenzustände Interpreter Ausgangs-zustand Zuweisungs-programm {x: 2; y: 5} BEGIN z := x; x := y; y := z END Zuweisungs-programm Interpreter End- zustand {x: 5; y: 2; z: 5} Spezifikation der Prädikate neuerZustand(+Variable, +Wert, +ZAlt, -ZNeu) ?- neuerZustand(z, 2, [wert(x, 2), wert(y, 5)], Z). Z = [wert(x, 2), wert(y, 5), wert(z, 2)]
Variablenzustände Problemreduktionen: varWert(u, [], 'undefiniert'). varWert(x, [wert(x, W) | _R], W). varWert(y, [wert(x, 2) | R], W) :- varWert(x, R, W). Fakten und Regeln: varWert(_, [], 'undefiniert'). varWert(V, [wert(V, W) | _R], W). varWert(V, [wert(X, _W) | R], W) :- V \= X, varWert(V, R, W).
Variablenzustände Problemreduktionen: neuerZustand(z, 2, [], [wert(z, 2)]). neuerZustand(y, 4, [wert(y, 5) | R], [wert(y, 4) | R]). neuerZustand(y, 4, [wert(x, 2) | R], [wert(x, 2) | RNeu]) :- neuerZustand(y, 4, R, RNeu). Fakten und Regeln: neuerZustand(V, W, [], [wert(V, W)]). neuerZustand(V, W, [wert(V, _) | R], [wert(V, W) | R]). neuerZustand(V, W, [wert(X, WAlt) | R], [wert(X, WAlt) | RNeu]) :- V \= X, neuerZustand(V, W, R, RNeu).
Zuweisungsinterpreter Ausgangs-zustand {x: 2; y: 5} BEGIN z := x; x := y; y := z END Zuweisungs-programm Interpreter End- zustand {x: 5; y: 2; z: 5} Repräsentation von primitiven Zuweisungsprogrammen: [let(z, x), let(x, y), let(y, z)] % Zuweisungssequenz Liste mit Termen
Zuweisungsinterpreter Ausgangs-zustand {x: 2; y: 5} BEGIN z := x; x := y; y := z END Zuweisungs-programm Interpreter End- zustand {x: 5; y: 2; z: 5} Spezifikation der Prädikate ausfuehren(+Programm, +ZAlt, -ZNeu) ?- ausfuehren([let(z,x), let(x,y), let(y,z)], [wert(x,2), wert(y,5)], Z). Z = [wert(x,5), wert(y,2), wert(z,2)]
Zuweisungsinterpreter Fakten und Regeln: % Zuweisung ausführen ausfuehren(let(X, Y), ZAlt, ZNeu) :- varWert(Y, ZAlt, W), neuerZustand(X, W, ZAlt, ZNeu). % Sequenz ausführen ausfuehren([], ZAlt, ZAlt). ausfuehren([Anw | R], ZAlt, ZNeu) :- ausfuehren(Anw, ZAlt, Z), ausfuehren(R, Z, ZNeu).
Zuweisungsinterpreter Testprogramm: testprogramm1 :- ausfuehren([let(z, x), let(x, y), let(y, z)], [wert(x,2), wert(y,5)], Z), write(Z). Programmtest: ?- testprogramm1. [wert(x, 5), wert(y, 2), wert(z, 2)]
Terminterpreter Interpreter Ausgangs-zustand Zuweisungs-programm {x: 2; y: 5} BEGIN x := x-y; y := x+y; x := y-x END Zuweisungs-programm Interpreter End- zustand {x: 5; y: 2} Spezifikation der Prädikate termWert(+Term, +Zustand, -Wert) ?- termWert(x-y, [wert(x, 2), wert(y, 5)], W). W = -3
Terminterpreter Fakten und Regeln: termWert(V, _Z, V) :- integer(V). termWert(V, Z, W) :- atom(V), varWert(V, Z, W). termWert(T1 + T2, Z, W) :- termWert(T1, Z, W1), termWert(T2, Z, W2), W is W1+W2. ... termWert(-T, Z, W) :- termWert(T, Z, W1), W is -W1.
Terminterpreter Fakten und Regeln: % Zuweisung ausführen ausfuehren(let(X, T), ZAlt, ZNeu) :- termWert(T, ZAlt, W), neuerZustand(X, W, ZAlt, ZNeu). % Sequenz ausführen ausfuehren([], ZAlt, ZAlt). ausfuehren([Anw | R], ZAlt, ZNeu) :- ausfuehren(Anw, ZAlt, Z), ausfuehren(R, Z, ZNeu).
Terminterpreter Testprogramm: testprogramm2 :- ausfuehren([let(x, x-y), let(y, x+y), let(x, y-x)], [wert(x,2), wert(y,5)], Z), write(Z). Programmtest: ?- testprogramm2. [wert(x, 5), wert(y, 2)]
Anweisungsinterpreter Ausgangs-zustand {x: 2; y: 5} IF x > y THEN betrag := x – y ELSE betrag := y – x Programm Interpreter End- zustand {x: 5; y: 2; betrag: 3} Spezifikation der Prädikate ausfuehren(+Programm, +ZAlt, -ZNeu) ?- ausfuehren( if(x > y, let(betrag, x-y), let(betrag, y-x)), [wert(x,2), wert(y,5)], Z ). Z = [wert(x, 2), wert(y, 5), wert(betrag, 3)]
Anweisungsinterpreter Ausgangs-zustand {b: 2; n: 3, p: 1} WHILE n > 0 DO BEGIN p := p*b; n := n-1 END Programm Interpreter End- zustand {b: 2; n: 3, p: 8} Spezifikation der Prädikate ausfuehren(+Programm, +ZAlt, -ZNeu) ?- ausfuehren( while(n > 0, [let(p, p*b), let(n, n-1)]), [wert(b,2), wert(n,3), wert(p,1)], Z ). Z = [wert(b, 2), wert(n, 0), wert(p, 8)]
Anweisungsinterpreter Ausgangs-zustand {x: 2; y: 5} IF x > y THEN betrag := x – y ELSE betrag := y – x Programm Interpreter End- zustand {x: 5; y: 2; betrag: 3} Spezifikation der Prädikate booleWert(+Term, +Zustand) ?- booleWert(x > y, [wert(x, 2), wert(y, 5)]). No
Anweisungsinterpreter booleWert(T1 = T2, Z) :- termWert(T1, Z, W1), termWert(T2, Z, W2), W1 =:= W2. booleWert(T1 =\= T2, Z) :- termWert(T1, Z, W1), termWert(T2, Z, W2), W1 =\= W2. booleWert(T1 < T2, Z) :- termWert(T1, Z, W1), termWert(T2, Z, W2), W1 < W2. booleWert(T1 > T2, Z) :- termWert(T1, Z, W1), termWert(T2, Z, W2), W1 > W2. booleWert(T1 =< T2, Z) :- termWert(T1, Z, W1), termWert(T2, Z, W2), W1 =< W2. booleWert(T1 >= T2, Z) :- termWert(T1, Z, W1), termWert(T2, Z, W2), W1 >= W2.
Anweisungsinterpreter ausfuehren(let(X, T), ZAlt, ZNeu) :- termWert(T, ZAlt, W), neuerZustand(X, W, ZAlt, ZNeu). ausfuehren([], ZAlt, ZAlt). ausfuehren([Anw | R], ZAlt, ZNeu) :- ausfuehren(Anw, ZAlt, Z), ausfuehren(R, Z, ZNeu). ausfuehren(if(Bed, Anw1, _Anw2), ZAlt, ZNeu) :- booleWert(Bed, ZAlt), ausfuehren(Anw1, ZAlt, ZNeu). ausfuehren(if(Bed, _Anw1, Anw2), ZAlt, ZNeu) :- not(booleWert(Bed, ZAlt)), ausfuehren(Anw2, ZAlt, ZNeu). ausfuehren(while(Bed, Anw), ZAlt, ZNeu) :- booleWert(Bed, ZAlt), ausfuehren(Anw, ZAlt, Z), ausfuehren(while(Bed, Anw), Z, ZNeu). ausfuehren(while(Bed, _Anw), ZAlt, ZAlt) :- not(booleWert(Bed, ZAlt)).
Anweisungsinterpreter Testprogramm: testprogramm5 :- ausfuehren( [let(p,1), while(u > 0, [if(u:2 = 1, [let(u, u-1), ... % siehe oben [wert(b,2), wert(u,5)], Z), write(Z). Programmtest: ?- testprogramm5. [wert(b, 256), wert(u, 0), wert(p, 32)]
Literaturhinweise Uwe Schöning: Logik für Informatiker. BI-Wissenschaftsverlag 1987. Gerhard Röhner: Informatik mit Prolog. Hessisches Landesinstitut für Pädagogik 2002. (HeLP Best.-Nr.: 06000). Rüdeger Baumann: PROLOG Einführungskurs. Klett-Verlag 1991. H. M. Otto: ProLog-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 – Ein Einstieg in die Algorithmik. Handreichung zum Lehrplan Informatik 1995.