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