Fortgeschrittenes Programmieren: Einführung in Prolog
Transcription
Fortgeschrittenes Programmieren: Einführung in Prolog
Fortgeschrittenes Programmieren: Einführung in Prolog Bernhard Schröder 14. Februar 2002 Inhaltsverzeichnis 1 Zum Anfang 1.1 Was ist Prolog? . . . . . . . . . . . . . . . . . . . . . . . . . . 1.2 Warum ist Prolog in Linguistik und Logik interessant? . . . . 1.3 Wo finde ich einen Prolog-Interpreter? . . . . . . . . . . . . . 3 3 3 4 2 Programmierparadigmen 2.1 Idee des logischen Programmierens . . . . . . . . . . . . . . . 2.2 Zu Prolog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 4 4 3 Eine erste Prolog-Wissensbasis 3.1 Konsultieren von Prolog-Programmen . . . . . . . . . . . . . . 3.1.1 Wechseln von Verzeichnissen unter SWI-Prolog . . . . 3.1.2 Ansehen von Verzeichnisinhalten . . . . . . . . . . . . 5 6 7 7 4 Syntax 4.1 Atome . . . . . . . . . . . . . . . . . . . . . . . . 4.2 Zahlen . . . . . . . . . . . . . . . . . . . . . . . . 4.3 Variablen . . . . . . . . . . . . . . . . . . . . . . 4.4 Komplexe Strukturen . . . . . . . . . . . . . . . . 4.5 Einige Metaprädikate zum Testen von Termtypen 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 8 9 9 10 11 5 Der 5.1 5.2 5.3 5.4 5.5 5.6 5.7 5.8 5.9 5.10 Prolog-Resolutionskalkül Der Prolog-Beweisalgorithmus: Aussagenlogischer Fall . Tracing . . . . . . . . . . . . . . . . . . . . . . . . . . Unifikation . . . . . . . . . . . . . . . . . . . . . . . . . Exkurs: Kodier-“Stile” . . . . . . . . . . . . . . . . . . Variablenersetzungen und Unifikatoren . . . . . . . . . Der Herbrand-Algorithmus . . . . . . . . . . . . . . . . Der occurs-check . . . . . . . . . . . . . . . . . . . . . Die anonyme Variable . . . . . . . . . . . . . . . . . . Der Prolog-Beweisalgorithmus: Prädikatenlogischer Fall Eine Notationskonvention für Prädikate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 13 16 19 22 25 27 30 30 30 32 6 Rekursion 34 6.1 Dokumentation von Prädikatsdefinitionen . . . . . . . . . . . . 42 7 Listen 42 8 Operatoren 48 9 Arithmetische Operationen 51 10 Vordefinierte Prädikate 10.1 Vergleichsoperationen . . . . 10.2 Arithmetische Prädikate . . 10.3 Metaprädikate . . . . . . . . 10.4 Kontrollprädikate . . . . . . 10.5 Listenprädikate . . . . . . . 10.6 Prädikate mit Hilfe-Funktion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52 52 53 54 54 55 55 A Beispielprogramme A.1 maier.pl . . . . . A.2 sokrates.pl . . . . A.3 bonn.pl . . . . . A.4 raetsel.pl . . . . . A.5 weg.pl . . . . . . A.6 puppe.pl . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55 55 57 57 58 59 60 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . B Formalia 60 B.1 Spezielle Prolog-Übungszeiten . . . . . . . . . . . . . . . . . . 61 2 C Seminarplan 61 D Einrichten des XEmacs für SWI-Prolog 63 E Links 63 1 Zum Anfang 1.1 Was ist Prolog? Prolog ist eine auf einem Ausschnitt der Prädikatenlogik erster Stufe (der sog. Hornklausellogik) basierende deklarativ orientierte Programmiersprache, d.h. Prolog-Programme bestehen im wesentlichen aus einer Menge (prädikatenlogischer) Aussagen über den zu beschreibenden Bereich, einer sogenannten Wissensbasis. Für gegebene prädikatenlogische Aussagen (der Hornklausellogik) entscheidet ein Prolog-Interpreter, ob diese Aussagen aus der Wissenbasis folgen oder nicht. Das Entscheidungsverfahren beruht auf einem Resolutionskalkül. 1.2 Warum ist Prolog in Linguistik und Logik interessant? Eine Reihe von Gründen machen Prolog zu einer geeigneten Programmiersprache in verschiedensten Bereichen der syntaktischen und semantischen Verarbeitung natürlicher und formaler Sprachen, darunter die folgenden: • Prolog eignet sich durch seine deklarative Orientierung zum Einsatz in Bereichen, in denen es um formal-semantische Repräsentation und Wissensverarbeitung geht. • Komplexe Datenstrukturen, wie sie zur Darstellung syntaktischer und semantischer Strukturen von natürlichen und formalen Sprachen erforderlich sind, sind in Prolog leicht aufzubauen und zu verarbeiten. • Grammatiken im DCG-Formalismus können direkt als Prolog-Programme interpretiert werden, Prolog hat gewissermaßen einen einfachen eingebauten Parser und Generator für solche Grammatiken; alternative Parsing- und Generierungsstrategien können auf dieser Grundlage leicht implementiert werden. 3 • Zudem ist in Prolog eine Termunifikationsoperation eingebaut, auf die die in Unifikationsgrammatiken benötigte Unifikationsoperation auf Merkmalstrukturen zurückgeführt werden kann. 1.3 Wo finde ich einen Prolog-Interpreter? Benutzern von Windows9x, Windows ME, Windows NT und Windows 2000empfehle ich den freien SWI-Prolog-Interpreter, dieser kann unter dem URL http://www.swi.psy.uva.nl/projects/SWI-Prolog/download.html heruntergeladen werden. Linux-Versionen von SWI-Prolog werden in der Regel mit Linux-Distributionen mitgeliefert. 2 Programmierparadigmen • Prozedurale Programmiersprachen • Funktionale Programmiersprachen • Objektorientierte Programmiersprachen • Logikbasierte Programmiersprachen 2.1 Idee des logischen Programmierens Ein “Programm”besteht aus Fakten und Regeln (singulären Fakten und allgemeinen Fakten, Wissensbasis). Über den Interpreter können diesem Programm Fragen gestellt werden. Der Interpreter versucht die Fragen aufgrund der Wissensbasis zu beantworten. 2.2 Zu Prolog • In den frühen 70er Jahren Entwicklung von Prolog durch Colmerauer et al. an der Universität Marseilles-Aix • Interpreter-Sprache • Hornklausellogik 4 3 Eine erste Prolog-Wissensbasis Prolog-Programmdateien, die im Seminar benötigt werden, befinden sich auf den pav-Rechnern unter Linux im Verzeichnis /pool stud/bsh LV/WS0102/Prolog/, das per ftp erreichbar ist unter ftp://[email protected]/pool stud/bsh LV/WS0102/Prolog/ wobei studxxx durch Ihren Benutzernamen zu ersetzen ist. Kopieren Sie nun die Datei maier.pl in Ihr Home-Verzeichnis oder ein Unterverzeichnis Ihres Home-Verzeichnisses. Sehen Sie sich die Fakten zur Familie Maier an. Wechseln Sie nun in einem Linux-Terminal in das Verzeichnis, in dem sich dir Prolog-Datei befindet und starten Sie dort SWI-Prolog mit dem Befehl pl am Linux-Prompt, konsultieren Sie das Prolog-Programm maier.pl mit der Prolog-Anfrage ?- consult(maier). und stellen Sie anschließend Anfragen wie ?- hund(fido). ?- mutter(X,uli). ?- vater(X,gitte), vater(X,uli). ?- vater(Wer,Wessen). ?- schenkt(gerd,X,d318). Beachten Sie, dass in Fällen, bei denen mehrere Antworten möglich sind, die Alternativen durch Eingabe eines Semikolon nach der Ausgabe einer Antwort erfragt werden können. Geben Sie diese Fragen auch natürlichsprachlich wieder. Fügen Sie der Wissensbasis weitere Fakten hinzu durch Eingabe von ?- asserta(beliebt(karl)). ?- asserta(person(karl)). Fügen Sie eine weitere Regel durch Eingabe von 5 ?- asserta((kennt(X,Y) :- person(X), beliebt(Y))). hinzu. Fragen Sie nun ?- kennt(uli,Wen). ?- kennt(fido,Wen). Fügen Sie eine weitere Regel hinzu, die besagt, dass jeder Hund jede beliebte Person kennt. Stellen Sie die letzte Anfrage erneut. Entfernen Sie das Faktum beliebt(karl) aus der Wissensbasis mit ?- retract(beliebt(karl)). Stellen Sie nun noch einmal die letztgenannten Anfragen. Beenden Sie Prolog mit ?- halt. 3.1 Konsultieren von Prolog-Programmen ?- consult(maier). ?- [maier]. ?- consult(’maier.pl’). ?- [’maier.pl’]. ?- consult(’~/prolog/maier’). ?- consult(’~/prolog/maier.pl’). ?- [’~/prolog/maier’]. ?- [’~/prolog/maier.pl’]. 6 3.1.1 Wechseln von Verzeichnissen unter SWI-Prolog ?- cd(prolog). ?- cd(’~/prolog’). ?- cd(’~’). ?- cd. ?- pwd. Das Symbol ~ steht nur auf UNIX-Systemen für das eigene Home-Verzeichnis. Das aktuelle Laufwerk wechselt man auf MS-Windows-Systemen unter SWI-Prolog mit der aus folgenden Beispielen ersichtlichen Syntax: ?- cd(’h:/prolog´). ?- cd(’h:’). 3.1.2 Ansehen von Verzeichnisinhalten ?- ls. Übung 3.1 1. Legen Sie unter neuem Namen, z.B. maier2.pl, eine Kopie der Datei maier.pl an. 2. Erweitern Sie die Wissensbasis um Fakten und Regeln, darunter auch für folgende Sachverhalte: (a) Lore und Gerd sind verheiratet. (b) X ist Großvater von Y, falls X der Vater eines Z ist und Z der Vater von Y ist. (c) In welchen weiteren Fällen kann eine Großvaterrelation bestehen? (d) Wann besteht die Großmutterrelation? (e) Führen Sie neue Personen für die Großeltern ein. (f ) Lore mag Gerd, und Gerd mag Lore, Gitte mag Fido. 7 (g) Führen Sie eine Geschwisterrelation ein, definieren Sie sie aufgrund der Vater- und Mutterrelationen. Dabei können Sie in kauf nehmen, dass Personen auch “Geschwister” von sich selbst sind. (h) Definieren Sie eine Bruder- und eine Schwesterrelation aufgrund der bereits vorhandenen Relationen. Hier gilt dieselbe Einschränkung wie bei der Geschwisterrelation. (i) Führen Sie weitere Nachkommen für die Großeltern ein. (j) Definieren Sie eine Onkel- und eine Tantenrelation. Dabei können Sie in kauf nehmen, dass diese Relation ähnlich wie oben die Geschwisterrelation “übergeneriert”, dass sie nämlich im vorliegenden Fall auch Eltern fälschlich als Onkel und Tanten einstuft, also genauer eine Onkel-oder-Vater- bzw. Tanten-oder-Mutter-Relation ist. 4 Syntax 4.1 Atome Es gibt 4 Arten von Atomen in Prolog: 1. Zeichenketten, die aus Buchstaben, Ziffern und dem Unterstrich bestehen und mit einem Kleinbuchstaben beginnen; 2. Zeichenketten, die ausschließlich aus Sonderzeichen bestehen; 3. [] und {}; 4. Zeichenketten, die in Hochkommata ´...´ eingeschlossen sind. Beispiele: fido microprozessor x4711 x47_11 8 ’Dies ist eine ’’Zeichenkette’’ hdjk’ :, ’,’ >= ’ ’ 4.2 Zahlen 012345 632708 3.14 3.14E3 3.14E+3 3.14E-3 Zahlen und Atome werden auch als atomare Strukturen bezeichnet. 4.3 Variablen Variablen sind Zeichenketten, die mit einem Großbuchstaben oder einem Unterstrich beginnen und ausschließlich aus Buchstaben, Ziffern und Unterstrichen bestehen. X X4711a 9 Wer Hund HundeHuette _ _fido _Hund _ heißt auch anonyme Variable. Die anonyme Variable wird immer dann verwendet, wenn der einzusetzende Wert nicht relevant ist, also als Platzhalter für eine Argumentstelle. Die Anfrage ?- vater(X,_). ergibt als Lösung für die Variable X alle Personen, die Vater eines Kindes sind, die Kinder als Lösungen für die anonyme Variable werden jedoch nicht angezeigt. Werden andere mit Unterstrich beginnende Variablen als die anonyme Variable in Anfragen verwendet, so zeigen viele Prolog-Interpreter – so auch SWI-Prolog – deren Lösung nicht an. Die Anfrage ?- vater(X,_Z), mutter(lore,_Z). ergibt als Lösungen für X den Vater oder Väter an, die mit Lore ein gemeinsames Kind oder gemeinsame Kinder haben; dabei werden die Lösungen für _Z, also die gemeinsamen Kinder, aber nicht angezeigt. 4.4 Komplexe Strukturen Komplexe Strukturen bestehen aus einem Atom als Funktor und einer Reihe von Argumenten, die in runde Klammern eingeschlossen sind und durch Kommata voneinander getrennt sind. Die öffnende runde Klammer muß unmittelbar hinter dem Funktor stehen. Argumente können atomare Strukturen, Variablen oder komplexe Strukturen sein. 10 person(gitte) liebt(lore, gitte) liebt(lore,vater(gerd)) >=(5,6) &=(lore,**) liste_x(e1, e2, e3, e4) ’hallo’(peter) 4.5 Einige Metaprädikate zum Testen von Termtypen var(Arg) testet, ob Arg uninstantiiert ist nonvar(Arg) testet, ob Arg wenigstens partiell instantiiert ist atomic(Arg) testet, ob Arg eine atomare Struktur ist atom(Arg) testet, ob Arg ein Atom ist integer(Arg) testet, ob Arg eine Integer-Zahl ist number(Arg) testet, ob Arg eine Integer- oder Real-Zahl ist Übung 4.1 1. Entscheiden Sie, ob die folgenden Klauseln zutreffen oder nicht. Überprüfen Sie Ihr Ergebnis mit dem Prolog-Interpreter. atomic(werda) atomic(Z) var(Z) atomic(a(B)) var(a(B)) 11 nonvar(a(B)) atom(312) atomic(312) atom(>=) atomic(’kette’) integer(3.14) number(3) number(3.14) integer(3.0) 2. Klassifizieren Sie die folgenden Terme als atomare, komplexe Terme oder Variablen. Fido nummer_24 hallo_leute hallo(leute) Leute x Y 314 12 *&(X,*=) *** X_X x(X) 5 Der Prolog-Resolutionskalkül 5.1 Der Prolog-Beweisalgorithmus: Aussagenlogischer Fall Die Eingabe einer Klausel, z.B. a, an der Prolog-Eingabeaufforderung, kann als Aufforderung verstanden werden, die Beweisbarkeit von a zu überprüfen. Yes heißt: a ist beweisbar, No: a ist nicht beweisbar. Die Überprüfung geschieht durch den Algorithmus callAL : Algorithmus P-5-1 (callAL (a) (indeterministisch)) Wähle eine Klausel, die ausschließlich aus a besteht, oder die Form a : −b1 , ...bn hat, in der Wissensbasis. Falls keine derartige Klausel existiert, scheitert callAL (a). 1. Falls die Klausel ausschließlich aus a besteht, gelingt callAL (a). 2. Falls die Klausel die Form a: −b1 , ...bn hat, rufe callAL (b1 ), . . . callAL (bn ) auf; callAL (a) gelingt, wenn alle Aufrufe callAL (b1 ), ... callAL (bn ) gelingen; anderenfalls scheitert callAL (a). Der oben dargestellte Algorithmus ist indeterministisch, da er nicht vorschreibt, welche Klausel aus der Wissensbasis gewählt wird, wenn es mehrere Kandidaten gibt. Wenn immer die “richtige” Wahl getroffen wird, liefert er für beweisbare Klauseln auch immer die richtige Antwort Yes. In Prolog ist allerdings die Wahl der Klausel festgelegt: Es wird immer die erste Klausel aus der Wissensbasis gewählt, die ausschließlich aus a besteht, oder die Form a :- b1 , . . . bn hat. Dies kann natürlich die falsche Wahl sein, wie in 13 Programm P-5-1 a :- b. a :- c. c. Hier gelingt der Beweis von a bei Wahl der zweiten Klausel, scheitert jedoch bei Wahl der ersten Klausel. Der Algorithmus muß also noch um einen Backtracking-Mechanismus ergänzt werden, der eine Revision der Wahl der Klausel ermöglicht. Algorithmus P-5-2 (callAL (a) (deterministisch)) 1. Nimm die erste Klausel, die ausschließlich aus a besteht, oder die Form a: −b1 , ...bn hat, in der Wissensbasis. Falls keine derartige Klausel existiert, scheitert callAL (a). 2. (a) Falls die Klausel ausschließlich aus a besteht, gelingt callAL (a). (b) Falls die Klausel die Form a: −b1 , ...bn hat, rufe callAL (b1 ), . . . callAL (bn ) in dieser Reihenfolge auf; callAL (a) gelingt, wenn alle Aufrufe callAL (b1 ), ... callAL (bn ) gelingen; sobald ein Aufruf scheitert gehe nach 3. 3. Revidiere die letzte Wahl einer Klausel in der Wissensbasis, indem die nächste geeignete Klausel in der Wissensbasis gewählt wird. Falls keine derartige Klausel existiert, scheitert callAL (a). Andernfalls verfahre wie nach der vorangehenden Wahl (Schritt 2). Beim Ablauf des Beweisalgorithmus werden meist vier Ports unterschieden: call Aufruf des callAL -Algorithmus exit Gelingen eines Aufrufs des callAL -Algorithmus fail Scheitern eines Aufrufs des callAL -Algorithmus 14 Abbildung 1: Beweis von a mit P-5-1 15 redo Suchen der nächsten alternativen Klausel (vgl. 3) Abbildung 1 zeigt den Beweis von a mit P-5-1. Für das Programm Programm P-5-2 a :- c. a :- b. c. zeigt Abbildung 2 den Ablauf. Schließlich demonstriert für das Programm Programm P-5-3 a :- c, d. a :- b. a :- c, e. c. e. Abbildung 3 den Ablauf. 5.2 Tracing Den nach Eingabe einer Anfrage ablaufenden Beweisprozess kann man mithilfe der Ablaufverfolgung oder des Tracing verfolgen. Dazu kann man unter SWI-Prolog ?- trace. an der Prolog-Eingabeaufforderung eingeben. Bei der als nächstes eingebenen Anfrage ist dann das Tracing eingeschaltet. Beim Tracing hält Prolog standardmäßig an allen vier Ports. Übung 5.1 Beschreiben Sie, was beim Aufruf von raetsel in raetsel.pl geschieht. Zeichnen Sie ein Ablaufdiagramm. 16 17 Abbildung 2: Beweis von a mit P-5-2 Abbildung 3: Beweis von a mit P-5-3 18 5.3 Unifikation ?- a = X. X=a ?- b(a,c) = Y. Y=b(a,c) ?- X = Y. X=_12 Y=_12 ?- b(a,c) = b(Z,c). Z=a ?- komplex(B,einfach2) = komplex(einfach1,C). B=einfach1 C=einfach2 ?- a(b(c),d318) = a(X,Z). X=b(c) Z=d318 ?- a(X,Y,Z) = a(Q,U). No ?- a(X,Y,Z) = b(Q,U,R). 19 No ?- a(X,Y,X) = a(b,c,d). No ?- a(X) = X. a(a(a(a(a.... ?- X = Y, Y = Z. X=_13 Y=_13 Z=_13 ?- X = dies, Y = das. X=dies Y=das ?- X = dies, Y = das, X = Y. No. Übung 5.2 Entscheiden Sie, welche der folgenden Unifizierbarkeitsbehauptungen zutreffen: X = dies. X = a(b(c(d))). a(b(c(X))) = a(b(Y)). vater(Q,R) = vater(peter). 20 a(c(Z),Z) = a(c(d),d). a(c(Z),X) = a(c(d),d). a(c(Z),Z) = a(c(d),c). a(c(Z),X) = a(c(d),d), X = peter. Übung 5.3 nen: 1. Entwerfen Sie eine Datenbasis mit folgenden Informatio- (a) Apfelbaum, Stachelbeer- und Himbeerstrauch, Kaktee und Hundsrose sind Pflanzen. (b) Apfel ist die Frucht eines Apfelbaums, Stachelbeere die eines Stachelbeerstrauchs, Himbeere die eines Himbeerstrauchs, Feige die einer Kaktee, Hagebutte die einer Hundsrose. (c) Äpfel, Stachelbeeren, Himbeeren und Feigen sind eßbar. (d) Etwas kann mit der Bezeichnung Obst versehen werden, wenn es eine Pflanze gibt, dessen Frucht es ist, und wenn es eßbar ist. 2. Stellen Sie Fragen wie: (a) Was ist die Frucht der Kaktee? (b) Welche Früchte sind essbar? (c) Die Früchte welcher Pflanzen werden als Obst bezeichnet? 3. Entwerfen Sie eine Städtedatenbank, in der Informationen wie Bonn ist eine Stadt in der Kölner Bucht gespeichert sind. Durch weitere Informationen in der Datenbank soll aber auch der Schluß von dieser Information auf die Information, dass Bonn in NRW liegt, möglich sein. 4. Entwerfen Sie eine zoologische Datenbank, in der Informationen wie Frösche sind Amphibien gespeichert sind. Durch weitere Informationen in der Datenbank soll aber auch der Schluß von dieser Information darauf, dass Frösche Wirbeltiere sind, möglich sein. 21 5. Entwerfen Sie einen Geburtstagskalender, der es Ihnen ermöglicht alle Geburtstage Ihrer Bekannten in einem bestimmten Monat abzufragen. Stellen Sie Fragen wie: (a) Wer hat im Juni Geburtstag? (b) Wer hat am 13. eines Monats Geburtstag? (c) Wann hat Karl Geburtstag? (d) Wer ist 1969 geboren? (e) Welches Problem tritt auf, wenn Sie auch Fragen stellen möchten, wie: Wer hat 10 Tage vor Karl Geburtstag? Wie lässt sich das Problem lösen. Schlagen Sie eine Lösungsstrategie zunächst ohne Implementation vor. 6. Bestimmte Fahrzeugtypen sind durch bestimmte Merkmale charakterisiert, so z.B. Pkw dadurch, dass sie (i.A.) vier Räder haben, motorbetrieben sind, zum Personentransport dienen usw., während Fahrräder (i.A.) zwei Räder haben, einen Pedalantrieb haben, zum Personentransport dienen usw. Entwerfen Sie eine Datenbank, die man befragen kann, welche Merkmale ein bestimmter Fahrzeugtyp, z.B. ein Fahrrad, hat, aber auch, welcher Fahrzeugtyp bestimmte Merkmale hat, z.B. vier Räder zu haben, motorbetrieben zu sein u.ä. 5.4 Exkurs: Kodier-“Stile” In Prolog ist die Realisierung verschiedener Kodier-“Stile” möglich. Man kann die in /* Die Personen in Familie Maier: */ person(lore). person(gerd). person(gitte). person(petra). person(uli). /* Die Frauen: */ weiblich(lore). weiblich(gitte). weiblich(petra). 22 /* Die Männer: */ maennlich(gerd). maennlich(uli). /* Eltern-Kind-Beziehungen */ vater(gerd,gitte). vater(gerd,uli). vater(gerd,petra). mutter(lore,gitte). mutter(lore,uli). gegebenen Informationen auch in einem “datensatzartigen” Stil kodieren als person(lore,weiblich,_,_). person(gerd,maennlich,_,_). person(gitte,weiblich,gerd,lore). person(petra,weiblich,gerd,_). person(lore,weiblich,gerd,lore). Übung 5.4 Nennen Sie Vor- und Nachteile der beiden vorgestellten Programmierstile. Übung 5.5 1. Erstellen Sie eine Datenbasis, die folgende lexikalische Information enthält: (a) Die Wortform Dieb ist ein Substantiv im Genus masculinum und ist der Nominativ Singular des Lemmas Dieb. Außerdem kann Dieb auch der Dativ und Akkusativ Singular sein. (b) Die Wortform Diebes ist ein Substantiv im Genus masculinum und ist der Genitiv Singular des Lemmas Dieb. (c) Die Wortform Diebe ist ein Substantiv im Genus masculinum und ist der Nominativ, Genitiv oder Akkusativ des Lemmas Dieb. (d) Fügen Sie der Datenbasis die analoge Information für die Wortformen der Lemmata Polizist, Polizistin, Tresor und Dokument hinzu. (e) Wie sieht analoge lexikalische Information für den bestimmten (der, die, das) und den unbestimmten (ein, eine) Artikel aus? Fügen Sie diese Information der Datenbasis hinzu. 23 2. Schreiben Sie ein Prädikat substantiv, das überprüft, ob eine gegebene Wortform ein Substantiv ist. 3. Schreiben Sie ein Prädikat lemma, das überprüft, ob eine gegebene Wortform gleichzeitig ein Lemma ist. Auf Dieb sollte das Prädikat zutreffen, nicht aber auf Diebes oder Dieben. 4. Schreiben Sie ein Prädikat kongruenz_det_n, das überprüft, ob ein gegebener Artikel und ein gegebenes Substantiv in Kasus, Numerus und Genus übereinstimmen (KNG-Kongruenz). 5. Schreiben Sie ein Prädikat, das auf alle Wortformen im Akkusativ zutrifft. 6. Schreiben Sie ein Prädikat, das auf alle Wortformen in einem gegebenen Kasus zutrifft. 7. Fragen Sie die Datenbasis nach allen Wortformen im Dativ Plural. 8. Fragen Sie die Datenbasis, ob den mit Dieben kongruiert. 9. Fragen Sie die Datenbasis nach allen kongruierenden Kombinationen von Artikeln und Substantiven im Nominativ. 10. Fragen Sie die Datenbasis nach allen kongruierenden Kombinationen von Artikeln und Substantiven im Akkusativ. 11. Nehmen Sie zu den für Substantive und Artikel analoge Einträge für die Personalpronomina (ich, du, er, sie, es, wir, ihr, sie und Flexionsformen) in Ihre Datenbasis auf. 12. Nehmen Sie die Verbformen komme, kommst, kommt, kommen, kämen, kämst, käme, kämen, kämt, kam, kamst, kam, kamen, kamt mit Angaben zu Person, Numerus, Tempus (Präsens, Präteritum), Modus (Indikativ, Konjunktiv) auf. Beachten Sie, dass eine Reihe von Verbformen mehrere Analysen haben können. 13. Schreiben Sie ein Prädikat kongruenz_pron_verb, das überprüft, ob ein gegebenes Personalpronomen als Subjekt zu einer Verbform passt. du passt beispielsweise zu kommst, nicht aber wir. 24 14. Schreiben Sie ein Prädikat kongruenz_det_n_verb, das überprüft, ob eine gegebene Artikel-Substantiv-Kombination zu einer Verbform passt. der Polizist passt beispielsweise zu kommt, nicht aber die Polizistinnen. 15. Inwiefern können bei dieser Aufgabe unterschiedliche Kodierstile im Sinne von Abschnitt 5.4 verwendet werden. Geben Sie Beispiele. Diskutieren Sie die Vor- und Nachteile der Kodierstile. 5.5 Variablenersetzungen und Unifikatoren Definition D-5-1 (Variablenersetzungsinstanz) Eine Variablenersetzungsinstanz ist ein Paar von Prolog-Termen, derart dass das erste Element, das Substituendum, eine Prolog-Variable und das zweite, das Substitut, ein Prolog-Term ist, der diese Variable nicht enthält. Die Variablenersetzungsinstanz bestehend aus der Variable S und dem Term a wird auch als S ← a geschrieben. Bei der Anwendung einer Variablenersetzungsinstanz S ← a auf einen Prolog-Term werden alle Vorkommen der Variablen S in diesem Term durch a ersetzt. Beispiel 5.1 X ← c(a, b(Y)) ist eine Variablenersetzungsinstanz mit dem Substituendum X und dem Substitut c(a,b(Y)); die Anwendung dieser Variablenersetzungsinstanz auf den Term abc(X, hoch_zwei(mal(X,Y)), usw(Z)) ergibt den Term abc(c(a,b(Y)), hoch_zwei(mal(c(a,b(Y)),Y)), usw(Z)). Definition D-5-2 (Variablenersetzung) Eine Variablenersetzung ist eine Menge von Variablenersetzungsinstanzen, in der keine zwei Variablenersetzungsinstanzen dasselbe Substituendum haben dürfen und kein Substituendum irgendeiner Variablenersetzungsinstanz in dem Substitut derselben oder einer anderen Variablenersetzungsinstanz in dieser Menge auftreten darf. Auch die leere Menge ist eine Variablenersetzung (die leere Variablenersetzung). Bei der Anwendung einer Variablenersetzung σ auf einen Prolog-Term a werden alle in σ enthaltenen Variablenersetzungsinstanzen auf a angewendet. Das Resultat wird auch als σ(a) notiert. Beispiel 5.2 σ = {X ← c(a, b(Y)), Z ← A} ist eine Variablenersetzung. σ(abc(X, hoch zwei(mal(X, Y)), usw(Z))) == abc(c(a, b(Y)), hoch zwei(mal(c(a, b(Y)), Y)), usw(A)) 25 (1) Das doppelte Gleichheitszeichen soll dabei für die Identitätsrelation für Prolog-Terme stehen. Definition D-5-3 (Unifikator) Ein Unifikator zweier Terme a und b ist eine Variablenersetzung σ derart, dass σ(a) == σ(b). Definition D-5-4 (Allgemeinheit) Eine Variablenersetzung σ ist allgemeiner als σ 0 (oder: σ 0 ist spezieller als σ) bzgl. einer Termmenge T gdw es eine Variablenersetzung σ 00 gibt, so dass für alle Terme a ∈ T gilt: σ 00 (σ(a)) == σ 0 (a) Anmerkung: Es ist nach der obigen Definition möglich, dass σ allgemeiner als σ 0 und σ 0 allgemeiner als σ ist. Dies gilt beispielsweise für σ = {X ← A} und σ 0 = {X ← B} bzgl. von Termmengen, in denen weder A noch B vorkommen. Solche Fälle sollen durch die folgende Definition ausgeschlossen werden. Definition D-5-5 (Strikte Allgemeinheit) Eine Variablenersetzung σ ist strikt allgemeiner als σ 0 (oder: σ 0 ist strikt spezieller als σ) bzgl. einer Termmenge T gdw σ allgemeiner als σ 0 bzgl. T , σ 0 aber nicht allgemeiner als σ bzgl. T ist. Definition D-5-6 (Allgemeinster Unifikator) Eine Variablenersetzung σ ist ein allgemeinster Unifikator (most general unifier, mgu) zweier Terme a und b gdw 1. σ Unifikator von a und b ist und 2. es keinen Unifikator σ 0 von a und b gibt, derart, dass σ 0 strikt allgemeiner als σ bzgl. von {a, b} ist. Anmerkung: In der Regel gibt es mehrere allgemeinste Unifikatoren zu einem gegebenen Termpaar. Diese haben allerdings die Eigenschaft, dass die aus der Anwendung der Unifikatoren erzeugten Terme - kürzer: die unifizierten Terme - sich nur in der Benennung der Variablen unterscheiden. Allgemeinste Unifikatoren zu f(A,B) und f(X,Y) sind beispielsweise: {X ← A, Y ← B}, {A ← X, B ← Y} und {X ← G26, Y ← G27, A ← G26, B ← G27}; die jeweiligen unifizierten Ausdrücke f(A,B), f(X,Y) und f(_G26,_G27) unterscheiden sich nur hinsichtlich der Benennung der vorkommenden Variablen. Etwas präziser soll dies im folgenden ausgedrückt werden: 26 Definition D-5-7 (Variablenumbenennung) Eine Variablenumbenennung für eine Termmenge T ist eine Variablenersetzung σ derart, dass für alle Terme a ∈ T gilt: es gibt eine Variablenersetzung σ 0 mit σ 0 (σ(a)) == a. Anmerkung: Eine Variablenumbenennung soll also immer durch eine weitere Variablenersetzung (ebenfalls wieder eine Variablenumbenennung) umkehrbar sein. {A ← X, B ← X} ist also keine Variablenumbenennung für die Termmenge {f(A, B)}, da der aus f(A,B) durch diese Ersetzung resultierende Term f(X,X) durch keine Variablenersetzung in f(A,B) zurücküberführt werden kann. Satz 5.1 Seien σ und σ 0 allgemeinste Unifikatoren zweier Terme a und b. Dann gibt es eine Variablenumbenennung σ 00 , so dass σ 00 (σ(a)) == σ 0 (a) und σ 00 (σ(b)) == σ 0 (b). 5.6 Der Herbrand-Algorithmus Ein allgemeinster Unifikator zu einem Termpaar kann nach dem im Folgenden beschriebenen Herbrand-Algorithmus ermittelt werden:1 Algorithmus P-5-3 (Unifiziere(a,b)) Seien a und b die zu unifizierenden Terme. Dann trifft einer der folgenden Fälle zu: Nichtübereinstimmung 1. a und b sind unterschiedliche atomare Ausdrücke. 2. Einer der beiden Ausdrücke a oder b ist ein atomarer Ausdruck, der andere ein komplexer Term. 3. a und b sind komplexe Strukturen mit unterschiedlichen Funktoren. 4. a und b sind komplexe Strukturen mit einer unterschiedlichen Anzahl an Argumentstellen. In diesen Fällen scheitert die Unifikation. 1 Vgl. [DEDC96, 14 ff]. 27 Positiver occurs-check a ist eine Variable X und b eine komplexe Struktur, die die Variable X enthält. In diesem Fall scheitert die Unifikation. (Dieser Test wird von den meisten Prolog-Interpretern bei der gewöhnlichen Unifikation nicht durchgeführt, vgl. 5.7.) Identitätsbeseitigung a ist derselbe Ausdruck wie b. In diesem Fall gelingt die Unifikation mit dem leeren Unifikator {}. Variablenelimination Es gelten die folgenden Bedingungen: 1. a ist eine Variable X. 2. b ist verschieden von a. 3. b enthält a nicht. (Dieser Test wird auch als negativer occurscheck bezeichnet. Diese Bedingung ist immer erfüllt, wenn der positive occurs-check durchgeführt wurde und scheiterte. Ebenso wie der positive occurs-check wird auch dieser Test von den meisten Prolog-Interpretern bei der gewöhnlichen Unifikation nicht durchgeführt.) In diesem Fall gelingt die Unifikation mit dem Unifikator {X ← b}. (Wenn auch b eine Variable Y ist, geben Prolog-Systeme in der Regel allerdings einen Unifikator {X ← Z, Y ← Z} mit einer noch nicht verwendeten Variable Z zurück.) Swapping b ist eine Variable, a aber nicht. Unifiziere in diesem Fall b und a und gib den Unifikator dieser Unifikation zurück. Splitting a ist eine komplexe Struktur f (a1 , . . . , an ) und b eine komplexe Struktur f (b1 , . . . , bn ) mit einem Funktor f und Termen a1 , . . . , an , b1 , . . . , bn . Unifiziere a1 und b1 . Falls die Unifkation von a1 und b1 scheitert, scheitert die gesamte Unifikation. Ansonsten sei das Ergebnis der Unifikation der Unifikator σ1 . Für alle i mit 1 < i ≤ n führe die folgende Operation durch: • Unifiziere σ1 ◦. . .◦σi−1 (ai ) und σ1 ◦. . .◦σi−1 (bi ). Falls die Unifkation von σ1 ◦· · ·◦σi−1 (ai ) und σ1 ◦· · ·◦σi−1 (bi ) scheitert, scheitert die gesamte Unifikation. Ansonsten sei das Ergebnis der Unifikation der Unifikator σi . 28 Gib σ1 ◦ · · · ◦ σn als Unifkator zurück.2 Beispiel 5.3 Unifiziere f(X,h(T)) und f(g(Y),Y). 1. Splitting: (a) Unifiziere X und g(Y). i. Variablenelimination: Gib {X ← g(Y)} als Unifikator zurück. (b) Unifiziere {X ← g(Y)}(h(T)) und {X ← g(Y)}(Y), also h(T) und Y. i. Swapping: Unifiziere Y und h(T). A. Variablenelimination: Gib {Y ← h(T)} als Unifikator zurück. Gib {Y ← h(T)} als Unifikator zurück. (c) Gib {X ← g(Y)} ◦ {Y ← h(T)}, also {X ← g(h(T)), Y ← h(T)} als Unifikator zurück. Beispiel 5.4 Unifiziere f(X,h(t)) und f(g(Y),h(X)). 1. Splitting: (a) Unifiziere X und g(Y). i. Variablenelimination: Gib {X ← g(Y)} als Unifikator zurück. (b) Unifiziere {X ← g(Y)}(h(t)) und {X ← g(Y)}(h(X)), also h(t) und h(g(Y)). i. Splitting: Unifiziere t und g(Y). A. Nichtübereinstimmung: Unifikation scheitert. Unifikation scheitert. Unifikation scheitert. Die Komposition σ ◦ σ 0 zweier Variablenersetzungen σ und σ 0 ist dabei definiert als diejenige Variablenersetzung, für die gilt: 2 σ ◦ σ 0 (a) == σ 0 (σ(a)) für beliebige Terme a. Es gilt σ ◦ σ 0 = σ ∪ σ 0 , falls keine Variable in σ ∪ σ 0 in zwei verschiedenen Variablenersetzungsinstanzen auf der linken Seite vorkommt und keine Variable, die in einer Variablenersetzungsinstanz auf der linken Seite vorkommt in derselben oder einer anderen Variablenersetzungsinstanz auf der rechten Seite vorkommt. In dem Fall, dass eine eine Variable in einer Variablenersetzungsinstanz einer der beiden zu komponierenden Variablenersetzungen links steht, in einer Variablenersetzungsinstanz in der anderen der beiden zu komponierenden Variablenersetzungen auf der rechten Seite vorkommt, ist die erste auf die rechte Seite der letzteren anzuwenden. {X ← f(Y)} ◦ {Y ← f(Z)} wird also zu {X ← f(f(Z)), Y ← f(Z)}. 29 5.7 Der occurs-check Aus Effizienzgründen prüfen nicht alle Prolog-Interpreter bei der Berechnung eines allgemeinsten Unifikators, ob in allen Variablenersetzungsinstanzen eines möglichen Unifikators auch immer die Bedingung erfüllt ist, dass das Substituendum nicht im Substitut auftritt. Diese Prüfung wird auch als occurs check bezeichnet. Das Auslassen dieser Prüfung kann in bestimmten Situationen zur Berechnung fehlerhafter Unifikatoren, wie {X ← f(X)} als vermeintlicher Unifikator von X und f(X), führen oder dazu, dass der Unifikationsprozess nicht terminiert. Es ist von daher der Programmiererin oder dem Programmierer überlassen, Situationen zu vermeiden, in denen Variablen mit Ausdrücken unifiziert werden, die dieselben Variablen als Teilausdruck enthalten. Manche Prolog-Interpreter bieten neben dem Unifikationsprädikat =/2 ohne occurs check auch ein Unifikationsprädikat unify_with_occurs_check/2 mit occurs check an. 5.8 Die anonyme Variable Die anonyme Variable _ kann in Prolog als Platzhalter für Vorkommen einmalig auftretender Variablen betrachtet werden, deren Variablenersetzungsinstanzen nicht weiter interessieren. Die anonyme Variable kann bei der Unifikation durch beliebige Prolog-Terme ersetzt werden, und verschiedene Vorkommen der anonymen Variablen können auch durch verschiedene Terme ersetzt werden. Die anonyme Variable steht also, anders ausgedrückt, da, wo sie steht, immer für irgendwas Beliebiges. Bei der Angabe des Unifikators werden die Ersetzungen der anonymen Variablen nicht berücksichtigt. f(_,_,X) ist also mit f(a,b(c),c(d,e)) unifizierbar unter dem Unifikator {X ← c(d, e)}. 5.9 Der Prolog-Beweisalgorithmus: Prädikatenlogischer Fall Algorithmus P-5-4 (call(a) (det.)) 1. Nimm die erste Klausel in der Wissensbasis mit umbenannten Variablen, die ausschließlich aus b besteht, oder die Form b: −b1 , ...bn 30 hat, derart, dass b mit a unifizierbar ist. Sei σ der Unifikator von a und b. Falls keine derartige Klausel existiert, scheitert call(a). 2. (a) Falls die Klausel ausschließlich aus b besteht, gelingt call(a) unter dem Unifikator σ. (b) Falls die Klausel die Form b: −b1 , ...bn hat, rufe call(σ1◦ (b1 )), . . . call(σn◦ (bn )) in dieser Reihenfolge auf; dabei ist σ1 := σ und σi+1 der jeweils von call(σi (bi )) für 1 ≤ i ≤ n zurückgelieferte Unifikator, und ◦ σ1◦ := σ1 sowie σi+1 := σi◦ ◦ σi+1 ;3 call(a) gelingt unter dem Unifi◦ kator σn+1 , wenn alle Aufrufe call(σ1◦ (b1 )), ... call(σn◦ (bn )) gelingen; sobald ein Aufruf scheitert, gehe nach 3. 3. Revidiere die letzte Wahl einer Klausel in der Wissensbasis, indem die nächste geeignete Klausel in der Wissensbasis mit umbenannten Variablen gewählt wird. Falls keine derartige Klausel existiert, scheitert call(a). Andernfalls verfahre wie nach der vorangehenden Wahl (Schritt 2). Wird eine Anfrage a an der Prolog-Eingabeauforderung eingegeben und gelingt ein Aufruf von call(a), so zeigen Prolog-Interpreter in der Regel diejenigen Variablenersetzungsinstanzen der von call(a) zurückgelieferten Variablenersetzung an, deren links stehende Variablen in a vorkommen und nicht mit einem Unterstrich beginnen. Gibt es keine derartigen Variablenersetzungsinstanzen, so wird nur Yes angezeigt. Scheitert call(a), so zeigt Prolog die Antwort No an. Wird eine Anfrage vom Prolog-Interpreter positiv beantwortet und wird nicht einfach Yes zurückgegeben, sondern eine Reihe von Variablenersetzungsinstanzen, so besteht im Allgemeinen die Möglichkeit, zwischen der Ausgabe weiterer Lösungen (in SWI-Prolog durch Eingabe von ;) und Beendigung der Anfrage (in SWI-Prolog durch Eingabe von Enter) zu wählen. Wählt man die Ausgabe weiterer Lösungen, so lässt der Prolog-Interpreter den zuallerletzt ausgeführten call-Schritt scheitern, ersetzt also das letzte 3 Dabei ist die Komposition von Variablenersetzungen folgendermaßen zu bestimmen: σ 0 ◦ σ 00 := {α ← σ 00 (β)|α ← β ∈ σ 0 } ∪ σ 00 31 exit durch ein fail. Dies führt, falls es alternative Lösungswege gibt, zu einem redo. Gibt es keine alternativen Lösungswege mehr, endet die Anfrage mit einem fail. Programm P-5-4 a(X,X) :- c(X), d(X). a(X,v) :- b(X,w). a(X,Z) :- c(X), e(X,Z). b(y,u). c(u). d(w). e(u,w). σ1 σ2 σ3 σ4 σ5 σ6 5.10 = = = = = = {X {X {X {X {X {X ← X1, Y ← X1} ← u, Y ← u, X1 ← u} ← X2, Y ← v} ← X3, Y ← Z3} ← u, Y ← Z3, X3 ← u} ← u, Y ← w, X3 ← u, Z3 ← w} (2) Eine Notationskonvention für Prädikate Zum Beweis eines Teilziels vater(peter,X) kommen in einer Datenbasis nur Klauseln in Fragen, die entweder nur aus einer Struktur mit dem Funktor vater und zwei Argumenten bestehen oder einen solchen Kopf haben. Klauseln, bei denen Bruder mit einer anderen Argumentanzahl vorkommt, können nicht zum Beweis herangezogen werden, z.B. nicht die Klausel vater(peter). Aus diesem Grund wird davon gesprochen, dass der Funktor bruder mit einem Argument in Prolog ein anderes Prädikat darstellt als derselbe Funktor mit zwei Argumenten. Man schreibt diese Prädikate, wenn man über PrologPrädikate spricht, auch als vater/1 und vater/2. 32 Abbildung 4: Beweis von a(X,Y) mit P-5-4. Dabei sind σ1 bis σ6 wie in (2) definiert. 33 6 Rekursion Von einem rekursiv definierten Prädikat spricht man in Prolog, wenn das im Kopf einer Regel auftretende Prädikat auch im Rumpf derselben Regel auftritt oder im Rumpf einer anderen Regel, die man zum Beweis eines Teilziels im Rumpf der ersteren Regel benötigt. Genauer: Definition D-6-1 (Abhängigkeit) Ein Prädikat p ist abhängig von r definiert genau dann, wenn 1. r als Teilziel im Rumpf einer Regel vorkommt, deren Kopf p ist, oder 2. es ein Teilziel f im Rumpf einer Regel, deren Kopf p ist, gibt und f abhängig von r definiert ist. Definition D-6-2 (Rekursivität) Ein Prädikat p ist rekursiv definiert genau dann, wenn p abhängig definiert von p ist. Beispiel 6.1 In den Definitionen bruder(X,Y) :mutter(M,X), mutter(M,Y), vater(V,X), vater(V,Y), X\=Y. vater(X,Y) :- elternteil(X,Y), maennlich(X). mutter(X,Y) :- elternteil(X,Y), weiblich(X). ist bruder/2 abhängig von mutter/2, vater/2, elternteil/2, maennlich/1, weiblich/1 (und \=/2) definiert. Würde man auch die Regel hinzunehmen vater(X,Y) :- bruder(A,Y), vater(X,A). so würde bruder/2 auch abhängig von bruder/2 definiert und würde somit rekursiv. Übung 6.1 1. Sehen Sie sich die Definition des Prädikats puppe/1 in puppe.pl an. (a) Wie läuft der Beweis von ?- puppe(matruschka(matruschka(matruschka(matruschka)))). 34 ab? (b) Definieren Sie ein Prädikat puppe2/1, das sich von puppe/1 nur darin unterscheidet, dass die Reihenfolge der beiden Klauseln umgekehrt ist. Wie läuft der Beweis von ?- puppe2(matruschka(matruschka(matruschka(matruschka)))). ab? (c) “Generieren” Sie “Puppen”mit ?- puppe(X). (d) Probieren Sie dasselbe mit puppe2/1. Wo liegt der Unterschied? 2. Lassen Sie sich von wegsuche/3 in weg.pl den Weg vom Bahnhof zur Uni suchen. (a) Wie läuft die Suche ab? (b) Welches Problem tritt auf, wenn Sie Wege in Gegenrichtung zu den gegebenen in Ihre Datenbasis aufnehmen? 3. Bei einer früheren Übung war es wegen der Symmetrie der Relation des Verheiratetseins nötig, für ein Faktum, wie verheiratet(georg,petra). auch immer das Faktum verheiratet(petra,georg). aufzunehmen. Warum ist die Regel verheiratet(X,Y) :- verheiratet(Y,X). keine geeignete Lösung zur Verminderung der Redundanz in der Datenbasis? Gibt es eine andere Möglichkeit (ohne Rekursion) die Datenbasis weniger redundant zu gestalten? 4. Definieren Sie rekursiv ein Prädikat fa/1, das auf die folgenden Terme zutrifft: 35 Abbildung 5: Karte zum Wegsuche-Problem 36 argument funktor(argument) funktor(funktor(argument)) ... ?- fa(funktor(argument)). soll also zutreffen, nicht aber ?- fa(funktor). 5. Wenn wir in Prolog den Datentyp Zahl nicht zur Verfügung hätten, könnten wir die natürlichen Zahlen auch durch Terme wie die folgenden darstellen: eins nachfolger(eins) nachfolger(nachfolger(eins)) nachfolger(nachfolger(nachfolger(eins))) nachfolger(nachfolger(nachfolger(nachfolger(eins)))) ... (a) Definieren Sie ein Prädikat zahl/1, das entscheidet, ob ein gegebener nicht-variabler Prolog-Term eine Zahl in diesem Sinne ist. (b) Kann zahl/1 auch “zählen”? D.h. werden bei Eingabe von ?- zahl(N). auch Zahlen als Ersetzungen von N ausgegeben? Falls nicht, wie kann man das erreichen? (c) Definieren Sie ein Prädikat groesser_als_drei/1, das auf Zahlen größer 3 in dieser Schreibweise zutrifft. (d) Definieren Sie ein Prädikat kleiner_als_fuenf/1, das auf Zahlen kleiner 5 in dieser Schreibweise zutrifft. (e) Definieren Sie ein Prädikat groesser_als/2, das, auf Zahlen in dieser Schreibweise angewandt, entscheidet, ob die erste größer als die zweite ist. (f ) Definieren Sie ein Prädikat gleich/2, das, auf Zahlen in dieser Schreibweise angewandt, entscheidet, ob die erste gegebene Zahl gleich der zweiten gegebenen Zahl ist. (g) Definieren Sie ein Prädikat summe/3, mit dessen Hilfe sich die Summe zweier in dieser Schreibweise gegebener Zahlen berechnen lässt. 37 ?- summe(nachfolger(nachfolger(eins)), nachfolger(eins), S). S = nachfolger(nachfolger(nachfolger(nachfolger(eins)))) Kann summe/3 auch Differenzen berechnen? Also: ?- summe(nachfolger(nachfolger(eins)), D, nachfolger(nachfolger(nachfolger(nachfolger(eins))))). D = nachfolger(eins) Falls nicht, wie können Sie dies erreichen? (h) Definieren Sie mithilfe von summe/3 ein entsprechendes Prädikat produkt/3 zur Produktbildung. 6. Seien binär verzweigende Baumstrukturen in der folgenden Weise repräsentiert: knoten(knoten(blatt,blatt),blatt) knoten(blatt,blatt) knoten(knoten(knoten(blatt,blatt),blatt), knoten(knoten(blatt,blatt),knoten(blatt,blatt))) Die folgende Graphik Abb. 6 stellt den ersten Baum dar. (a) Definieren Sie ein Prädikat baum/1, das feststellt, ob eine gegebene Prolog-Struktur eine Baumstruktur in dieser Darstellung ist. (b) Wenn man als die Tiefe eines Baums die maximale Anzahl von Knoten versteht, die von der Wurzel bis zu einem Blatt passiert werden müssen (einschließlich der Wurzel), definieren Sie ein Prädikat tiefe/2, das für einen gegebenen Baum diese Tiefe berechnet und das Ergebnis in der oben beschriebenen Zahlenrepräsentation ausgibt. Dabei können Sie die Tiefe in der Zahlenrepräsentation von Übung 6.1.5 angeben, z.B. ?- tiefe(knoten(knoten(blatt,blatt),blatt),N). N = nachfolger(eins) ?- tiefe(knoten(blatt,blatt), N). N = eins 38 Abbildung 6: Der Baum knoten(knoten(blatt,blatt),blatt) 39 ?- tiefe(knoten(knoten(knoten(blatt,blatt),blatt), knoten(knoten(blatt,blatt),knoten(blatt,blatt)))). N = nachfolger(nachfolger(eins) oder durch Prolog-Integers, z.B. ?- tiefe(knoten(knoten(blatt,blatt),blatt),N). N = 2 ?- tiefe(knoten(blatt,blatt), N). N = 1 ?- tiefe(knoten(knoten(knoten(blatt,blatt),blatt), knoten(knoten(blatt,blatt),knoten(blatt,blatt)))). N = 3 In letzterem Fall ist das Prädikat is/2 von Abschnitt 9 zu verwenden. Die Bedingung M is N + 1 liefert bei einem gegebenen Integer N den um eins höheren Integer als M. (c) Definieren Sie ein Prädikat, das feststellt, ob die beiden Teilbäume, die am Wurzelknoten hängen, gleich tief sind. (d) Definieren Sie ein Prädikat ausgewogen/1, das feststellt, ob der binäre Baum ausgewogen ist. Ein binärer Baum ist ausgewogen, wenn für alle Knoten gilt: entweder hängen an ihnen zwei Blätter oder zwei gleichtiefe Bäume. Man kann ausgewogen/1 mithilfe des unmittelbar zuvor definierten Prädikats definieren; das dürfte allerdings nicht die effizienteste Lösung sein. (e) Lassen Sie statt der “Blätter” auch die Atome n, v, art, adj in Ihren Bäumen als “Terminalsymbole” zu. Definieren Sie ein Prädikat enthaelt_terminalsymbol/2, das für einen gegebenen Baum entscheidet, ob ein gegebenes Terminalsymbol darin vorkommt. (f ) Lassen Sie statt der Knoten auch die Funktoren np und vp als “Nichtterminalsymbole” zu. Definieren Sie ein Prädikat enthaelt_nichtterminalsymbol/2, das für einen gegebenen Baum entscheidet, ob ein gegebenes Nichtterminalsymbol darin vorkommt. 40 ?- enthaelt_nichtterminalsymbol(vp(vp(n,v),adj), vp). Yes ?- enthaelt_nichtterminalsymbol(vp(vp(n,v),adj), np). No Kann Ihr Prädikat auch die in einem Baum vorkommenden Nichtterminalsymbole aufzählen (Mehrfachnennungen erlaubt)? (g) Definieren Sie ein Prädikat pruefe_phrasen/1, das überprüft, ob unterhalb jeden np-Knotens auch mindestens ein n-Blatt vorkommt und unterhalb jeden vp-Knotens auch mindestens ein vBlatt. ?- pruefe_phrasen(vp(np(art,n),v)). Yes ?- pruefe_phrasen(vp(np(art,n),adj)). No Es ist in Prolog immer dann unerlässlich, Prädikate rekursiv zu definieren, wenn Probleme gelöst werden sollen, bei denen nicht unabhängig von konkreten Eingaben zu bestimmen ist, wieviele Schritte zur Problemlösung erforderlich sind. Zu jedem Prolog-Programm, das gänzlich ohne Rekursion auskommt, gibt es eine für dieses Programm spezifische Höchstzahl an Schritten, die ein Beweis haben kann. Im Umkehrschluss heißt das: Prolog-Programme ohne Rekursion können Probleme nicht lösen, bei denen unbestimmt ist, wieviele Schritte erforderlich sind. Die meisten Probleme der Übung 6.1 sind von dieser Art. Die Definition eines rekursiv definierten Prädikats P besteht i.A. aus einer oder mehreren Klauseln, die den oder die einfachsten Fälle beschreiben, die sog. Abbruchbedingungen. Die Abbruchbedingungen sind entweder Fakten oder Regeln, in deren Rumpf P oder ein von P abhängig definiertes Prädikat nicht vorkommt. Die Abbruchbedingungen sind also nicht rekursiv. Die Abbruchbedingungen sollten i.A. auch die ersten Klauseln der Prädikatsdefinition sein, damit Abbruchbedingungen so früh wie möglich im Beweisprozess angewandt werden. Die übrigen Klauseln eines rekursiv definierten Prädikats enthalten im Rumpf neben anderen entweder P oder von P abhängig definierte Prädika41 te. Diese Klauseln sind also rekursiv. Wichtig ist, dass sichergestellt ist, dass durch jede Anwendung einer rekursiven Klausel das zu lösende Problem derart vereinfacht wird, dass auf jedes zu lösende Problem nach endlich vielen Rekursionsschritten eine der Abbruchbedingungen anwendbar ist. 6.1 Dokumentation von Prädikatsdefinitionen Prolog-Programme sollten immer durch die Einfügung von Kommentaren dokumentiert werden, damit sie übersichtlich bleiben. Es ist üblich, jeder Prädikatsdefinition einige Kommentarzeilen voranzustellen, die die Bedeutung des Prädikats erläutern und seine Argumente beschreiben. Vielfach sind Prädikate für sehr spezifische Verwendungsweisen intendiert: Einzelne Argumente sollen beim Aufruf des Prädikats Variablen sein, andere müssen durch Nicht-Variablen belegt sein. Das oben definierte Prädikat tiefe/2 beispielsweise dürfte normalerweise nicht im Hinblick auf Fälle definiert sein, bei denen das erste Argument eine Variable ist; denn es soll für gegebene Bäume deren Tiefe berechnen. Das zweite Argument kann allerdings eine Variable sein, wenn man die Tiefe eines Baum berechnen möchte, es kann aber auch eine gegebene Zahl sein, wenn es ausschließlich darum geht, zu überprüfen, ob ein Baum die angegebene Tiefe hat. Diese Intention wird in der ersten Kommentarzeile des Kommentars % tiefe(+Baum,?N) % Berechnet N als die Tiefe von Baum. ausgedrückt. + vor einem Argument, gibt an, dass es beim Aufruf des Prädikats eine Nicht-Variable sein sollte, - das Gegenteil; ? vor einem Argument drückt aus, dass beide Möglichkeiten zugelassen sind. Ein derartiger Kommentar sollte im allgemeinen der Definition eines Prolog-Prädikats vorangestellt werden. 7 Listen Sollen in Prolog Folgen von Elementen dargestellt werden und soll auf die einzelnen Elemente zugegriffen werden, so ist eine Darstellung der Form liste(a1,a2,a3) 42 nur dann eine geeignete Form, wenn die Listenlänge (im Beispiel 3) feststeht. Variiert die Listenlänge, hat man es mit komplexen Strukturen mit unterschiedlicher Argumentzahl zu tun. Es ist damit nicht mehr möglich, diese unterschiedlich langen Listen entsprechenden komplexen Strukturen mit denselben komplexen Strukturen zu unifizieren, um die Listenelemente zu extrahieren. Ein Prädikat, das das erste Element einer Liste zurückgibt, wäre beispielsweise für drei- und vierelementige Listen unterschiedlich zu definieren: erstes3(liste(E,_,_),E). erstes4(liste(E,_,_,_),E). Geeigneter ist eine Darstellung der Form liste(a1,liste(a2,liste(a3,leer))) bei der eine Liste immer einer komplexen Struktur mit dem Funktor liste und zwei Argumenten besteht, von denen das erste ein Listenelement ist und das zweite wiederum eine Liste ist. Das Ende der Liste wird durch das Atom leer repräsentiert, das die leere Liste vertritt. Bei dieser Art der Listendarstellung liefert das folgende Prädikat erstes/2 immer das erste Element einer Liste, zweites/2 immer das zweite usw. unabhängig von der Länge der Liste, sofern die Liste überhaupt ein erstes bzw. ein zweites Element enthält: erstes(liste(E,_),E). zweites(liste(_,liste(Z,_)),Z). Zwar ist es reine Konvention, wie man den Funktor einer eine Liste repräsentierenden komplexen Struktur benennt, doch wird in Prolog statt des Funkturs liste i.A. der Funktor . oder ’.’ gewählt und statt des Atoms leer für die leere Liste das Atom []. Für diese komplexen Strukturen gibt es eine kompaktere Schreibweise, die Listenschreibweise und i.d.R. bei PrologInterpretern auch besonders effiziente Verarbeitungsroutinen. Die oben genannte Liste sähe in dieser Repräsentation also wie folgt aus: ’.’(a1,’.’(a2,’.’(a3,[]))) und in Listenschreibweise [a1,a2,a3] 43 Ist nur der Anfang einer Liste bekannt, nicht aber ihr Ende und die Anzahl ihrer Elemente kann man das in der folgenden Weise notieren: ’.’(a1,’.’(a2,’.’(a3,X))) und in Listenschreibweise [a1,a2,a3|X] Allerdings entstehen aus diesen Ausdrücken nur dann Listen, wenn X ebenfalls durch eine Liste ersetzt wird. Prolog-Terme, die selbst keine Listen sind, durch Variablenersetzungen aber Listen werden können, werden auch als Listenterme bezeichnet. Ersetzt man im obigen Beispiel X durch ’.’(a4,’.’(a5,[])) bzw. [a4,a5], so entsteht die Liste ’.’(a1,’.’(a2,’.’(a3,’.’(a4,’.’(a5,[]))))) und in Listenschreibweise [a1,a2,a3|[a4,a5]] bzw. [a1,a2,a3,a4,a5] Definition D-7-1 (Liste) Ein Prolog-Term a ist eine Liste gdw 1. a das Atom [] ist oder 2. es einen Prolog-Term b und eine Liste c gibt, so dass a die komplexe Struktur ’.’(b,c) ist. ’.’(b,c) kann auch als [b|c] geschrieben werden. b wird auch als erstes Element der Liste und c als der Rest bezeichnet. Statt [a1 , . . . , an |[b1 , . . . , bm ]] kann auch immer [a1 , . . . , an , b1 , . . . , bm ] notiert werden. Definition D-7-2 (Listenterm) Ein Prolog-Term a ist ein Listenterm gdw es Prolog-Terme b und c gibt, so dass 1. c ein Listenterm oder eine Variable ist und 44 2. a die komplexe Struktur ’.’(b,c) ist. ’.’(b,c) kann auch als [b|c] geschrieben werden. b wird auch als erstes Element des Listenterms und c als der Rest bezeichnet. Statt [a1 , . . . , an |[b1 , . . . , bm ]] kann auch immer [a1 , . . . , an , b1 , . . . , bm ] notiert werden. Beispiel 7.1 Beispiele für zutreffende Unifizierbarkeitsbehauptungen: [a] = .(a,[]) [a,b] = .(a,.(b,[])) [a,b|Rest] = .(a,.(b,Rest)) Beispiel 7.2 Beispiele für Listen, eine zutreffende Unifizierbarkeitsbehauptung und Unifizierbarkeitsanfragen mit Listen(termen): [gitte,fido,venus] [X] [gitte,Planet] [sonne,[erde,[mond],venus,saturn]] [[],impliziert(mensch(X),sterblich(X))] [menschen([gitte,lore,gerd]),hunde([fido,bello])] [Erstes|Rest] [Erstes,Zweites|Rest] [a,b,c|[d,e]] = [a,b,c,d,e] ?- [a,b,c] = [Erstes|Rest]. Erstes = a Rest = [b,c] ?- [a] = [X|Y]. X = a Y = [] Übung 7.1 1. Treffen die folgenden Unifikationsbehauptungen zu? Welchen allgemeinsten Unifikator ergeben sie? [1,5,6] = [E|R]. 45 [1,5,6] = [E,Z|R]. [1,5,6] = [E,R]. [1,5] = [E,Z|R]. [1,5,6|R1] = [E|R2]. [1,5,6|R1] = [E|R]. [[mond],venus,saturn] = [A|B]. [mond,[venus,saturn]] = [A|B]. 2. Was testet das wie folgt definierte test1/1? test1([_,_,_,_]). 3. Was testet das wie folgt definierte test2/1? test2([_,_,_|_]). 4. Definieren Sie ein Prädikat zweites_element/2, das zutrifft, wenn das erste Argument eine Liste ist und das zweite Argument das zweite Element dieser Liste. ?- zweites_element([a,b,c,d],b). Yes ?- zweites_element([a,b,c,d],c). No ?- zweites_element([a,b,c,d],X). X = b 5. Definieren Sie ein Prädikat loesche_viertes/2, das das vierte Element aus einer Liste löscht. ?- loesche_viertes([a,b,c,d,e],X). X = [a,b,c,e] 6. Definieren Sie ein Prädikat ersetze_viertes/3, das das vierte Element einer Liste durch ein gegebenes ersetzt. 46 ?- ersetze_viertes([a,b,c,d,e],neu,X). X = [a,b,c,neu,e] Übung 7.2 1. Sehen Sie sich die Prädikate in der Datei liste.pl an. 2. Definieren Sie ein Prädikat loesche/3, das aus einer Liste alle Vorkommen eines gegebenen Elementes löscht. ?- loesche(b,[a,b,c,d,b],X). X = [a,c,d] Bietet Ihr Prädikat als alternative Lösungen auch X = [a,b,c,d] X = [a,c,d,b] X = [a,b,c,d,b] also alle Listen, bei denen höchstens alle Vorkommen eines gegebenen Elementes gelöscht sind? Wie können Sie die Alternativen vermeiden? 3. Definieren Sie ein Prädikat ersetze/4, das in einer Liste alle Vorkommen eines gegebenen Elementes durch einen gegebenen Prolog-Term ersetzt. ?- ersetze(b,[a,b,c,d,b],neu,X). X = [a,neu,c,d,neu] Bietet Ihr Prädikat als alternative Lösungen auch X = [a,b,c,d,neu] X = [a,neu,c,d,b] X = [a,b,c,d,b] also alle Listen, bei denen höchstens alle Vorkommen eines gegebenen Elementes ersetzt sind? Wie können Sie die Alternativen vermeiden? 4. Definieren Sie ein Prädikat umgekehrt/2, das die Reihenfolge der Elemente einer Liste umkehrt. 47 5. Definieren sie ein Prädikat, das das letzte Element einer Liste liefert. 6. Erweitern Sie das Prädikat loesche/3 zu loesche_liste/3 dadurch, dass Sie nicht nur die Angabe eines einzelnen zu löschenden Elements, sondern die Angabe einer Liste zu löschender Elemente gestatten. ?- loesche_liste([b,c],[a,b,c,d,b],X). X = [a,d] Die Bemerkungen zu den alternativen Lösungen gelten in ähnlicher Weise. 7. Definieren Sie ein Prädikat teilmenge/2, das feststellt, ob die in einer ersten Liste enthaltenen Elemente sämtlich auch in einer zweiten Liste enthalten sind, ohne Rücksicht auf Reihenfolge oder Wiederholungen. ?- teilmenge([a,b,c,b,d],[e,d,b,c,a]). Yes 8. Wie kann man feststellen, ob zwei Listen dieselben Elemente, ohne Rücksicht auf Reihenfolge oder Wiederholungen, enthalten? 8 Operatoren Oft kommt es gewohnten Notationsweisen näher, wenn man statt der üblichen Funktor-Argument-Schreibweise bei zwei Argumenten den Funktor zwischen die Argumente schreiben kann, also statt =(X,a) z.B. X=a bzw. X = a schreiben kann (zwischen dem Funktor und den Argumenten sind Leerzeichen erforderlich, wenn der Funktor mit den Argumenten auch ein einzelnes Atom bilden koennte, wie bei * = * im Gegensatz zu *=*). Auch Funktoren mit einem Argument können als einstellige Operatoren verwendet werden, z.B. kann not(X) in SWI-Prolog auch not X geschrieben werden. Ausdrücke in Operatorenschreibweise können beliebig oft mit runden Klammern geklammert werden. Es gilt also (a+b) == a+b oder sogar 48 ((((a+b)))) == a+b Prolog behandelt Ausdrücke in Operatorenschreibweise und ihre konventionellen Äquivalente als identische Ausdrücke. +(1,*(2,3)) == 1 + 2 * 3 Ob und welche Prolog-Terme in Operatorenschreibweise selbst wieder als Argumente von Termen in Operatorenschreibweise mit einem Operator o verwendet werden können, entscheiden die Assoziativitätsklasse von o und die Priorität von o. Die Priorität eines Operators ist eine ganze Zahl zwischen 0 und 1200. Man unterscheidet in Prolog folgende Assoziativitätsklassen von Operatoren: xf, yf, xfx, xfy, yfx, yfy, fy und fx. f steht dabei jeweils für die Position des Operators o relativ zu seinen Argumenten. x besagt, dass das entsprechende Argument nur dann ein ungeklammerter Prolog-Term in Operatorenschreibweise sein darf, wenn die Priorität seines Operators echt kleiner ist als die von o. y besagt, dass das entsprechende Argument nur dann ein ungeklammerter Prolog-Term in Operatorenschreibweise sein darf, wenn die Priorität seines Operators kleiner als die von o oder gleich der von o ist. Operatoren der Assoziativitätsklasse xfy werden auch als rechtsassoziativ, Operatoren der Assoziativitätsklasse yfx als linksassoziativ bezeichnet. Gültige Operatorendeklarationen lassen sich in Prolog mit dem Prädikat current_op/3 abfragen, dessen erstes Argument die Priorität, dessen zweites Argument die Assoziativitätsklasse und dessen drittes Argument den Namen des Operators angibt. Die Deklaration des Operators * erhält man beispielsweise durch die Anfrage ?- current_op(P,T,*). P = 400 T = yfx Aufgrund dieser Definition ist a*b*c = (a*b)*c da nur links von * ein ungeklammerter Ausdruck in Operatorenschreibweise mit einem Operator derselben Priorität vorkommen darf. Es gilt a+b*c = a+(b*c) 49 weil ?- current_op(P,T,+). P = 500 T = yfx Andererseits aber ist a-->b-->c ein syntaktisch nicht korrekter Ausdruck, da ?- current_op(P,T,-->). P = 1200 T = xfx und deshalb keines der beiden Argumente des Operators ein ungeklammerter Prolog-Term mit einem Operator derselben Priorität sein darf. Durch Anfragen mit dem Prädikat op/3 kann man in Prolog neue Operatorendeklarationen einführen. ?- op(700, xfx, ist_gleich). deklariert beispielsweise das Atom ist_gleich als einen Operator mit Präzedenz 700 und Assoziativitätsklasse xfx. Im Anschluss an diese Deklaration kann ist_gleich als Operator verwendet werden. 23.0 ist_gleich 23 ist nach der Deklaration also ein gültiger Prolog-Term. Die Anfrage ?- 23.0 ist_gleich 23. führt geneu dann zum Ergebnis Yes, wenn auch ?- ist_gleich(23.0, 23). Dies hängt natürlich von der Definition des Prädikats ist_gleich/2 ab. Wichtige vordefinierte Operatoren sind der Tabelle 1 zu entnehmen. 50 Operator = \= + * / is :--> ’,’ Priorität Assoziativitätsklasse 700 xfx 700 xfx 500 yfx 500 yfx 400 yfx 400 yfx 700 xfx 1200 xfx 1200 xfx 1000 xfy Tabelle 1: Wichtige vordefinierte Operatoren 9 Arithmetische Operationen Das Prädikat is/2 erlaubt es in Prolog mit Zahlen und arithmetischen Operatoren bzw. Funktoren zu rechnen. Dabei evaluiert is/2 das zweite Argument arithmetisch, sofern es ein arithmetischer Ausdruck ist und unifiziert das Ergebnis der Evaluation mit dem ersten Argument, z.B. ?- X is 2*3+5.2. X=11.2 Man beachte, dass für die Unifikationsbehauptung gilt: ?- 11.2 = 2*3+5.2. no da hier ein atomarer Ausdruck mit einer komplexen Struktur unifiziert werden soll. Übung 9.1 1. Definieren Sie ein Prädikat laenge/2, das die Länge einer Liste zurückgibt. 2. Definieren Sie ein Prädikat ntes/3, das das n-te Element einer Liste zurückgibt. 3. Definieren Sie ein Prädikat loesche_ntes/3, das das n-te Element einer Liste löscht. 51 4. Lassen Sie bei den beiden vorangehenden Prädikaten auch Listen von Positionsangaben zu. 5. Definieren Sie ein Prädikat sortiere/2, das eine Liste von Zahlen sortiert zurückgibt. 6. Definieren Sie ein Prädikat suche/3, das ein gegebenes Element in einer Liste sucht und die Position des ersten Vorkommens zurückgibt. 7. Modifizieren Sie suche/3 so, dass eine Liste aller Vorkommen des gesuchten Elementes zurückgegeben wird. 8. Definieren Sie ein Prädikat addiere/2, das die Elemente einer Liste von Zahlen addiert und das Ergebnis zurückgibt. 10 Vordefinierte Prädikate Neben den selbstdefinierten Prädikaten kennt jeder Prolog-Interpreter eine Reihe vordefinierter Prädikate. Einige von diesen wurden bereits verwendet. Wie andere Prädikate auch liefert der Aufruf (call) vordefinierter Prädikate einen der Werte Yes oder No oder einen Unifikator. Bei manchen vordefinierten Prädikaten sind aber andere Auswirkungen des Prädikataufrufs interessanter, die sogenannten Seiteneffekte, die mit einem Aufruf verbunden sind. 10.1 Vergleichsoperationen Hier handelt es sich um Prädikate zum Vergleich von Termen ohne irgendwelche Seiteneffekte. =/2 unifiziert die beiden Argumente, scheitert bei Nicht-Unifizierbarkeit; zwei Ausdrücke gelten auch dann als unifizierbar, wenn mit ihnen i.S.v. ==/2 jeweils “gleiche” Ausdrücke unifizierbar sind. Also gilt: ?- X + 1 * 3 = 2 + (Y * 3). Yes weil 52 ?- X + 1 * 3 Yes == +(X,*(1,3)). ?- 2 + (Y * 3) == +(2,*(Y,3)). Yes ?- +(X,*(1,3)) = Yes +(2,*(Y,3)). \=/2 testet die beiden Argumente auf Nicht-Unifizierbarkeit, scheitert bei Unifizierbarkeit; ==/2 testet die beiden Argumente auf Gleichheit, scheitert bei Ungleichheit; als gleich werden allerdings auch Funktor-Argument-Strukturen und ihnen entsprechende Operatorenstrukturen (mit oder ohne Klammern) (vgl. Abschnitt 8) betrachtet. \==/2 testet die beiden Argumente auf Ungleichheit, scheitert bei Gleichheit; 10.2 Arithmetische Prädikate Hierbei handelt es sich um Prädikate, die für Rechenoperationen benötigt werden. Die Prädikate haben keinerlei Seiteneffekte. >=/2 testet, ob das erste Argument eine größere oder gleichgroße Zahl wie das zweite Argument ist, scheitert sonst; >/2 testet, ob das erste Argument eine größere Zahl als das zweite Argument ist, scheitert sonst; =</2 testet, ob das erste Argument eine kleinere oder gleichgroße Zahl wie das zweite Argument ist, scheitert sonst; >/2 testet, ob das erste Argument eine kleinere Zahl als das zweite Argument ist, scheitert sonst. is/2 wertet das zweite Argument arithmetisch aus (vgl. Abschnitt 9 und unifiziert das Ergebnis mit dem ersten Argument, scheitert bei Nichtauswertbarkeit des zweiten Arguments oder bei Nicht-Unifizierbarkeit des Ergebisses mit dem ersten Argument. 53 10.3 Metaprädikate Metaprädikate erfragen oder ändern Eigenschaften von Prolog-Termen. Die Metaprädikate var/1, nonvar/1, atomic/1, atom/1, integer/1, number/1 wurden schon in Abschnitt 4.5 vorgestellt. current op/3 Verwendung: current_op(?Prio,?AC,?Op), fragt die Priorität Prio und die Assoziativitätsklasse AC des Operators Op ab; op/3 Verwendung: op(+Prio,+AC,+Op), gelingt, wenn Prio, AC und Op gültige Prioritäten, Assoziationsklassen bzw. Atome angeben, scheitert sonst; Seiteneffekt beim Gelingen: Op wird zu einem Operator mit Priorität Prio und Assoziativitätsklasse AC. 10.4 Kontrollprädikate Kontrollprädikate verändern den Beweisgang, indem sie Einfluss auf den Beweisalgorithmus nehmen oder die Wissensbasis verändern. Bei diesen Prädikaten ist also der Seiteneffekt wesentlich. consult/1 Seiteneffekt: konsultiert die als Argument angegebene Datei; scheitert bei Misslingen; asserta/1 Seiteneffekt: fügt in der Wissensbasis zu Anfang die als Argument angegebe Klausel ein; scheitert bei Misslingen; assertz/1 Seiteneffekt: fügt in der Wissensbasis am Ende die als Argument angegebe Klausel ein; scheitert bei Misslingen; retract/1 gelingt bei Unifizierbarkeit des Arguments mit einer zuvor mit asserta/1 oder assertz/1 der Wissensbasis hinzugefügten Klausel, gibt den Unifikator der Unifikation mit der ersten derartigen Klausel in der Wissensbasis zurück, scheitert, wenn keine derartige Klausel existiert; Seiteneffekt: löscht bei Gelingen die Klausel, die mit dem Argument unifiziert wurde; !/0 Cut: gelingt immer; Seiteneffekt: die Wahl einer alternativen Klausel zum Beweis des aktuellen Teilziels wird ausgeschlossen. 54 10.5 Listenprädikate Die folgenden Listenprädikate gehören nicht zum Prolog-Standard, sind jedoch bei den meisten Prolog-Interpretern als eingebaute Prädikate vorhanden. Sie haben keine Seiteneffekte. append/3 Verwendungsweise append(?L1,?L2,?L3): gelingt, wenn es eine Variablenersetzung gibt, unter der L1 eine Liste und L2 und L3 Listen oder Listenterme sind und L3 die aus der Verkettung L1 und L2 hervorgehende Liste (oder der daraus hervorgehende Listenterm ist, scheitert sonst; length/2 Verwendungsweise: length(?L,?N): gelingt, wenn es eine Variablenersetzung gibt, unter der L eine Liste ist und N deren Länge ist, scheitert sonst; reverse/2 Verwendungsweise reverse(+L1,?L2): gelingt, wenn L2 mit derjenigen Liste unifizierbar ist, die aus L1 durch Umkehrung der Reihenfolge der Elemente hervorgeht. 10.6 Prädikate mit Hilfe-Funktion Diese Prädikate gehören ebenfalls nicht zum Prolog-Standard. Prädikate mit Hilfe-Funktion bieten jedoch fast alle Prolog-Interpreter an. SWI-Prolog kennt u.a. die Prädikate: help/0 gelingt immer; Seiteneffekt: gibt Information zur Hilfe-Funktion aus; help/1 gelingt immer; Seiteneffekt: gibt Information zum als Argument übergebenen Prädikat aus; apropos/1 gelingt immer; Seiteneffekt: gibt Information zum als Argument übergebenen Stichwort aus. A A.1 Beispielprogramme maier.pl % % Zu den Beispielen vgl. E. König / R. Seiffert: Grundkurs PROLOG für 55 % Linguisten. UTB 1525. Tübingen: 1989. % % fakten % % Eine erste Menge von Fakten. % % Fakten zur Familie Maier % % Beginn % /* Die Personen in Familie Maier: */ person(lore). person(gerd). person(gitte). person(petra). person(uli). /* Die Frauen: */ weiblich(lore). weiblich(gitte). weiblich(petra). /* Die Männer: */ maennlich(gerd). maennlich(uli). /* Ihr Hund. */ hund(fido). /* Die Spielzeugeisenbahn. */ spielzeugeisenbahn(d318). /* Eltern-Kind-Beziehungen */ vater(gerd,gitte). vater(gerd,uli). 56 vater(gerd,petra). mutter(lore,gitte). mutter(lore,uli). % Eine Regel: % Jeder Vater schenkt seiner Tochter eine Spielzeugeisenbahn. % schenkt(X,Y,Z) :% X schenkt Y ein Z, falls vater(X,Y), % X Vater von Y ist und weiblich(Y), % Y weiblich ist und spielzeugeisenbahn(Z). % Z eine Spielzeugeisenbahn ist. % % Fakten zur Familie Maier % % Ende % A.2 sokrates.pl % Eine weitere Regel und und ein weiteres Fakt: % sterblich(X) :- mensch(X). mensch(sokrates). % % Zu den Beispielen vgl. E. König / R. Seiffert: Grundkurs PROLOG für % Linguisten. UTB 1525. Tübingen: 1989. % A.3 bonn.pl % Einige Bonner Fakten % bonner(X) :57 bonner_stadtteil(Y), wohnt(X,Y). bonner_stadtteil(poppelsdorf). bonner_stadtteil(auerberg). wohnt(lothar,poppelsdorf). wohnt(gustav,auerberg). wohnt(birte,auerberg). A.4 raetsel.pl % Ein Raetsel. % raetsel :was_denn, wie_auch_immer. was_denn :abxy. was_denn :cufg. cufg. abxy. wie_auch_immer. % Ein weiteres Raetsel. % raetsel2(X) :was_denn(X). was_denn(huhn(X)) :abrakadabra(X). was_denn(hahn(X)) :simsalabim(X). abrakadabra(ute). simsalabim(otto). % % Zu den Beispielen vgl. E. König / R. Seiffert: Grundkurs PROLOG für % Linguisten. UTB 1525. Tübingen: 1989. 58 % A.5 weg.pl % Stadtplan: Orte sind durch Atome (bahnhof, uni) % oder einen Term mit dem Funktor kreuzt und zwei % Atomen für sich kreuzende Straáen bezeichnet. % Wege werden durch den Funktor weg mit zwei % Orten als Argumenten bezeichnet. % weg(bahnhof,kreuzt(kronenstr,lautenschlagerstr)). weg(kreuzt(kronenstr,lautenschlagerstr), kreuzt(friedrichstr,kronenstr)). weg(bahnhof,kreuzt(friedrichstr,kriegsbergstr)). weg(kreuzt(friedrichstr,kriegsbergstr), kreuzt(friedrichstr,kronenstr)). weg(kreuzt(friedrichstr,kronenstr),uni). weg(kreuzt(friedrichstr,kronenstr), kreuzt(kriegsbergstr,kronenstr)). weg(kreuzt(kriegsbergstr,kronenstr), kreuzt(keplerstr,kriegsbergstr)). weg(kreuzt(keplerstr,kriegsbergstr),uni). % % wegsuche(X,Y,Z) % % trifft zu, wenn Z ein Weg ist, der von X nach Y führt % wegsuche(Punkt,Punkt,Punkt). wegsuche(Anfang,Ende,weg(Anfang,NaechsterWeg)) :weg(Anfang,NaechsterPunkt), wegsuche(NaechsterPunkt,Ende,NaechsterWeg). % % Zu den Beispielen vgl. E. König / R. Seiffert: Grundkurs PROLOG für % Linguisten. UTB 1525. Tübingen: 1989. % 59 A.6 puppe.pl % % Beispiele zur Rekursion % % puppe(X). % % trifft auf das Atom emma zu oder alle Prolog-Terme, % in denen eine "puppe" als Argument und emma als Funktor % auftritt. puppe(matruschka). puppe(matruschka(Puppe)) :puppe(Puppe). % % Zu den Beispielen vgl. E. König / R. Seiffert: Grundkurs PROLOG für % Linguisten. UTB 1525. Tübingen: 1989. % B Formalia In dieser Übung können Leistungs- und Teilnahmenachweise erworben werden. Leistungsnachweis Voraussetzung für den Erwerb eines Leistungsnachweises ist die Abgabe der abzugebenden Hausarbeiten und das Bestehen der Klausur in der letzen Sitzung. Teilnahmenachweis Voraussetzung für den Erwerb eines Teilnahmenachweises ist die regelmäßige und aktive Teilnahme. Zur aktiven Teilnahme gehört die Abgabe der abzugebenden Hausarbeiten und die Teilnahme an der Abschlussübung in der letzen Sitzung. Eine regelmäßige Teilnahme ist bei mehr als dreimaligen Fehlen nicht mehr gegeben. 60 B.1 Spezielle Prolog-Übungszeiten • Mi 12-13 • Do 17-18 Bei Fragen zu Prolog kann Hyeon-Young Lee zu diesen Zeiten helfen. C Seminarplan 18.10.01 Plenum: bis Abschnitt 3. Gruppe II: Hausaufgabe bis zur nächsten Sitzung: Übung 3.1.2a–2e 25.10.01 Gruppe I: Hausaufgabe bis zur nächsten Sitzung: Übung 3.1.2a– 2e; Plenum: bis Abschnitt 4.3; Gruppe II: Hausaufgabe bis zur nächsten Sitzung: Übung 4.1 8.11.01 Gruppe I: Übung 5.3.1 begonnen, Hausaufgabe bis zur nächsten Sitzung: Übung 5.3.1 zuende, Übungen 5.3.2, 5.3.5, 5.3.6 (anders als angekündigt: 5.3.3 und 5.3.4 sind fakultativ!); Plenum: bis Algorithmus P-5-2; Gruppe II: Übungen 5.3.1, 5.3.2, Hausaufgabe bis zur nächsten Sitzung: Übungen 5.3.5, 5.3.6 15.11.01 Gruppe I: Übung 5.3.5, Hausaufgabe bis zur nächsten Sitzung: 5.3.6; Plenum: bis Abschnitt 5.2 einschließlich; Gruppe II: Übungen 5.3.5, 5.3.6, Übung 5.5.1 angefangen, Hausaufgabe bis zur nächsten Sitzung: 5.5.1-10. 22.11.01 Gruppe I: Übung 5.3.6; Übung 5.5.1 angefangen, Hausaufgabe bis zur nächsten Sitzung: 5.5.1-10; Plenum: bis Definition D-5-4; Gruppe II: bis Übung 5.5.4, Hausaufgabe bis zur nächsten Sitzung: 5.5 zuende. 29.11.01 Gruppe I: Übung 5.5.1, Hausaufgabe bis zur nächsten Sitzung: wie 28.11.01; Plenum: bis Satz 5.1; Gruppe II: bis Übung 5.5.10, Hausaufgabe bis zur nächsten Sitzung: wie 28.11.01 06.12.01 Gruppe I: bis Übung 5.5.11, Hausaufgabe bis zur nächsten Sitzung Übung 5.5 zuende; Plenum: bis Abschnitt 5.6 einschl.; Gruppe II: Übung 5.5 zuende, Hausaufgabe bis zur nächsten Sitzung: nichtrekursive Lösung für Übungen 5.3.3-4. 61 13.12.01 Gruppe I: Übung 5.5 zuende; Hausaufgabe bis zur nächsten Sitzung: nicht-rekursive Lösung für Übungen 5.3.3-4; Plenum: bis Algorithmus P-5-4; Gruppe II: Übungen 5.3.3-4, Hausaufgabe bis zur nächsten Sitzung: Anfragen charakterisieren, bei denen die rekursive Lösung zu Übung 5.3.3 einen Speicherüberlauf erzeugt. 20.12.01 Gruppe I: Übungen 5.3.3-4, Hausaufgabe bis zur nächsten Sitzung: Anfragen charakterisieren, bei denen die rekursive Lösung zu Übung 5.3.3 einen Speicherüberlauf erzeugt; Plenum: bis Definition D6-2; Gruppe II: Hausaufgabe bis zur nächsten Sitzung: Übung 6.1.1 zuende, Übung 6.1.3. 10.1.01 Gruppe I: Hausaufgabe bis zur nächsten Sitzung: Übung 6.1.1 zuende. Plenum: Übung 6.1.5 bis 6.1.5d, Hausaufgabe zur nächsten Sitzung: 6.1.5e, Test 1 http://www.ikp.uni-bonn.de/dt/lehre/materialien/prolog/test1.pdf Testlösungen können bei mir zur Durchsicht abgegeben werden; Gruppe II: Übung 6.1.6 bis 6.1.6b. Hausaufgabe bis zur nächsten Sitzung: Übung 6.1.6.6b zuende, Übung 6.1.6 möglichst ganz lösen. 17.1.02 Gruppe I: Übung 6.1.6a, Hausaufgabe bis zur nächsten Sitzung: Übung 6.1.6b; Plenum: Übung 6.1.5 bis 6.1.5g, Hausaufgabe bis zur nächsten Sitzung: Übung 6.1.5h; Gruppe II: bis 6.1.6e, Hausaufgabe bis zur nächsten Sitzung: Übung 6.1.6 ganz lösen. 24.1.02 Gruppe I: Übung 6.1.6b–6c, Hausaufgabe bis zur nächsten Sitzung: Übung 6.1.6 zuende; Plenum: bis Übung 7.1 ausschließlich, Hausaufgabe bis zur nächsten Sitzung Übung 7.1.1; Gruppe II: Übung 6.1.6 zuende, Übungen 7.1.2–5, Hausaufgabe bis zur nächsten Sitzung: Übungen 7.1.6, 7.2.2–3; 31.1.02 Gruppe I: Übungen 6.1.6d–6e, 7.2.2–4, Hausaufgabe bis zur nächsten Sitzung Übung 7.2 zuende; Plenum: Abschnitte 8–10, als Vorbereitung für die Klausur/Abschlussübung empfohlen: Übung 9.1 und Test 2 http://www.ikp.uni-bonn.de/dt/lehre/materialien/prolog/test2.pdf Testlösungen, die bei mir bis zum 4.2.01 18:00 zur Durchsicht abgegeben werden, können nachgesehen am 6.2.01 zwischen 14:00 und 15:00 abgeholt werden; Gruppe II: Abschnitt 6.1, Übung 7.2.2–3, Übungsempfehlung bis zur nächsten Sitzung: 7.2 zuende; 62 7.2.02 Sitzung fällt aus. 14.2.02 Gruppe I: Übung 7.2 zuende; Übung 9.1.2; Plenum: Klausur/Abschlussübung D Einrichten des XEmacs für SWI-Prolog Um den XEmacs für die Arbeit mit SWI-Prolog vorzubereiten ist im Menübalken Help/Customize/Specific Groups auszuwählen und als Gruppe Prolog einzugeben. Anschließend kann man Prolog Program Name auf pl und Prolog Consult String auf consult(user) setzen. Der Prolog-Mode für eine Datei wird mit ESC-x prolog-mode aufgerufen, ein Buffer mit Prolog wird gestartet durch ESC-x run-prolog, markierte Teile einer gerade editierten Prolog-Datei können mit ESC-x prolog-consult-region oder Strg-Alt-x konsultiert werden. E Links SWI-Prolog-Manual http://www.swi.psy.uva.nl/projects/SWI-Prolog/Manual/Contents.html Blackburn/Bos/Striegnitz: Learn Prolog Now http://www.coli.uni-sb.de/∼kris/prolog-course/ Prolog Tutorial von J.R. Fisher http://www.csupomona.edu/∼jrfisher/www/prolog tutorial/intro.html On-Line Guide to Prolog Programming von Roman Barták http://ktiml.mff.cuni.cz/∼bartak/prolog/ Darin auch eine kleine Prolog-Implementierung, die in WWW-Browsern lauffähig ist, s. Test Zone. The Language Guide: Prolog http://www.engin.umd.umich.edu/CIS/course.des/cis400/prolog/prolog.html Nilsson/Maluszynski: Logic, Programming and Prolog (2ed) http://www.ida.liu.se/∼ulfni/lpp/ Lehrbuch zum freien Download 63 ISO-Prolog-Standard http://pauillac.inria.fr/∼hodgson/prolog/ Practical Standard Prolog Courseware Initiative http://www.ifcomputer.com/PrologCourse/ Prolog Tutorials von James Power http://www.cs.may.ie/∼jpower/Courses/PROLOG/ Prolog Cafe: A Prolog to Java Translator System http://kaminari.scitec.kobe-u.ac.jp/PrologCafe/ Freie Prolog-Compiler und Interpreter http://www.thefreecountry.com/developercity/prolog.html Literatur [Cov94] Covington, Michael A.: Natural Language Processing for Prolog Programmers. Prentice Hall, Englewood Cliffs, New Jersey, 1994. [DEDC96] Deransart, Pierre, AbdelAli Ed-Dbali, and Laurent Cervoni: Prolog: The Standard. Reference Manual. Springer, Berlin; Heidelberg; New York, 1996. 1 [KS89] König, Esther und Roland Seiffert: Grundkurs PROLOG für Linguisten. UTB für Wissenschaft: Uni-Taschenbücher 1525. Francke, Tübingen, 1989. [Leh90] Lehner, Christoph: Prolog und Linguistik. Neue Software. R. Oldenbourg Verlag, München, Wien, 1990. [Sho94] Shoham, Yoav: Artificial Intelligence Techniques in Prolog. Morgan Kaufmann Publishers, San Francisco, Cal., 1994. [SS86] Sterling, Leon and E. Shapiro: The Art of Prolog. Advanced Programming Techniques, with a foreword by David H.D. Warren. The MIT Press, Cambridge, Mass.; London, England, 1986. [Yas95] Yasdi, Ramin: Logik und Programmieren in Logik. Prentice Hall, München etc., 1995. 64