Logik für Informatiker 3 Wintersemester 2012/13 Logikprogrammierung P ROLOG ermöglicht • deklarative Programmierung • kompakte Programme • agile Softwareentwicklung, rapid Prototyping Die Auswertungsstrategie der SLDNF–Resolution benutzt • Tiefensuche • Backtracking • Unifikation Prof. Dr. Dietmar Seipel 298 Logik für Informatiker 3.1 Wintersemester 2012/13 Grundlagen von P ROLOG Datentypen und Datenstrukturen • Die Beschränkung auf wenige Basisdatentypen und einen einzigen komplexen Datentyp, nämlich die Strukturen (Terme), der generisch ist und alle anderen Datentypen subsumiert, standardisiert die Datenstrukturen ganz entscheident. • Es gibt keine expliziten Typdeklarationen. Man kann aber rein syntaktisch zwischen P ROLOG–Atomen (Strings), Zahlen und Variablensymbolen unterscheiden; aus diesen kann man komplexere Strukturen (Terme) bilden. • Es gibt eine große Kollektion von generischen Operationen, die auf alle Strukturen (Terme) anwendbar sind – und somit auf alle Datentypen. Prof. Dr. Dietmar Seipel 299 Logik für Informatiker Wintersemester 2012/13 Methoden und Kontrollstrukturen • Prädikate realisieren Methoden. Alle Parameter – auch die Rückgabewerte – werden als Argumente eines Prädikats übergeben. Kommentare helfen zu erkennen, welche Argumente die Eingabe bzw. die Ausgabe bilden. • Manche Prädikate kann man mit unterschiedlichen Bindungsmustern aufrufen, und für dieselbe Eingabe kann es unterschiedliche Ausgaben geben (relationales Programmieren). Die meisten Prädikate sind aber funktional. • Häufig werden Meta–Prädikate verwendet. Auch Kontrollstrukturen basieren auf Meta–Prädikaten. Zusätzlich zu den Standardkontrollstrukturen, wie Verzweigungen (if–then–else), Schleifen (for, while), und Rekursion, können benutzerdefinierte Kontrollstrukturen in Form von Meta–Prädikaten gebildet werden. Prof. Dr. Dietmar Seipel 300 Logik für Informatiker Wintersemester 2012/13 Strukturen in P ROLOG P ROLOG–Atom: z.B. a, books, ’Books’, kt_321_xy Konstante: P ROLOG–Atom | Number: z.B. books, 0, 123 Variable: beginnend mit Großbuchstaben oder mit “_” z.B. X, Y, Books, _, _A, _a Funktor (Funktions– bzw. Prädikatensymbol): Operator | P ROLOG–Atom: z.B. +, -, ≤, ancestor Struktur: Konstante | Variable | Funktor(Struktur, . . . , Struktur) z.B. +(1,7), ancestor(’William’,’Elizabeth’) Listen sind spezielle Strukturen zum Funktor “.”: [a,b,c,d] = .(a, [b,c,d]) +(1,7) ist äquivalent zu 1+7 (Infix–Notation). Prof. Dr. Dietmar Seipel 301 Logik für Informatiker Wintersemester 2012/13 P ROLOG–Klauseln Eine P ROLOG–Klausel (Regel, Fakt) ist eine Infix–Struktur der Form Kopf :– Rumpf. “:-” spricht man dabei als “falls” aus. Falls der Rumpf leer ist (Fakt), so kann man “:-” weglassen und kurz “Kopf” schreiben. Der Regelrumpf kann folgende Junktoren enthalten: • Konjunktion “,”, • Disjunktion “;”, und • Negation “\+”, “not”. Eine negierte Formel kann man als “\+ F” oder als “not(F)” schreiben. Prof. Dr. Dietmar Seipel 302 Logik für Informatiker Wintersemester 2012/13 Prädikatensymbole: ancestor, parent Regel: ancestor(X, Z) :ancestor(X, Y), parent(Y, Z). Eine Elternteil Z eines Vorfahren Y von X ist ebenfalls ein Vorfahre. In der PL1 könnte man das wie folgt schreiben: ∀X∀Y ∀Z ( ancestor(X, Y ) ∧ parent(Y, Z) → ancestor(X, Z) ) Fakten: parent(a, b). parent(b, c). parent(c, d). Goal: ?- ancestor(a, Z). Prof. Dr. Dietmar Seipel 303 Logik für Informatiker Wintersemester 2012/13 Prädikatensymbole: likes, woman, nice, loves Regeln: likes(george, Y) :woman(Y), likes(Y, books). likes(mary, Y) :( nice(Y) ; loves(Y, cats) ) Fakten: woman(mary). likes(mary, books). loves(george, cats). Goal: ?- likes(george, Y).} Prof. Dr. Dietmar Seipel 304 Logik für Informatiker Wintersemester 2012/13 Das Prädikat likes besteht aus 2 Regeln und einem Fakt. Diese decken unterschiedliche Fälle ab: • Die erste Regel besagt, daß George alle Frauen mag, die Bücher mögen. • Die zweite Regel besagt, daß Mary alles, was schön (nice) ist, und alle Lebewesen, die Katzen lieben, mag. Ein Fakt besagt außerdem, daß Mary Bücher mag. In der prozeduralen Programmierung könnte man eine Fallunterscheidung in einem case–Statement ausdrücken. Die likes–Regel zu Mary mit dem disjunktiven Rumpf könnte man in zwei separate Regeln zerlegen. Die Bündelung der Information zu Mary – zu der man eventuell auch noch das Fakt hinzunehmen könnte – erscheint aber softwaretechnisch auch sehr sinnvoll. Da uns momentan keine Information zu nice vorliegt, ist der erste Teil der Regel inaktiv. Prof. Dr. Dietmar Seipel 305 Logik für Informatiker Wintersemester 2012/13 Die Bündelung liefert folgende Regel mit einem disjunktiven Regelrumpf: likes(mary, Y) :( nice(Y) ; loves(Y, cats) ; Y = books ). Diese ist äquivalent zu drei einzelnen Regeln: likes(mary, nice(Y). likes(mary, loves(Y, likes(mary, Y) :Y) :cats). books). Die Reihenfolge der Regeln und Fakten zum selben Prädikatensymbol ist – wie in klassischen Programmiersprachen auch – wichtig. Prof. Dr. Dietmar Seipel 306 Logik für Informatiker Wintersemester 2012/13 Notation Wenn man geeignete Operatoren (Infix, Präfix, Postfix) definiert, dann kann man die P ROLOG–Klauseln etwas natürlicher notieren: X has_ancestor Z :X has_ancestor Y and Y has_parent Z. george likes Y :Y is_a_woman and Y likes books. mary likes Y :Y is_nice or Y loves cats. mary is_a_woman. mary likes books. george loves cats. Man könnte H :- B sogar als B implies H schreiben. Prof. Dr. Dietmar Seipel 307 Logik für Informatiker Wintersemester 2012/13 Anfragen in P ROLOG Ein P ROLOG–Interpreter versucht ein Goal durch Inferenz zu beweisen. Dies erfolgt Top–Down vom Goal ausgehend durch DFS–Durchlauf (Tiefensuche, Depth–First–Search) des SLD–Baumes. Beispiel (Anfragen) ?- likes(george, Y). Y = mary ?- likes(X, X = george, X = mary, Y X = mary, Y Prof. Dr. Dietmar Seipel Y). Y = mary ; = george ; = books 308 Logik für Informatiker Wintersemester 2012/13 P ROLOG gibt eine Antwort auf eine Anfrage zurück: • Falls die Anfrage erfolgreich beantwortet wurde, so gibt P ROLOG die erzeugte Variablenbelegung als Antwort zurück; falls keine Variablen belegt wurden, so ist die Antwort true. • Falls die Anfrage erfolglos beantwortet wurde, so ist die Antwort false. Bei erfolgreicher Beantwortung der Anfrage kann man hinter der Antwort einen Strichpunkt gefolgt von Return eingeben. Dieser stößt Backtracking an, so daß P ROLOG versucht eine weitere Antwort zu finden. Wenn man nur Return eingibt, so ist die Anfrageauswertung beendet. Ebenso ist die Anfrageauswertung nach der Antwort false automatisch sofort beendet. Prof. Dr. Dietmar Seipel 309 Logik für Informatiker Wintersemester 2012/13 Auswertung von Anfragen in P ROLOG • Die Auswertung von P ROLOG–Regeln erfolgt Top–Down mittels der Methode der SLDNF–Resolution: aus einer Anfrage an das Kopfatom einer Regel werden Unteranfragen an die Rumpfatome erzeugt. • Dies entspricht dem Vorgehen bei der Abarbeitung von prozeduralen Programmiersprachen. • Falls ein Rumpfatom mehrere Antworten liefert, so wird zuerst mit einer solchen Antwort weitergerechnet (Tiefensuche); falls die Berechnung später fehlschlägt, so kann mit der nächsten Antwort fortgefahren werden (Backtracking). • In der Praxis sind viele P ROLOG–Prädikate aber funktional: aus einer Eingabe wird genau eine Ausgabe erzeugt. Prof. Dr. Dietmar Seipel 310 Logik für Informatiker Wintersemester 2012/13 Aus der Anfrage ← likes(X, Y ) wird mittels der Ersetzung X 7→ george und der Regel r1 = likes(george, Y ) ← woman(Y ) ∧ likes(Y , books) eine Folge von Unteranfragen erzeugt: ← woman(Y ) ∧ likes(Y , books) Aufgrund des Fakts f1 wird die erste Unteranfrage mit Y 7→ mary beantwortet. Der neue Wert für Y wird in der zweiten Unteranfrage sofort berücksichtigt, so daß wir also ← likes(mary, books) zu beantworten haben. Aufgrund des Fakts f2 ist die Antwort dafür ja. Prof. Dr. Dietmar Seipel 311 Logik für Informatiker Wintersemester 2012/13 SLD–Baum ← likes(X, Y ) r1 9 ← woman(Y ) ∧ likes(Y, books) f1 ? ← likes(mary, books) r2 ← nice(books) ∨ loves(books, cats) failure r2 ? f2 q ← nice(Y ) ∨ loves(Y, cats) 2 {X 7→ mary, Y 7→ books} f3 success ? 2 {X → 7 mary, Y 7→ george} f2 j success 2 {X 7→ george, Y 7→ mary} success Der SLD–Baum faßt alle SLD–Ableitungen zusammen. Jeder success–Ast gibt eine Antwort. Prof. Dr. Dietmar Seipel 312 Logik für Informatiker Wintersemester 2012/13 Kontrollprimitive, welche über die PL1 hinausgehen: • assert und retract verändern die interne Datenbank von P ROLOG; clause sucht in dieser. • call und apply rufen Goals auf, die vorher zusammengebaut werden können. • Der Cut “!” friert die bisherige Variablenbelegung in der aktuellen Regel ein. • fail ist ein Goal, das immer fehl schlägt. • Meta–Prädikate wir findall und maplist realisieren komplexe Kontrollstrukturen. • ... Prof. Dr. Dietmar Seipel 313 Logik für Informatiker Wintersemester 2012/13 Anfrage mit einem Meta–Prädikat Mit dem Meta–Prädikat findall/3 kann man alle Antworten auf eine Anfrage bestimmen: ?- findall( [X, Y], likes(X, Y), Pairs ). Pairs = [[george,mary], [mary,george], [mary,books]]. Das D DK erlaubt sogar folgende äquivalente Mengenschreibweise: ?- Pairs <= { [X, Y] | likes(X, Y) }. Pairs wird als die Liste aller Paare [X, Y] bestimmt, für die likes(X, Y) gilt. Prof. Dr. Dietmar Seipel 314 Logik für Informatiker Wintersemester 2012/13 Listen sind spezielle P ROLOG–Strukturen mit dem binären Funktor “.”. Liste: [a,b,c,d] = .(a,.(b,.(c,.(d,[])))) Listenkonstruktion: Falls X und Xs bereits gebunden (mit Werten belegt) sind, so ist [X|Xs] die Liste, die man erhält, wenn man das Element X an die Liste Xs vorne anhängt. Für X = a und Xs = [b,c,d] ist [X|Xs] = [a,b,c,d]. Listenzerlegung: Falls X und Xs ungebunden sind, so liefert der Aufruf [X|Xs] = [a,b,c,d] die Belegungen X = a und Xs = [b,c,d]; man kann eine Liste also in ihren Kopf X und den Rest Xs zerlegen. leere Liste: [] Prof. Dr. Dietmar Seipel 315 Logik für Informatiker Wintersemester 2012/13 Listenkonstruktion und Listenzerlegung erfolgen also mittels desselben Aufrufs Xs = [Head|Tail]. Die folgenden beiden Prädikate bestimmen das erste Listenelement Head und den Rest Tail der Liste. list_to_head(Xs, Head) :Xs = [Head|_]. list_to_tail(Xs, Tail) :Xs = [_|Tail]. Um eine “singleton variable warning” zu vermeiden, wird der jeweils nicht benötigte Listenteil mittels einer anonymen Variable “_” (Wildcard) bezeichnet. Prof. Dr. Dietmar Seipel 316 Logik für Informatiker Wintersemester 2012/13 Die Listenschreibweise [X1 , . . . ,Xn ] nennt man Syntactic Sugar. Eine Liste ist eigentlich eine stark verschachtelte binäre Struktur: .( X1 , .(X2 , . . . ,.(Xn ,[]))). {z } |{z} | Tail Head Somit ist Xs = [Head|Tail] = .(Head, Tail). Für Xs = [a,b,c,d] = .(a,.(b,.(c,.(d,[])))) bestimmt der Aufruf Xs = [Head|Tail], oder .(a,.(b,.(c,.(d,[])))) = .(Head, Tail), mittels Unifikation Head = a und Tail = .(b,.(c,.(d,[]))). Prof. Dr. Dietmar Seipel 317 Logik für Informatiker Wintersemester 2012/13 Die Listenkonstruktion aus einem gegebenen Kopf und einem Rest erfolgt – wie bereits gezeigt – auch mittels des Aufrufs Xs = [Head|Tail]: head_and_tail_to_list(Head, Tail, Xs) :Xs = [Head|Tail]. Dasselbe Prädikat kann man auch benutzen, um eine gegebene Liste in Kopf und Rest zu zerlegen: ?- head_and_tail_to_list([a], [b,c,d], Xs). Xs = [a,b,c,d]. ?- head_and_tail_to_list(Head, Tail, [a,b,c,d]). Head = [a], Tail = [b,c,d]. Prof. Dr. Dietmar Seipel 318 Logik für Informatiker Wintersemester 2012/13 Arbeiten mit Termen • Aufbau und Zerlegung: =../2 • functor/3 • arg/3 ?- likes(mary, books) =.. Xs. Xs = [likes, mary, books]. ?- functor([a,b,c,d], F, N). F = ’.’, N = 2. ?- arg(N, [a,b,c,d], A). N = 1, A = a ; N = 2, A = [b,c,d]. Prof. Dr. Dietmar Seipel 319 Logik für Informatiker Wintersemester 2012/13 Eingabe und Ausgabe • Einlesen einer P ROLOG–Datei: consult/1, [...] • Eingabe von Termen: read/1,2 • Ausgabe von Termen: write/1,2 ?- [’sources/projects/teaching/likes.pl’]. % sources/.../likes.pl compiled 0.00 sec, 0 bytes ?- read(X). |: likes(mary, cats). X = likes(mary, cats). ?- write(likes(mary, cats)). likes(mary, cats) Die zweistelligen Prädikate read/2 und write/2 greifen auf Dateien zu. Prof. Dr. Dietmar Seipel 320 Logik für Informatiker Wintersemester 2012/13 Man kann mittels assert/1 auch dynamisch die Datenbasis von P ROLOG erweitern: ?- read(X), assert(X). |: likes(mary, cats). X = likes(mary, cats). Nachfolgende Aufrufe können die erweiterte Datenbasis benutzen: ?- likes(mary, cats). true. Mittels retract/1 kann man in der Datenbasis von P ROLOG löschen. Prof. Dr. Dietmar Seipel 321 Logik für Informatiker Wintersemester 2012/13 Aufruf dynamischer Goals Man kann zur Laufzeit mittels =../2 Goals zusammenbauen und mittels call/1 aufrufen: ?- read(P), Goal =.. [P, X, Y], call(Goal). |: likes. P = likes, Goal = likes(X, Y), X = george, Y = mary. Dies geht noch eleganter, wenn man stattdessen apply/2 verwendet, denn Goal =.. [P,X1,...,Xn], call(Goal) ist äquivalent zu apply(P, [X1,...,Xn]). Der Aufruf read(P), P(X,Y) ist in P ROLOG nicht erlaubt, da eine Variable – hier P – nicht an der Stelle eines Prädikatensymbols stehen kann. Prof. Dr. Dietmar Seipel 322 Logik für Informatiker Wintersemester 2012/13 Rekursion: das Prädikat member /* member(?X, +Xs) <X is a member of the list Xs. */ member(X, [X|_]). member(X, [_|Xs]) :member(X, Xs). ?- member(b, [a,b,c]). true. Ein Element liegt in einer Liste, falls es das erste Listenelement (Listenkopf) ist, oder falls es in der Restliste liegt (rekursiver Aufruf). Genauer gesagt wird eine Substitution gesucht, die X mit einem Element der Liste Xs unifiziert. Prof. Dr. Dietmar Seipel 323 Logik für Informatiker Wintersemester 2012/13 In dieser kompakten Notation wird die Eingabeliste bereits im Regelkopf in den Listenkopf und die Restliste zerlegt. 1. Der Kopf der ersten Regel testet auch gleich, ob der Listenkopf mit dem gesuchten Element unifizierbar ist. 2. Die zweite Regel sucht in der Restliste rekursiv weiter. Zur Verdeutlichung geben wir im folgenden die entsprechende Langfassung an: member(X, Xs) :list_to_head(Xs, Head), X = Head. member(X, Xs) :list_to_tail(Xs, Tail), member(X, Tail). Prof. Dr. Dietmar Seipel 324 Logik für Informatiker Wintersemester 2012/13 Relationales Programmieren member: Element × List 7→ Boolean ?- member(b, [a,b,c]). true. ?- member(X, [a,b,c]). X = a ; X = b ; X = c Beim Aufruf member(X, Xs) sind X und Xs nicht funktional voneinander abhängig. Stattdessen realisiert member/2 eine n : m–Beziehung (Relation) zwischen Listen und ihren Elementen. Prof. Dr. Dietmar Seipel 325 Logik für Informatiker Wintersemester 2012/13 Das Prädikat member/2 definiert eine virtuelle Relation: member Element List a [a,b,c] b [a,b,c] c [a,b,c] a [a,b] ... ... Diese Relation ist unendlich, sie wird aber nie berechnet. Es werden meist nur die Elemente einer gegebenen Liste bestimmt. Prof. Dr. Dietmar Seipel 326 Logik für Informatiker Wintersemester 2012/13 Tracing Man kann die Anfrageauswertung in P ROLOG mittels trace schrittweise verfolgen: ?- trace. true. [trace] ?- member(X, [a,b]). Call: (6) member(X, [a, b]) ? creep Exit: (6) member(a, [a, b]) ? creep X = a ; Der initiale Aufruf member(X, [a,b]) wird zuerst mit dem Fakt member(X, [X|_]) unifiziert. Dabei wird X auf a gesetzt und die anonyme Variable (Wildcard) _ auf [b]. Somit ergibt sich die erste Antwort X = a. Prof. Dr. Dietmar Seipel 327 Logik für Informatiker Wintersemester 2012/13 Die Eingabe des Strichpunkts hinter der Antwort X = a stößt Backtracking an: Redo: Call: Exit: Exit: X = b ; (6) (7) (7) (6) member(X, member(X, member(b, member(b, [a, b]) ? creep [b]) ? creep [b]) ? creep [a, b]) ? creep Nun wird der Aufruf member(X, [a,b]) mit dem Kopf member(X, [_|Xs]) der Regel unifiziert. Dabei wird X belassen, und es wird _ auf a und Xs auf [b] gesetzt. Der neue Aufruf member(X, [b]) ergibt sich aus dem Rumpf der Regel. Er wird mittels des Fakts mit X = b beantwortet (zweite Antwort). Prof. Dr. Dietmar Seipel 328 Logik für Informatiker Wintersemester 2012/13 Die Eingabe des Strichpunkts hinter der Antwort X = b stößt noch einmal Backtracking an: Redo: Call: Fail: Fail: Fail: Fail: false. (8) (9) (9) (8) (7) (6) member(X, member(X, member(X, member(X, member(X, member(X, [b]) ? creep []) ? creep []) ? creep [b]) ? creep [b]) ? creep [a, b]) ? creep Nun wird der Aufruf member(X, [b]) mit dem Kopf member(X, [_|Xs]) der Regel unifiziert. Dabei wird X belassen, und es wird _ auf b und Xs auf [] gesetzt. Der neue Aufruf member(X, []) ergibt sich aus dem Rumpf der Regel. Er kann nicht beantwortet werden. Also ergibt sich die Antwort false. Prof. Dr. Dietmar Seipel 329 Logik für Informatiker Wintersemester 2012/13 Bindungsmuster Einige Prädikate, wie z.B. das boolean_and/3, können mit unterschiedlichen Bindungsmustern für die Argumente aufgerufen werden: /* boolean_and(U, V, W) <W is derived as the boolean conjunction of the truth values U and V. */ boolean_and(0, boolean_and(0, boolean_and(1, boolean_and(1, 0, 1, 0, 1, 0). 0). 0). 1). Hier kann man beliebig viele (auch 0) Argumente mit Werten versehen und die restlichen Werte berechnen. Prof. Dr. Dietmar Seipel 330 Logik für Informatiker Wintersemester 2012/13 Wenn die ersten beiden Argumente gebunden sind, dann realisiert das Prädikat eine Funktion: ?- boolean_and(1, 0, W). W = 0 . Man kann die Berechnung umkehren, und nach allen Paaren von Wahrheitswerten U und V fragen, deren Konjunktion 0 ist; dann realisiert das Prädikat eine n : m–Beziehung (Relation): ?- boolean_and(U, V, 0). U = 0, V = 0 ; U = 0, V = 1 ; U = 1, V = 0 Dabei wird durch die Eingabe von ; hinter einer Lösung die Berechnung der nächsten Lösung angestoßen. Prof. Dr. Dietmar Seipel 331 Logik für Informatiker Wintersemester 2012/13 Arithmetik Im Gegensatz zum Unifikationsprädikat =/2 wertet das Prädikat is/2 den arithmetischen Ausdruck zu seiner rechten aus und unifiziert das Ergebnis mit dem Ausdruck zu seiner linken: ?- X = 3, Y is e^X + sin(X). X = 3, Y = 20.2267. Der entsprechende Aufruf mit =/2 würde Y dagegen lediglich mit dem Term e^3 + sin(3) unifizieren: ?- X = 3, Y = e^X + sin(X). X = 3, Y = e^3 + sin(3). Prof. Dr. Dietmar Seipel 332 Logik für Informatiker Wintersemester 2012/13 Symbolisches Differenzieren Das Prädikat diff/3 differenziert beim Aufruf diff(F, X, DF) einen Funktionsterm F symbolisch nach der Variablen X – die beim Aufruf durch eine Konstante instanziiert sein muß – und liefert DF als Ergebnis: ?- diff(e^x + sin(x), x, F). F = e^x + cos(x). ?- diff(x^7 + 3 * x^6, x, F). F = 7 * x^6 + 3 * 6 * x^5. Dasselbe Prädikat diff/3 kann bei einem anderen Bindungsmuster zum symbolischen Integrieren benutzt werden, wenn stattdessen X und DF gebunden sind. Bei den Aufrufen des folgenden Prädikats diff/3 muß die Unbekannte, nach der differenziert wird, durch ein P ROLOG–Atom repräsentiert sein. Prof. Dr. Dietmar Seipel 333 Logik für Informatiker Wintersemester 2012/13 Die ersten beiden Regeln behandeln die Spezialfälle, daß F identisch ist mit X, oder daß F ein anderes P ROLOG–Atom ist: % diff(+F, +X, ?DF) <% diff(?F, +X, +DF) <diff(X, X, 1) :!. diff(C, X, 0) :atomic(C). Der Cut, “!”, weist P ROLOG an, keine weiteren Regeln zu versuchen, falls die aktuelle Regel anwendbar ist. Ohne den Cut würde der Aufruf diff(x,x,DF) sowohl das Resultat DF=1 (die richtige Antwort aus Regel 1) als auch DF=0 (die falsche Antwort aus Regel 2) liefern. Prof. Dr. Dietmar Seipel 334 Logik für Informatiker Wintersemester 2012/13 diff(X^N, X, N*X^M) :N > 0, M is N - 1. diff(sin(X), X, cos(X)). diff(e^X, X, e^X). diff(F+G, X, DF+DG) :diff(F, X, DF), diff(G, X, DG). diff(C*F, X, C*DF) :atomic(C), !, diff(F, X, DF). Der Cut in der letzten Regel ist hier eigentlich nicht erforderlich. Er wird erst dann wichtig, wenn man das Regelsystem noch erweitert. Prof. Dr. Dietmar Seipel 335 Logik für Informatiker Wintersemester 2012/13 3.2 SLD– und SLDNF–Resolution Definites Logikprogramm, Anfrage 1. Ein definites Logikprogramm besteht aus Horn–Klauseln in Implikations–Notation mit jeweils genau einem Kopfatom: Fakt: A Regel: A ← B1 ∧ . . . ∧ Bm , m ≥ 0. Fakten stellen Wissen ohne Vorbedingung dar, Regeln mit m ≥ 1 konditionales Wissen mit Vorbedingung β = B1 ∧ . . . ∧ Bm . 2. Horn–Klauseln in Implikations–Notation ohne Kopfatom repräsentieren Anfragen: Goal: ← B1 ∧ . . . ∧ Bm , m ≥ 0. Dabei sind A und die Bi prädikatenlogische Atome. Prof. Dr. Dietmar Seipel 336 Logik für Informatiker Wintersemester 2012/13 Die SLD–Resolution (Linear Resolution with Selection Function for Definite Clauses) wurde ursprünglich zum automatischen Theorembeweisen für allgemeine Klauseln verwendet, vgl. J.A. Robinson (1965). • Sei s eine Selektionsfunktion, die aus jedem Goal ein Atom auswählt. • Sei G ein Goal und r = A ← β eine definite Regel: G = ← β1 ∧ B ∧ β2 . Dabei seien β1 und β2 Konjunktionen von Atomen und s(G) = B das von s selektierte Atom. Falls M GU (A, B) = θ existiert, dann heißt G′ = ← ( β1 ∧ β ∧ β2 ) θ eine Resolvente von G und r bezüglich s. Falls r ein Fakt ist (d.h. β ist leer), dann ist G′ um ein Atom kürzer als G. Prof. Dr. Dietmar Seipel 337 Logik für Informatiker Wintersemester 2012/13 Die SLD–Resolution ergibt sich aus der binären Resolution der PL1. Bekanntlich ist ein Goal G = ← β1 ∧ B ∧ β2 äquivalent zu einer Disjunktion α1 = ¬β1 ∨ ¬B ∨ ¬β2 , und eine Regel r = A ← β ist äquivalent zu einer Disjunktion α2 = A ∨ ¬β. Durch die bekannte binäre Resolution der PL1 erhält man mittels eines allgemeinsten Unifikators θ von A und B eine neue Disjunktion α = (¬β1 ∨ ¬β ∨ ¬β2 )θ, die wieder einem Goal G′ = ← ( β1 ∧ β ∧ β2 ) θ entspricht. Prof. Dr. Dietmar Seipel 338 Logik für Informatiker Wintersemester 2012/13 SLD–Widerlegung • Sei P ein definites Logikprogramm und Q eine Anfrage. Eine SLD–Widerlegung von h P, Q i ist eine endliche Folge h Gi i0≤i≤n , wobei G0 = Q und Gn = 2, von Goals zusammen mit einer Folge h ri i1≤i≤n von Regeln und einer Folge h θi i1≤i≤n von Substitutionen, wobei für alle 1 ≤ i ≤ n gilt: – ri ist eine Variante einer Regel aus P , – Gi ist eine Resolvente aus Gi−1 und ri bezüglich s, und – θi ist der benutzte allgemeinste Unifikator. Die Substitution θ = θ1 · θ2 · . . . · θn heißt Antwortsubstitution. • Die SLD–Widerlegung einer atomaren Anfrage Q = ← A ist äquivalent zu dem Beweis, daß die Instanz Aθ, welche man Antwort nennt, aus P abgeleitet werden kann. Prof. Dr. Dietmar Seipel 339 Logik für Informatiker Wintersemester 2012/13 • Ein SLD–Widerlegungsbaum veranschaulicht eine SLD–Widerlegung: G0 ? G1 ? G2 ? r1 r2 r3 G3 .. . .. . rn ? Gn = 2 Man kann eine SLD–Widerlegung natürlich auch einfach als eine r1 r2 r3 rn lineare Kette G0 −→ G1 −→ G2 −→ . . . −→ Gn = 2 repräsentieren, wenn man die Kanten mit den verwendeten Regeln markiert. Prof. Dr. Dietmar Seipel 340 Logik für Informatiker Wintersemester 2012/13 Beispiel (SLD–Resolution) Für das DATALOG–Programm P = { r, f1 , f2 }, mit r = p ← a ∧ b, f1 = a, f2 = b, erhalten wir mit der Selektionsfunktion sl eine SLD–Widerlegung zum Goal Q = ← p. ←p ? ←a∧b ? ←b ? 2 Prof. Dr. Dietmar Seipel r f1 f2 341 Logik für Informatiker Wintersemester 2012/13 In Klauselschreibweise r = p ∨ ¬a ∨ ¬b, f1 = a, f2 = b, erhalten wir folgende Folge von binären Resolutionen zum Goal Q = ¬p : ¬p r ? ¬a ∨ ¬b f1 ? ¬b f2 ? 2 Prof. Dr. Dietmar Seipel 342 Logik für Informatiker Wintersemester 2012/13 Nicht–Lineare Resolution Für die inkonsistente Klauselmenge F = { p ∨ q, p ∨ ¬q, ¬p ∨ q, ¬p ∨ ¬q } gibt es keine lineare Widerlegung, aber folgende Resolutionsableitung: p∨q p ∨ ¬q ¬p ∨ q Rp ¬p ∨ ¬q R¬p s 2 + Diese Klauselmenge ist keine Hornklauselmenge. Für eine inkonsistente Hornklauselmenge gibt es immer eine lineare Ableitung der leeren Klausel, die mit einer Integritätsbedingung startet. Prof. Dr. Dietmar Seipel 343 Logik für Informatiker Wintersemester 2012/13 Substitutionen Wir schreiben eine Substitution [X1 |t1 , . . . Xn |tn ], bei der alle Ersetzungen parallel angewendet werden, als Menge θ = { X1 7→ t1 , . . . , Xn 7→ tn }. θ definiert eine Abbildung von einer Struktur t auf eine neue Struktur tθ: • Für eine Konstante c gilt cθ = t. • Für eine Variable X erhalten wir Xθ = t, falls es eine Ersetzung X 7→ t ∈ θ gibt, und ansonsten Xθ = X. • Für eine komplexe Struktur gilt f (t1 , . . . , tn )θ = f (t1 θ, . . . , tn θ). Dann entspricht die Substitution θ1 = [X|Z][Z|Y ] der Substitution [X|Y, Z|Y ], da X zuerst durch Y und dieses dann durch Z ersetzt wird. Sie ist damit verschieden von θ2 = [X|Z, Z|Y ]. Für t = f (X, Y, Z) gilt z.B. tθ1 = f (Y, Y, Y ) und tθ2 = f (Z, Y, Y ). Prof. Dr. Dietmar Seipel 344 Logik für Informatiker Wintersemester 2012/13 Beispiel (SLD–Resolution) Wir betrachten das nicht–rekursive, definite Logikprogramm P = { r, f1 , f2 , f3 , f4 } und die Anfrage Q = ← grandparent(X, Z): r = grandparent(X, Z) ← parent(X, Y ) ∧ parent(Y, Z), f1 = parent(’Elizabeth’, ’Queen Mum’), f2 = parent(’Elizabeth’, ’George’), f3 = parent(’Charles’, ’Elizabeth’), f4 = parent(’William’, ’Charles’). Aus G0 = Q erhält man mittels r und θ1 = ∅ die Resolvente G1 = ← parent(X, Y ) ∧ parent(Y, Z). ’Queen Mum’ ’George’ f1 f2 ’Elizabeth’ f3 ’Charles’ f4 ’William’ Daraus kann man mit der Selektionsfunktion sl , welche stets das linkeste Literal eines Goals auswählt, z.B. folgende SLD–Widerlegungen erhalten: Prof. Dr. Dietmar Seipel 345 Logik für Informatiker Wintersemester 2012/13 • Mittels f3 und θ2 = { X 7→ ’Charles’, Y 7→ ’Elizabeth’ } erhalten wir G2 = ← parent(’Elizabeth’, Z). – Mittels f1 und θ3 = { Z 7→ ’Queen Mum’ } erhalten wir G3 = 2 und die Antwortsubstitution θ = { X 7→ ’Charles’, Y 7→ ’Elizabeth’, Z 7→ ’Queen Mum’ }. – Mittels f2 und θ3 = { Z 7→ ’George’ } erhalten wir ebenfalls G3 = 2; nun ist die Antwortsubstitution θ ′ = { X 7→ ’Charles’, Y 7→ ’Elizabeth’, Z 7→ ’George’ }. • Mittels f4 und f3 erhalten wir aus G1 die Antwortsubstitution θ ′′ = { X 7→ ’William’, Y 7→ ’Charles’, Z 7→ ’Elizabeth’ }. Später werden wir alle SLD–Widerlegungen in einem SLD–Baum zusammenfassen. Prof. Dr. Dietmar Seipel 346 Logik für Informatiker Wintersemester 2012/13 Beispiel (SLD–Resolution) Betrachten wir das rekursive, definite Logikprogramm P = { r, e, f } mit den folgenden Regeln (bzw. Fakten): r = anc(X, Y ) ← par (X, Z) ∧ anc(Z, Y ), e = anc(X, X), f = par (a, b). Zur Vereinfachung benutzen wir anstelle der üblichen bereichsbeschränkten Regel e′ = anc(X, Y ) ← par (X, Y ) das Fakt e = anc(X, X) mit Variablen zusammen mit der rekursiven Regel r. Dadurch wird hier anc als die reflexive, transitive Hülle von par berechnet. Prof. Dr. Dietmar Seipel 347 Logik für Informatiker Wintersemester 2012/13 Dann kann das Goal G0 = ← anc(X, b) von allen Selektionsfunktionen mittels der Regel r zu G1 = ← A1 ∧ A2 , mit A1 = par (X, Z ′ ) und A2 = anc(Z ′ , b), resolviert werden. Sei sl (sr ) die Selektionsfunktion, welche stets das linkeste (rechteste) Literal eines Goals auswählt. 1. sl wählt das erste (linkeste) Atom A1 = par (X, Z ′ ) in G1 . Dieses kann nur mit dem Fakt f = A = par (a, b) resolviert werden. Mit M GU (A1 , A) = { X 7→ a, Z ′ 7→ b } erhält man das verkürzte Goal G2 = ← anc(b, b). Eine weitere Resolution mit dem Fakt e würde die leere Klausel G3 = ← 2 liefern, und somit die Antwort anc(a, b). Prof. Dr. Dietmar Seipel 348 Logik für Informatiker Wintersemester 2012/13 2. sr wählt das zweite (rechteste) Atom A2 = anc(Z ′ , b) in G1 . Dieses kann mit Varianten r ′′ = anc(X ′′ , Y ′′ ) ← par (X ′′ , Z ′′ ) ∧ anc(Z ′′ , Y ′′ ), e′′ = anc(X ′′ , X ′′ ), der Regeln r bzw. e resolviert werden. Sei A′′ jeweils deren Regelkopf. • Mit r ′′ , A′′ = anc(X ′′ , Y ′′ ) und M GU (A2 , A′′ ) = { X ′′ 7→ Z ′ , Y ′′ 7→ b } erhält man das verlängerte Goal G′2 = ← par (X, Z ′ ) ∧ par (Z ′ , Z ′′ ) ∧ anc(Z ′′ , b). • Mit e′′ , A′′ = anc(X ′′ , X ′′ ) und M GU (A2 , A′′ ) = { X ′′ 7→ b, Z ′ 7→ b } erhält man das verkürzte Goal G′′2 = ← par (X, b). Prof. Dr. Dietmar Seipel 349 Logik für Informatiker Wintersemester 2012/13 Eine weitere Resolution mit dem Fakt f würde M GU (par (X, b), f ) = { X 7→ a } und die leere Klausel G′′3 = ← 2 liefern, und somit die Antwort anc(a, b). Mittels des Faktes e kann das Goal G0 = ← anc(X, Y ) von allen Selektionsfunktionen zur leeren Klausel G′1 = ← 2 resolviert werden. Dabei wird M GU (anc(X, Y ), anc(X, X)) = { Y 7→ X } berechnet, und somit die Antwort anc(X, X). Diese Antwort enthält noch das Variablensymbol X. Prof. Dr. Dietmar Seipel 350 Logik für Informatiker Wintersemester 2012/13 Beispiel (SLD–Widerlegungsbäume) Wir betrachten weiterhin das definite Logikprogramm P = { r, e, f }, jetzt aber mit den Anfragen Q1 = ← anc(X, b), Q2 = ← anc(X, Y ). Die Regeln (bzw. Fakten) sind folgende: r = anc(X, Y ) ← par (X, Z) ∧ anc(Z, Y ), e = anc(X, X), f = par (a, b). Anders als in Q1 , ist in Q2 auch die zweite Argumentposition mit einem Variablensysmbol – hier Y – belegt. Deswegen kann eine Antwort berechnet werden, die noch Variablensymbole enthält. Prof. Dr. Dietmar Seipel 351 Logik für Informatiker Wintersemester 2012/13 Im folgenden werden ein SLD–Widerlegungsbaum T1 für Q1 und die zugehörige Grundversion T1 θ angegeben: T1 : ← anc(X, b) ?9 ← par (X, Z ′ ) ∧ anc(Z ′ , b) ?9 ← anc(b, b) r ′ = anc(X ′ , Y ′ ) ← par (X ′ , Z ′ ) ∧ anc(Z ′ , Y ′ ) θ1 = { X ′ 7→ X, Y ′ 7→ b } f ′ = par (a, b) θ2 = { X 7→ a, Z ′ 7→ b } e′ = anc(X ′′ , X ′′ ) ?9 2 θ3 = { X ′′ 7→ b } Die berechnete Antwort ist anc(a, b). Prof. Dr. Dietmar Seipel 352 Logik für Informatiker Wintersemester 2012/13 Die Grundinstanz für die berechnete Antwort anc(a, b) ist folgende: T1 θ: ← anc(a, b) ?9 ← par (a, b) ∧ anc(b, b) ?9 ← anc(b, b) ?9 2 Prof. Dr. Dietmar Seipel r ′ θ = anc(a, b) ← par (a, b) ∧ anc(b, b) f ′ θ = par (a, b) e′ θ = anc(b, b) θ = θ1 · θ2 · θ3 = { X 7→ a, X ′ 7→ a, X ′′ 7→ b, Y ′ 7→ b, Z ′ 7→ b } 353 Logik für Informatiker Wintersemester 2012/13 Die Top–Down–Auswertung kann auch nicht–bereichsbeschränkte definite Logikprogramme behandeln. Sie hat keine Probleme mit Fakten, die Variablen enthalten, wie etwa e = anc(X, X). T2 : ← anc(X, Y ) ?) 2 e = anc(X, X) θ = { Y 7→ X } Allerdings ist die erzeugte Antwortsubstitution θ dann unter Umständen keine Grundsubstitution. Im obigem Beispiel für Q2 = ← anc(X, Y ) ist die berechnete Antwort anc(X, X) dann ein Fakt mit Variablen, das zeigt, daß die beiden Grundinstanzen anc(a, a) und anc(b, b) aus P ableitbar sind. Prof. Dr. Dietmar Seipel 354 Logik für Informatiker Wintersemester 2012/13 Vollständigkeit und Korrektheit der SLD–Resolution Sei P ein definites Logikprogramm und Q = ← A eine atomare Anfrage. 1. Es gibt genau dann eine SLD–Widerlegung mit der Antwort Aθ, wenn Aθ im minimalen Modell MP von P liegt. 2. Dieses Resultat ist unabhängig von der verwendeten Selektionsfunktion s. P ROLOG verwendet immer die Selektionsfunktion sl , welche stets das linkeste (erste) Literal eines Goals auswählt. Durch Umstellung der Atome in den Regelrümpfen kann der Programmierer de facto eine andere Selektionsfunktion simulieren. Prof. Dr. Dietmar Seipel 355 Logik für Informatiker Wintersemester 2012/13 SLD–Bäume Sei P ein definites Logikprogramm, Q eine Anfrage und s eine Selektionsfunktion. s Der SLD–Baum TP,Q faßt alle möglichen SLD–Ableitungen zusammen: s 1. Die Knoten von TP,Q sind mit Goals markiert, s und die Kanten von TP,Q sind mit Regeln r ∈ P markiert. s 2. Die Wurzel von TP,Q ist mit Q markiert. 3. Ein Knoten v, der mit einem Goal G markiert ist, hat für jede SLD–Resolvente G′ , die man aus G und einer Regel r ∈ P bezüglich s bilden kann, einen Nachfolgerknoten v ′ . 4. Dieser ist mit G′ markiert, und die Kante h v, v ′ i ist mit r markiert. Prof. Dr. Dietmar Seipel 356 Logik für Informatiker Wintersemester 2012/13 Jeder mit dem Goal G = 2 endende Ast eines SLD–Baumes entspricht einer SLD–Widerlegung bzw. einem SLD–Widerlegungsbaum: • Die Blätter dieser Äste werden als erfolgreich (success) markiert. • Alle anderen Blätter werden als erfolglos (failure) markiert. • Daneben kann es noch unendliche Äste im Baum geben. s1 s2 Zwei SLD–Bäume TP,Q und TP,Q zu unterschiedlichen Selektionsfunktionen s1 , s2 haben immer dieselben Antworten (success–Äste). Sie unterscheiden sich aber in der Regel hinsichtlich ihrer failure–Äste bzw. ihrer unendlichen Äste. Prof. Dr. Dietmar Seipel 357 Logik für Informatiker Wintersemester 2012/13 Beispiel (SLD–Bäume) Wir betrachten das nicht–rekursive, definite Logikprogramm P = { r, f1 , f2 , f3 , f4 } und die Anfrage Q = ← grandparent(X, Z): r = grandparent(X, Z) ← parent(X, Y ) ∧ parent(Y, Z), f1 = parent(’Elizabeth’, ’Queen Mum’), f2 = parent(’Elizabeth’, ’George’), f3 = parent(’Charles’, ’Elizabeth’), f4 = parent(’William’, ’Charles’). In diesem Falle sind alle SLD–Bäume – unabhängig von der Selektionsfunktion – endlich. sl Wir zeigen unten den SLD–Baum TP,Q zur Selektionsfunktion sl . Prof. Dr. Dietmar Seipel 358 Logik für Informatiker Wintersemester 2012/13 ← grandparent(X, Z) r ? ← parent(X, Y ) ∧ parent(Y, Z) f1 9 f2 ← parent(’Queen Mum’, Z ) ← parent(’George’, Z ) failure failure ) 2 { X 7→ ’Charles’, Y 7→ ’Elizabeth’, Z 7→ ’Queen Mum’ } success Prof. Dr. Dietmar Seipel f3 f4 j z ← parent(’Elizabeth’, Z ) f1 f2 ? 2 {X → 7 ’Charles’, Y 7→ ’Elizabeth’, Z → 7 ’George’ } success ← parent(’Charles’, Z ) f3 ? 2 {X → 7 ’William’, Y → 7 ’Charles’, Z 7→ ’Elizabeth’ } success 359 Logik für Informatiker Wintersemester 2012/13 Beispiel (SLD–Bäume) Wir betrachten wieder das rekursive, definite Logikprogramm P = { r, e, f } und die Anfrage Q = ← anc(X, b): r = anc(X, Y ) ← par (X, Z) ∧ anc(Z, Y ), e = anc(X, X), f = par (a, b). Die SLD–Bäume zu den Selektionsfunktionen sl bzw. sr haben dieselben Antworten (success–Äste). • Allerdings ist in diesem Falle Tl endlich, • wohingegen Tr unendliche Äste hat. Für sr könnte man in obigem Beispiel die unendlichen Äste vermeiden, indem man die Reihenfolge der Rumpfatome invertiert. Prof. Dr. Dietmar Seipel 360 Logik für Informatiker Wintersemester 2012/13 Der SLD–Baum Tl zur Selektionsfunktion sl ist endlich: ← anc(X, b) Tl : r ← par (X, Z ′ ) ∧ anc(Z ′ , b) f ? ← anc(b, b) r ← par (b, Z ′′ ) ∧ anc(Z ′′ , b) failure Prof. Dr. Dietmar Seipel e R 2 { X 7→ b } success e R 2 { X 7→ a } success 361 Logik für Informatiker Wintersemester 2012/13 Der SLD–Baum Tr zur Selektionsfunktion sr ist unendlich, hat aber die gleichen Antwortsubstitutionen in den success–Blättern wie Tl : ← anc(X, b) Tr : r e R ← par (X, Z ′ ) ∧ anc(Z ′ , b) r e ← par (X, Z ′ ) ∧ par (Z ′ , Z ′′ ) r ) ← par (X, Z ′ ) ∧ par (Z ′ , Z ′′ ) ∧ par(Z ′′ , Z ′′′ ) ∧ anc(Z ′′′ , b) r e R ∧ R anc(Z ′′ , b) 2 { X 7→ b } success ← par (X, b) e f s R ← par (X, Z ′ ) ∧ par (Z ′ , b) f ? 2 { X 7→ a } success ← par (X, a) failure (unendlicher Ast) Prof. Dr. Dietmar Seipel 362 Logik für Informatiker Wintersemester 2012/13 Steuerung der SLD–Resolution Der Logikprogrammierer kann bei gegebener Selektionsfunktion durch • die Reihenfolge der Regeln und • die Reihenfolge der Rumpfatome in den Regeln die Abarbeitung steuern: • Wenn wir in unserem letzten Beispiel die Regel e vor die Regel r stellen, dann wandern im neuen SLD–Baum Tr′ zur Selektionsfunktion sr die mit e markierten Kanten vor die mit r markierten. • Bei Backtracking findet der LWR–Durchlauf von Tr′ nun die beiden Antworten, bevor der unendliche Ast zu einer Dauerschleife führt. • Wenn wir dagegen die Reihenfolge der Rumpfatome von r vertauschen, dann hat der neue SLD–Baum Tr′′ zu sr dieselbe Struktur wie der alte SLD–Baum Tl zu sl : r ′′ = anc(X, Y ) ← anc(Z, Y ) ∧ par (X, Z). Prof. Dr. Dietmar Seipel 363 Logik für Informatiker Wintersemester 2012/13 • Generell ist es am besten die nicht–rekursive Regel e vor die rekursive Regel r zu stellen: e = anc(X, X), r = anc(X, Y ) ← par (X, Z) ∧ anc(Z, Y ). • Für die Standard–Selektionsfunktion sl sollte in der rekursiven Regel r der nicht–rekursive Aufruf par (X, Z) vor dem rekursiven Aufruf anc(Z, Y ) stehen. Dies garantiert die Terminierung für azyklische par –Relationen. • Bei zyklischer par –Relation enthält der SLD–Baum Tl aber leider trotzdem unendliche Äste. Für die Fakten f1 = par (a, b), f2 = par (b, a), und die Anfrage Q = ← anc(a, Y ) generiert die alternierende Verwendung von f1 und f2 abwechselnd die Antworten Y 7→ a und Y 7→ b. Prof. Dr. Dietmar Seipel 364 Logik für Informatiker Wintersemester 2012/13 ← anc(a, Y ) Tl : e r R 2 ← par (a, Z ′ ) ∧ anc(Z ′ , Y ) {Y → 7 a} success f1 ? ← anc(b, Y ) e r R 2 ← par (b, Z ′′ ) ∧ anc(Z ′′ , Y ) { Y 7→ b } f2 success ? ← anc(a, Y ) (unendlicher Ast) Prof. Dr. Dietmar Seipel 365 Logik für Informatiker Wintersemester 2012/13 Beispiel (Redundanz in SLD–Bäumen) Wir betrachten nun das etwas erweiterte rekursive, definite Logikprogramm P = { r, e, f1 , f2 } und die Anfrage Q = ← anc(X, Y ): r = anc(X, Y ) ← par (X, Z) ∧ anc(Z, Y ), e = anc(X, X), f1 = par (a, b), f2 = par (b, c). Der SLD–Baum Tl zur Selektionsfunktion sl ist endlich. Die success–Äste leiten der Reihe nach die folgenden Grundinstanzen ab: • success–Äste 1 bis 3: tc(a, c), tc(a, b), tc(b, c); • success–Ast 4: tc(a, a), tc(b, b), tc(c, c). Die Unteranfrage ← anc(c, Y ) wurde redundant in zwei success–Ästen (1 und 3) mit Y 7→ c beantwortet. Derartige Redundanz tritt bei Graphen mit längeren Ketten (hier: a → b → c) noch verstärkt auf. Prof. Dr. Dietmar Seipel 366 Logik für Informatiker Wintersemester 2012/13 ← anc(X, Y ) Tl : r e R 2 ← par (X, Z ′ ) ∧ anc(Z ′ , Y ) { X 7→ Y } success f1 f2 R ← anc(b, Y ) r e ← par (b, Z ′′ ) f2 ∧ ← anc(c, Y ) r R anc(Z ′′ , Y par (c, Z ′′ ) 2 ) ← { X 7→ a, Y 7→ b } success ? e R ∧ z anc(Z ′′ , Y failure 2 ) { X 7→ b, Y 7→ c } success ← anc(c, Y ) r e R ← par (c, Z ′′′ ) ∧ anc(Z ′′′ , Y ) 2 { X 7→ a, Y 7→ c } failure success Prof. Dr. Dietmar Seipel 367 Logik für Informatiker Wintersemester 2012/13 Normale Logikprogramme Syntax: 1. Ein normales Logikprogramm besteht aus Regeln in Implikations–Notation mit jeweils genau einem Kopfatom: Fakt: A Regel: A ← B1 ∧ . . . ∧ Bm ∧ not C1 ∧ . . . ∧ not Cn . Fakten stellen Wissen ohne Vorbedingung dar, Regeln mit m ≥ 1 oder n ≥ 1 konditionales Wissen mit Vorbedingung. 2. Regeln mit n = 0 und ohne Kopfatom repräsentieren Anfragen: Goal: ← B1 ∧ . . . ∧ Bm . Dabei sind A, die Bi und die Ci Atome. not nennt man Default–Negation. In P ROLOG schreibt man diese als “not(C)” oder “\+ C”. Prof. Dr. Dietmar Seipel 368 Logik für Informatiker Wintersemester 2012/13 SLDNF–Resolution Die SLDNF–Resolution erweitert die SLD–Resolution auf normale Logikprogramme durch ein Konzept namens Negation–as–Finite–Failure zur Behandlung negativer Literale not A: • Wenn im Rahmen einer SLDNF–Resolution ein negatives Literal not A abgeleitet werden soll, so wird eine neue SLDNF–Resolution für das Goal G0 = ← A gestartet. • Falls diese erfolglos abbricht, so ist not A abgeleitet; sonst war der Ableitungsversuch für not A erfolglos. not A bedeutet, daß A nicht ableitbar ist, und nicht etwa, daß ¬A ableitbar ist. Damit sind die beiden wesentlich verschieden. Zur Illustration der SLDNF–Resolution wollen wir damit im folgenden Zwei–Personen–Gewinnspiele mit azyklischen Übergangsgraphen behandeln. Prof. Dr. Dietmar Seipel 369 Logik für Informatiker Wintersemester 2012/13 Beispiel (Zwei–Personen–Gewinnspiele) • Bei Tic–Tac–Toe markieren die Spieler abwechselnd Felder auf einem 3 × 3–Brett. Ein Spieler gewinnt, wenn er als erster eine Reihe, Spalte oder Diagonale zu besetzt. • Wenn beide Spieler allerdings optimal spielen, so gehen die Spiele Unentschieden aus: Prof. Dr. Dietmar Seipel 370 Logik für Informatiker Wintersemester 2012/13 • Für Tic–Tac–Toe ist der Übergangsgraph azyklisch: Es gibt 765 wesentlich verschiedene Positionen. Achsenspiegelungen erzeugen strukturell gleiche Positionen. • Für Schach ist der Übergangsgraph zyklisch. Prof. Dr. Dietmar Seipel 371 Logik für Informatiker Wintersemester 2012/13 Beispiel (Zwei–Personen–Gewinnspiele mit SLDNF) Wir betrachten das normale Logikprogramm P = { r, f1 , f2 } und die Anfrage Q = ← win(X) : r = win(X) ← move(X, Y ) ∧ not win(Y ), f1 = move(b, c), f2 = move(a, b). a - b - c Ein Spieler kann in Position X gewinnen, wenn es einen Zug von X nach Y gibt, so daß man in Position Y nicht gewinnen kann. • Offenbar kann man in Position b gewinnen, da man nach c ziehen kann, und da es keinen Zug von c aus gibt; c ist eine Verlustposition. • In Position a kann man nicht gewinnen, da man nach b ziehen muß, und da b ja dann eine Gewinnposition für den Gegner ist. Prof. Dr. Dietmar Seipel 372 Logik für Informatiker Wintersemester 2012/13 Sei G0 = Q: • Wir starten eine SLDNF–Resolution für G0 = ← win(X) : – h G0 , r i 7→ G1 = ← move(X, Y ) ∧ not win(Y ) – h G1 , f1 i 7→ G2 = ← not win(c) • Wir starten eine SLDNF–Resolution für H0 = ← win(c) : – h H0 , r i 7→ H1 = ← move(c, Y ) ∧ not win(Y ) – H1 kann bezüglich sl nicht weiter resolviert werden, und es gibt keine Möglichkeit zum Backtracking. – Deshalb schlägt die SLDNF–Resolution für H0 fehl. • Damit ist die SLDNF–Resolution für G0 erfolgreich mit der Substitution { X 7→ b, Y 7→ c }, und somit ist win(b) abgeleitet. Prof. Dr. Dietmar Seipel 373 Logik für Informatiker Wintersemester 2012/13 • Backtracking innerhalb der SLDNF–Resolution für G0 liefert: – h G1 , f2 i 7→ G′2 = ← not win(b) • Wir starten eine SLDNF–Resolution für H0′ = ← win(b) : – h H0′ , r i 7→ H1′ = ← move(b, Y ) ∧ not win(Y ) – h H1′ , f1 i 7→ H2′ = ← not win(c) – Da die SLDNF–Resolution für ← win(c) bekanntermaßen fehlschlägt, ist die SLDNF–Resolution für H0′ = ← win(b) erfolgreich. • Damit bricht die aktuelle Berechnungslinie erfolglos ab. • Jetzt gibt es keine weiteren Alternativen zum Backtracking innerhalb der SLDNF–Resolution für G0 . Prof. Dr. Dietmar Seipel 374 Logik für Informatiker Wintersemester 2012/13 ?- trace. [trace] Call: Call: Exit: Call: Call: Call: Fail: Fail: Exit: Exit: X = b ; ?- win(X). (6) win(X) (7) move(X, Y) (7) move(b, c) (7) not(win(c)) (8) win(c) (9) move(c, Y’) (9) move(c, Y’) (8) win(c) (7) not(win(c)) (6) win(b) Fail: Redo: Exit: Call: Call: Call: Exit: Call: (7) (7) (7) (7) (8) (9) (9) (9) not(win(c)) move(X, Y) move(a, b) not(win(b)) win(b) move(b, Y’) move(b, c) not(win(c)) Call: Call: Fail: Fail: Exit: Exit: Fail: Fail: Fail: (10) win(c) (11) move(c, Y’’) (11) move(c, Y’’) (10) win(c) (9) not(win(c)) (8) win(b) (7) not(win(b)) (7) move(X, Y) (6) win(X) false. Prof. Dr. Dietmar Seipel 375 Logik für Informatiker Wintersemester 2012/13 Zyklisches, nicht–terminierendes Verhalten Wir betrachten nun das normale Logikprogramm P = { r, f3 } und die Anfrage Q = ← win(X) : r = win(X) ← move(X, Y ) ∧ not win(Y ), f3 = move(c, c). Die Relation move/2 ist hier zyklisch. • In diesem Fall führt die SLDNF–Resolution für G0 = Q zu einer Dauerschleife, da immer wieder das Goal ← win(c) auftritt. • Deswegen kann weder win(c) noch ¬win(c) abgeleitet werden. Das P ROLOG–System X SB kann solche Dauerschleifen durch eine modifizierte Auswertung mit Zyklentest vermeiden. Prof. Dr. Dietmar Seipel 376 Logik für Informatiker Wintersemester 2012/13 führt zur Dauerschleife: zyklische Relation move/2: win(X) :move(X, Y), not(win(Y)). move(c, c). Prof. Dr. Dietmar Seipel [trace] Call: Call: Exit: ^ Call: Call: Call: Exit: ^ Call: Call: ... ?- win(X). (6) win(X) (7) move(X, Y) (7) move(c, c) (7) not(win(c)) (8) win(c) (9) move(c, Y’) (9) move(c, c) (9) not(win(c)) (10) win(c) 377 Logik für Informatiker Wintersemester 2012/13 Abhängigkeitsgraph Es gibt ein DDK–Tool zur Veranschaulichung der Abhängigkeitsgraphen von P ROLOG–Programmen. Da hier die Regeln keine Namen haben, werden die Regel–Knoten mit den entsprechenden File–Namen markiert. Prof. Dr. Dietmar Seipel 378 Logik für Informatiker 3.3 Wintersemester 2012/13 Suche in Graphen Labyrinth: Prof. Dr. Dietmar Seipel 379 Logik für Informatiker Wintersemester 2012/13 Berechnung einfacher Pfade mittels Backtracking Das Prädikat graph_search/2 berechnet einen einfachen Pfad von einem gegebenen Knoten zu einer Senke des Graphen: % graph_search(+Node, ?Path) <graph_search(X, Path) :graph_search(X, [X], Path). Es wird ein weiteres Prädikat graph_search/3 mit demselben Prädikatensymbol aber einer anderen Stelligkeit aufgerufen. Der Graph ist in Form von Fakten für die Prädikate graph_arc/2 und graph_sink/1 gegeben. Notation für die Argumente in der Kommentarzeile: +: gebunden, -: frei, ?: gebunden oder frei Prof. Dr. Dietmar Seipel 380 Logik für Informatiker Wintersemester 2012/13 Path = Visited [Y1 =Y, . . . ,Yn =Z] -X -Y -Z • Beim Aufruf graph_search(X, Visited, Nodes) mit einem gebundenen Argument X, das keine Senke ist, und einer Liste Visited von bereits besuchten Knoten, wird – eine Kante von X zu einem bisher nicht besuchten Nachfolgerknoten Y benutzt, und dann – ein Weg Path von Y zu einer Senke Z berechnet, der Y und die Knoten in Visited nicht benutzt. Falls kein Weg von Y zu einer Senke gefunden werden kann, so muß ein anderer Nachfolgerknoten von X benutzt werden (Backtracking). • Das Ergebnis Nodes = [X|Path] ist ein einfacher Pfad von X zu einer Senke des Graphen. Prof. Dr. Dietmar Seipel 381 Logik für Informatiker Wintersemester 2012/13 Das Prädikat graph_search/3 ist aufgrund seiner zweiten Regel rekursiv: % graph_search(+Node, +Visited, ?Path) <graph_search(X, _, [X]) :graph_sink(X). graph_search(X, Visited, [X|Path]) :Path = graph_edge(X, Y), [Y1 =Y, Visited -X-Y not(member(Y, Visited)), write(user, ’->’), write(user, Y), graph_search(Y, [Y|Visited], Path). . . . ,Yn =Z] -Z Die Terminierung wird dadurch gewährleistet, daß Knoten nicht mehrfach besucht werden dürfen. Prof. Dr. Dietmar Seipel 382 Logik für Informatiker Wintersemester 2012/13 • Der initiale Aufruf graph_search(X, [X], Path) berechnet einen einfachen Pfad von X zu einer Senke des Graphen. – Falls X bereits eine Senke ist, so bestimmt die erste Regel für graph_search/3 den Pfad Path als die leere Liste. – Ansonsten wählt die rekursive zweite Regel mittels graph_edge (X, Y) einen Nachfolgerknoten Y und sucht von dort aus weiter. • Bei Backtracking können weitere einfache Pfade berechnet werden. – Dazu können in der zweiten Regel alternative Nachfolgerknoten Y betrachtet werden. – In der obigen Implementierung kann über eine Senke hinaus zu anderen Senken weitergesucht werden, indem man die zweite Regel anstelle der ersten verwendet. Prof. Dr. Dietmar Seipel 383 Logik für Informatiker Wintersemester 2012/13 Implizites und explizites Backtracking In P ROLOG wird automatisch (implizit) Backtracking verwendet. In einer prozeduralen Sprache muß man das Backtracking explizit implementieren. Falls man obigen Code eins–zu–eins in einer prozeduralen Umgebung umsetzen würde, so könnte ein Aufruf graph_edge(X, Y) nur einen einzigen Nachfolgerknoten Y von X produzieren – falls es dann keinen Pfad von Y zu einer Senke gibt, so würde die Berechnung fehlschlagen. Außerdem könnte nur maximal eine Lösung ermittelt werden. Wenn man die Graph–Suche prozedural mit explizitem Backtracking realisiert, so ergibt sich mehr Code als bei der P ROLOG–Implementierung. Prof. Dr. Dietmar Seipel 384 Logik für Informatiker Wintersemester 2012/13 Repräsentation des Graphen mit P ROLOG–Fakten Labyrinth: a b c d e f g h i 6 Prof. Dr. Dietmar Seipel - graph_arc(i, graph_arc(i, graph_arc(h, graph_arc(g, graph_arc(d, graph_arc(d, graph_arc(a, graph_arc(b, f). h). g). d). e). a). b). c). graph_sink(c). 385 Logik für Informatiker Wintersemester 2012/13 Die folgende Regel symmetrisiert das Prädikat graph_arc/2: graph_edge(X, Y) :( graph_arc(X, Y) ; graph_arc(Y, X) ). Dadurch ist es nicht nötig, für die Kanten die Rückrichtung explizit anzugeben: graph_edge(i, graph_edge(f, graph_edge(i, graph_edge(h, ... Prof. Dr. Dietmar Seipel f). i). h). i). 386 Logik für Informatiker Wintersemester 2012/13 Berechnung • Das Prädikat graph_search/2 benutzt Tiefensuche, und es berechnet einfache Pfade (ohne doppelte Knoten). • Beim Aufruf graph_search(+Node, ?Path) können alle einfachen Pfade von Node zu einer Senke (graph_sink) über Backtracking berechnet werden: ?- graph_search(i, Path). ->f->h->g->d->e->a->b->c Path = [i, h, g, d, a, b, c] ?- graph_search(e, Path). ->d->a->b->c Path = [e, d, a, b, c] ; ->g->h->i->f false. Prof. Dr. Dietmar Seipel 387 Logik für Informatiker Wintersemester 2012/13 • Würde man eine weitere Kante graph_arc(e, b) in den Graphen einfügen (die Wand zwischen e und b einreisen), so gäbe es einen weiteren einfachen Pfad [e, b, c] von e zur Senke c. • Man kann alle Antworten mittels Backtracking und findall/3 bestimmen: graph_arc(e, b). ?- findall( Path, graph_search(e, Path), Paths ). ... Paths = [ [e, d, a, b, c], [e, b, c] ] Prof. Dr. Dietmar Seipel 388 Logik für Informatiker Wintersemester 2012/13 Das Meta–Prädikat findall/3 Finden aller Lösungen für ein Goal: findall( X, goal(X), Xs ) Das D DK erlaubt sogar folgende äquivalente Mengenschreibweise: Xs <= { X | goal(X) } Weitere wichtige Meta–Prädikate sind checklist/2 und maplist/3 für Listen sowie die Prädikate für Schleifen (Kontrollstrukturen) aus der Loops–Bibliothek (z.B. foreach-do). Prof. Dr. Dietmar Seipel 389 Logik für Informatiker 3.4 Wintersemester 2012/13 Sortieren und Suchbäume Im folgenden werden einige wohlbekannte Algorithmen zum Sortieren und Suchen in P ROLOG formuliert. Vorzüge von P ROLOG liegen hierbei • im einfachen Umgang mit Datenstruktuen (Listen, Bäume, X ML) und • in der kompakten Realisierbarkeit von Fallunterscheidungen durch verschiedene Regeln. Die Algorithmen sind typischerweise rekursiv. Die Rekursion wird durch die kompakten Listenzugriffe gut formulierbar. Auch Meta–Prädikate tragen zur eleganten Implementierung bei. Prof. Dr. Dietmar Seipel 390 Logik für Informatiker Wintersemester 2012/13 Quicksort in P ROLOG % quicksort(+List, ?Sorted_List) <quicksort([], []) :!. quicksort([X|Xs], Ys) :quicksort_divide(X, Xs, Xs1, Xs2), quicksort(Xs1, Ys1), quicksort(Xs2, Ys2), append(Ys1, [X|Ys2], Ys). Der eigentliche Aufwand steckt in der Listenaufteilung (Divide); der Merge–Schritt ist einfach (append). Prof. Dr. Dietmar Seipel 391 Logik für Informatiker Wintersemester 2012/13 [X|Xs] = [4,3,7,2,5,1,6] quicksort_divide R Xs1 = [3,2,1] Xs2 = [7,5,6] quicksort ? ? Ys1 = [1,2,3] Ys2 = [5,6,7] append R Ys = [ 1,2,3, 4, 5,6,7 ] Prof. Dr. Dietmar Seipel 392 Logik für Informatiker Wintersemester 2012/13 quicksort_divide(X, Xs, Xs1, Xs2) :findall( X1, ( member(X1, Xs), X1 < X ), Xs1 ), findall( X2, ( member(X2, Xs), X2 > X ), Xs2 ). append([], Ys, Ys). append([X|Xs], Ys, [X|Zs]) :append(Xs, Ys, Zs). Prof. Dr. Dietmar Seipel 393 Logik für Informatiker Wintersemester 2012/13 Mittels des Meta–Prädikats sublist/3 kann man die Listenaufteilung noch etwas kompakter formulieren: quicksort_divide(X, Xs, Xs1, Xs2) :sublist(>(X), Xs, Xs1), sublist(<(X), Xs, Xs2). Ein Element X1 von Xs kommt nach Xs1, falls >(X, X1) gilt; in Infix–Notation bedeutet dies X > X1. Analog kommen die Elemente X2 von Xs mit <(X, X2) nach Xs2; in Infix–Notation bedeutet dies X < X2. Falls ein Element mehrfach in der zu sortierenden Liste vorkommt, so ist es trotzdem nur einmal in der Resultatsliste enthalten, denn das Pivot–Element X wird nicht in Xs1 oder Xs2 aufgenommen. Dies könnte man ändern, indem man > durch >= ersetzt, oder < durch =<. Prof. Dr. Dietmar Seipel 394 Logik für Informatiker Wintersemester 2012/13 Mergesort in P ROLOG % mergesort(+List, ?Sorted_List) <mergesort(Xs, Xs) :length(Xs, N), N =< 1, !. mergesort(Xs, Ys) :middle_split(Xs, Xs1, Xs2), mergesort(Xs1, Ys1), mergesort(Xs2, Ys2), mergesort_merge(Ys1, Ys2, Ys). Die Aufteilung (Divide mittels middle_split) ist einfach; der eigentliche Aufwand steckt im Merge–Schritt. Prof. Dr. Dietmar Seipel 395 Logik für Informatiker Wintersemester 2012/13 mergesort_merge([], Xs, Xs) :!. mergesort_merge(Xs, [], Xs) :!. mergesort_merge([X1|Xs1], [X2|Xs2], [X|Xs]) :( X1 < X2 -> X = X1, mergesort_merge(Xs1, [X2|Xs2], Xs) ; X = X2, mergesort_merge([X1|Xs1], Xs2, Xs) ). middle_split(Xs,Xs1,Xs2) splittet eine Liste Xs in zwei etwa gleich große Teile Xs1 und Xs2. Hier wird die Kontrollstruktur If -> Then ; Else verwendet. Prof. Dr. Dietmar Seipel 396 Logik für Informatiker Wintersemester 2012/13 Binäre Suchbäume in P ROLOG % search_in_binary_tree(+Key, +Tree) <search_in_binary_tree(Key, Tree) :binary_tree_parse(Tree, Root, Lson, Rson), ( Key = Root ; Key < Root -> search_in_binary_tree(Key, Lson) ; Key > Root -> search_in_binary_tree(Key, Rson) ). Die Suchbäume können dabei in einer X ML–artigen Termnotation in P ROLOG vorliegen (binary_tree_mode=xml) oder in einer einfachen – aber schwerer zu lesenden – Listennotation. Prof. Dr. Dietmar Seipel 397 Logik für Informatiker Wintersemester 2012/13 Suchbaum in X ML–Darstellung <node key="8"> <node key="4"> <node key="2"> <node key="1"/> <node key="3"/> </node> <node key="6"> <node key="5"/> <node key="7"/> </node> </node> <node key="12"> <node key="10"> <node key="9"/> <node key="11"/> </node> <node key="13"/> </node> </node> Prof. Dr. Dietmar Seipel Visualisierung in P ROLOG mittels binary_tree_to_picture(Picture, Tree) 398 Logik für Informatiker Wintersemester 2012/13 Suchbaum – verschiedene Darstellungen X ML–Darstellung: <node key="2"> <node key="1"/> <node key="3"/> </node> P ROLOG–Darstellung: node:[key:2]:[ node:[key:1]:[], node:[key:3]:[] ] alternative, einfache P ROLOG–Darstellung: [ 2, [1], [3] ] Prof. Dr. Dietmar Seipel 2 1 U 3 399 Logik für Informatiker Wintersemester 2012/13 Der leere Baum wird in X ML als leerer Knoten <node/> dargestellt. Falls ein Knoten eines Suchbaumes nur genau einen Sohn hat, so wird als anderer Sohn der leere Baum eingetragen: <node key="2"> <node key="1"/> <node/> </node> 2 1 Dies gilt auch für die alternative P ROLOG–Darstellung [ 2, [1], [] ] Eine entsprechende JAVA–Klasse wäre folgende: Class node { int key ; node lson, rson; ... } Prof. Dr. Dietmar Seipel 400 Logik für Informatiker Wintersemester 2012/13 Kapselung des Zugriffs: % binary_tree_empty(?Tree) <binary_tree_empty(node:[]:[]). binary_tree_empty([]). Dabei ist “:” ein binärer, assoziativer Operator, und X:Y:Z wird wie X:(Y:Z) geklammert. Man braucht natürlich jeweils nur eines der beiden Fakten. Das erste ist für die X ML–Repräsentation, das zweite für die alternative P ROLOG–Repräsentation. Prof. Dr. Dietmar Seipel 401 Logik für Informatiker Wintersemester 2012/13 % binary_tree_parse(+Tree, ?Key, ?Lson, ?Rson) <% binary_tree_parse(?Tree, +Key, +Lson, +Rson) <binary_tree_parse(Tree, Key, Empty, Empty) :binary_tree_empty(Empty), Tree = node:[key:Key]:[]. binary_tree_parse(Tree, Key, Lson, Rson) :Tree = node:[key:Key]:[Lson, Rson]. binary_tree_parse(Tree, Key, Empty, Empty) :binary_tree_empty(Empty), Tree = [Key]. binary_tree_parse(Tree, Key, Lson, Rson) :Tree = [Key, Lson, Rson]. Diese Methode schlägt für den leeren Baum bewußt fehl. Man braucht auch hier jeweils nur eines der beiden Regelpaare. Prof. Dr. Dietmar Seipel 402 Logik für Informatiker Wintersemester 2012/13 Einzelne Einfügeoperation % insert_into_binary_tree(+Key, +Tree, ?New_Tree) <insert_into_binary_tree(Key, Tree, New_Tree) :binary_tree_parse(Tree, Root, Lson, Rson), ( Key = Root -> New_Tree = Tree ; Key < Root -> insert_into_binary_tree(Key, Lson, L), binary_tree_parse(New_Tree, Root, L, Rson) ; Key > Root, insert_into_binary_tree(Key, Rson, R), binary_tree_parse(New_Tree, Root, Lson, R) ). insert_into_binary_tree(Key, Empty, New_Tree) :binary_tree_empty(Empty), binary_tree_parse(New_Tree, Key, Empty, Empty). Prof. Dr. Dietmar Seipel 403 Logik für Informatiker Wintersemester 2012/13 Aufbau eines Suchbaums % keys_to_binary_tree(+Keys, ?Tree) <keys_to_binary_tree(Keys, Tree) :binary_tree_empty(Empty), insert_into_binary_tree_(Keys, Empty, Tree). % insert_into_binary_tree_(+Keys, +Tree, ?New_Tree) <insert_into_binary_tree_([], Tree, Tree). insert_into_binary_tree_([Key|Keys], Tree, New_Tree) :insert_into_binary_tree(Key, Tree, Tree_2), insert_into_binary_tree_(Keys, Tree_2, New_Tree). Prof. Dr. Dietmar Seipel 404 Logik für Informatiker Wintersemester 2012/13 Berechnung der Höhe eines Suchbaums % binary_tree_to_height(+Tree, ?H) <- binary_tree_to_height(Tree, -1) :binary_tree_empty(Tree), L !. binary_tree_to_height(Tree, H) :binary_tree_parse(Tree, Root, Lson, Rson), binary_tree_to_height(Lson, L), binary_tree_to_height(Rson, R), max(L, R, M), H is M + 1. j R 1 max(L,R) Funktional könnte man in P ROLOG auch H is max(L,R) + 1 schreiben. Prof. Dr. Dietmar Seipel 405 Logik für Informatiker Wintersemester 2012/13 Man kann in P ROLOG (im Gegensatz zur “reinen” Logikprogrammierung) auch • prozedural • mit Seiteneffekten und • mit globalen Variablen (realisiert mit Hilfe von assert und retract) programmieren. Es gibt umfangreiche Programmbibliotheken und Erweiterungen: • Datenstrukturen und Algorithmen, Kombinatorik, • Datenbank– und Web–Programmierung, • GUI–Programmierung, etc. Prof. Dr. Dietmar Seipel 406 Logik für Informatiker Wintersemester 2012/13 Anwendungsbereiche: • regelbasierte Diagnosesysteme (Medizin, Technik) • symbolische Informationsverarbeitung, Parsing • Datenbanken mit komplexen Strukturen (Hierarchien, X ML) • Datenintegration • Semantic Web • Default Reasoning • kombinatorische Suchprobleme (Graphenprobleme, Spiele wie Sudoku oder Minesweeper, etc.) Prof. Dr. Dietmar Seipel 407