PROLOG

Werbung
PROLOG
Lernende Systeme
WS 10/11
Crashkurs
Martin Sticht
Stephan Weller
SWI Prolog
http://www.swi-prolog.org
Grundlegendes
Grundkonstrukte
• Fakten
• Regeln
• Anfragen
 Fakten und Regeln kommen in die Programm-Datei
 Anfragen werden dem Interpreter gestellt
Jede Anweisung endet mit „.“
Prolog-Programme werden in SWI mit
consult(dateiname).
geladen
(Dateiname ohne Endung,
Punkt nicht vergessen!)
Fakten
• Fakten sind instanziiert
• Instanzen werden klein geschrieben!
father(bart, homer).
mother(bart, marge).
sister(bart, lisa).
sister(bart, maggie).
brother(lisa, bart).
brother(maggie, bart).
hasChild(marge).
hasChild(homer).
Achtung: Kein Leerzeichen zwischen Prädikatname und Klammer
Die vorliegenden Fakten so zu definieren kann zu Problemen führen (siehe später)
Anfragen (1)
father(bart,homer).
mother(bart,marge).
sister(bart,lisa).
sister(bart,maggie).
brother(lisa,bart).
brother(maggie,bart).
family.pl
Variablen werden GROSS geschrieben.
Bei Anfragen mit Variablen werden alle möglichen Instanzen für die Variablen ausgegeben.
ACHTUNG: Die Instanzen erscheinen nacheinander jedes Mal, wenn ; gedrückt wird
Anfragen (2)
father(bart,homer).
mother(bart,marge).
sister(bart,lisa).
sister(bart,maggie).
brother(lisa,bart).
brother(maggie,bart).
?- sister(X,Y).
X = bart,
Y = lisa ;
X = bart,
Y = maggie.
?- mother(maggie,X).
Action (h for help) ?
continue
false.
Viele Fakten vergessen!
Prädikate vielleicht sinnvoller wählen?
1. Bindung
2. Bindung
Drücke c für „continue“
oder a für „abort“
oder e für „exit“
Regeln (1)
<Konklusion> :- <Bedingung1>, <Bedingung2>, ...
Wie Logik (nur andersrum):
Konklusion
Bedingung1 /\ Bedingung2 /\....
• :- steht für
• , steht für /\
Für Regeln werden Variablen verwendet:
father(X,Y) :- gender(Y, male), parent(X,Y).
Y ist Vater von wenn Y männlich ist UND Y Elternteil von X ist
Regeln (2)
?- sister(X,Y).
X = bart,
Y = lisa ;
X = bart,
Y = maggie ;
X = lisa,
Y = maggie ;
X = maggie,
Y = lisa ;
false.
father(X,Y)
mother(X,Y)
grandpa(X,Y)
child(X,Y)
sister(X,Y)
:::::-
Neue Fakten:
parent(bart, homer).
parent(bart, marge).
parent(lisa, homer).
parent(lisa, marge).
parent(maggie, homer).
parent(maggie, marge).
parent(homer, ape).
gender(bart, male).
gender(lisa, female).
gender(maggie, female).
gender(homer, male).
gender(marge, female).
gender(ape, male).
gender(Y, male), parent(X,Y).
gender(Y, female), parent(X,Y).
parent(X,Z), father(Z,Y).
parent(Y,X).
father(X,Z), father(Y,Z), mother(X,W), mother(Y,W),
gender(Y,female), not(X==Y).
Regeln (3)
Alternativen / ODER-Verknüpfungen
schmecktGut(zucker).
schmecktGut(X) :- enthaelt(X,zucker).
WICHTIG:
Der Prolog-Interpreter sucht die Fakten/Regeln von oben nach unten ab.
Deshalb immer Fakten VOR Regeln!
Es geht auch rekursiv:
schmecktGut(zucker).
schmecktGut(sahne).
schmecktGut(X) :- enthaelt(X,Y),
schmecktGut(Y).
Auch hier die Fakten als Abbruchbedingungen vor den rekursiven Regeln!
Weiteres
Negation by failure
Werden keine passenden Variablenbindungen
gefunden oder gibt es das Faktum nicht
?- brother(simon, bernd).
 false
false.
Vergleiche
X == Y
> < >=
not(X == Y)
=<
Listen (1)
• Listen sind eigentlich auch nur zusammengesetzte Terme,
bei denen der Funktor ein Punkt ist.
• Um die Sache zu vereinfachen, kann man Listen mit eckigen
• Klammern notieren: [1,2,’drei’,4.2,X]
• Die Punkt-Notation funktioniert aber auch:
.(1,.(2,.(3,[])))
• Außerdem gibt es noch die Head-Tail-Notation (wichtig!) in
der Form [Erstes|Rest], wobei Erstes das erste
Element der Liste ist und Rest der Rest.
mylist([1|[2,3,4]]).
?- mylist(X).
X = [1, 2, 3, 4].
• weiteres Beispiel: .(4,[5|.(6,[])]) ≡ [4,5,6]
Listen (2)
Rekursion mit Listen:
even([]).
even([X,Y|R]) :- even(R).
?- even([1,2,3]).
false.
last([X],X).
last([X|R],Y) :- last(R,Y).
?- even([1,2,3,5]).
true.
Ablauf even:
[1,2,3]
even([]).
even(X,Y|R)
[3]
even([]).
even(X,Y|R)
 FALSE
Ablauf last:
-- FALSE
-- X=1, Y=2, R=[3]
[1,2], X
last[[X],X]
-- FALSE
last([X|R],Y) -- X=1, R=[2]
-- FALSE
-- X=3, ..???-
[2], X
last[[X],X])
 TRUE
-- X=2
Ohne Funktionen?
• Prolog ist nicht funktional!
Haskell:
last [1,2,3,4]  4
• Prolog behandelt nur Wahrheitswerte!
 Deshalb Ergebnis als Variable
last([1,2,3,4],4) 
True
last([1,2,3,4],X)  X = 4
True
Cut! (1)
Wie ist eigentlich not/1 implementiert?
not(X) :- X, !, fail.
not(_).
fail schlä̈gt immer fehl.
Der Cut-Operator (!) heißt so viel wie:
An dieser Stelle keine anderen Möglichkeiten ausprobieren.
• Genauer: Prolog führt in den Pr ädikaten eine Tiefensucheaus, falls es auf
den Cut-Operator trifft, schneidet es alle anderen Möglichkeiten ab
(daher der Name).
• Steht der Cut am Ende einer Regel, so wird das Prädikat beim Erreichen
des ! erfolgreich. Beim evtl. Backtracking werden keine Alternativen für
dieses Prädikat gesucht. Durch fail wird ein Misserfolg verzeichnet.
Cut! (2)
• Wichtigste Funktion:
Unnötige Teile des Suchraums abschneiden.
• Man spricht auch von einem Green Cut.
• Einfaches Beispiel:
minimum(X,Y,X) :- X <= Y, !.
minimum(X,Y,Y) :- X > Y, !.
• Wenn x ≤ y stimmt, wird das zweite Prädikat gar
nicht mehr angesehen.
• Die Implementation ist also effizienter, ohne
logisch etwas zu verändern
Cut! (3)
• Aber es gibt natürlich auch einen Red Cut. Ein
solcher verändert das Ergebnis und kann auch
(bei falschem Einsatz) zu unerwünschten
Ergebnissen führen.
• Beispiel:
minimum(X,Y,X) :- X <= Y, !.
minimum(X,Y,Y).
Was stimmt hier nicht?
Was ist z.B. mit minimum(2,5,5).?
Listen und Mengen (1)
• append(?List1, ?List2, ?List3)
List1 an List2 gehängt ergibt List3
• member(?Elem, ?List)
Elem ist ein Element von List
• last(?List, ?Elem)
Elem ist das letzte Element von List
• reverse(+List1,-List2)
List1 umgedreht ergibt List2
• flatten(+List1,-List2)
List2 ist List1 ganz ohne Schachtelungen
Listen und Mengen (2)
• is_set(+Set)
Set ist eine Menge
• list_to_set(+List, -Set)
Set ist die Menge der Elemente aus List
• intersection(+Set1, +Set2, -Set3)
Schnitt von Mengen
• substract(+Set, +Delete, -Result)
Mengendifferenz
• union(+Set1, +Set2, -Set3)
Vereinigungsmenge
• subset(+Subset, +Set)
Teilmenge
Herunterladen