Kapitel 4
Transcription
Kapitel 4
Deduktive Datenbanken 4 Sommersemester 2012 Datenstrukturen und Programmstrukturen für Logikprogramme 2 Es werden einige zentrale Datenstrukturen und Programmstrukturen für P ROLOG vorgestellt. Diese helfen beim Software Engineering, indem sie die elegante und kompakte Programmierung unterstützen. 2 Es werden strukturelle Eigenschaften von definiten Logikprogrammen untersucht. Ein sehr wichtiges Hilfsmittel zur Programmanalyse sind Abhängigkeitsgraphen. 2 Es werden unterschiedlich starke Formen der Äquivalenz von Logikprogrammen vorgestellt. Mittels darauf aufbauender Programmtransformationen werden wir in Kapitel 5 definite Logikprogramme effizienter auswerten, ohne die zugrundeliegende Inferenzmaschine ändern zu müssen. Prof. Dr. Dietmar Seipel 591 Deduktive Datenbanken 4.1 Sommersemester 2012 Datenstrukturen in P ROLOG allgemeine Strukturen in P ROLOG: 2 Termzerlegung und –aufbau 2 dynamischer Aufbau und Aufruf von Goals 2 Operatoren (Funktoren) spezielle, interessante Datenstrukturen: 2 Fakten und Regeln – die clause–Datenbank von P ROLOG – Fakten und Regeln als Listenargumente 2 die Field Notation zur Repräsentation von X ML–Daten Prof. Dr. Dietmar Seipel 592 Deduktive Datenbanken Sommersemester 2012 4.1.1 Terme und Goals Termzerlegung und –aufbau Terme können mittels functor/3 und arg/3 in ihre Bestandteile zerlegt werden, und mittels ” =../2 ” können sie aufgebaut und zerlegt werden: 2 functor(+Term, ?Functor, ?Arity) functor(?Term, +Functor, +Arity) 2 arg(+N, +Term, ?Argument) 2 +Term =.. [?Functor|?Arguments] ?Term =.. [+Functor|+Arguments] Dabei ist ” =../2 ” das mächtigste Prädikat; mit ihm können die beiden anderen simuliert werden. Prof. Dr. Dietmar Seipel 593 Deduktive Datenbanken Sommersemester 2012 Das Prädikat functor/3 bestimmt den Funktor und die Stelligkeit eines Terms; z.B. ist der Listenfunktor ’.’ zweistellig: ?- functor(arc(a, b), Functor, Arity). Functor = arc, Arity = 2 ?- functor([a, b, c], Functor, Arity). Functor = ’.’, Arity = 2 ?- functor(Term, tc, 2). Term = tc(_G123, _G124) Prof. Dr. Dietmar Seipel 594 Deduktive Datenbanken Sommersemester 2012 Das Prädikat arg/3 bestimmt die einzelnen Argumente eines Terms – mittels findall/3 könnten alle Argumente bestimmt werden: ?- arg(2, arc(a, b), Argument). Argument = b ?- arg(1, a+b+c, Argument). Argument = a+b Offenbar steht der Term a+b+c für +(+(a,b),c). Prof. Dr. Dietmar Seipel 595 Deduktive Datenbanken Sommersemester 2012 Das Prädikat ” =../2 ” kann Terme aufbauen bzw. zerlegen. Der Aufruf ” Term =.. Xs ” baut aus einer gegebenen Liste Xs einen Term auf: ?- Term =.. [arc, a, b]. Term = arc(a, b) Derselbe Aufruf ” Term =.. Xs ” bestimmt zu einem gegebenen Term eine Liste Xs bestehend aus dem Funktor und den Argumenten: ?- a+b+c =.. Xs. Xs = [+, a+b, c] Prof. Dr. Dietmar Seipel 596 Deduktive Datenbanken Sommersemester 2012 functor/3 und arg/3 können mittels ” =../2 ” simuliert werden: ?- functor(Term, Functor, _), arg(N, Term, Argument). ?- Term =.. [Functor|Arguments], nth(N, Arguments, Argument). ”=../2 ” kann mittels functor/3 und arg/3 simuliert werden: ?- Term =.. [Functor|Arguments]. ?- functor(Term, Functor, _), findall( Argument, arg(_, Term, Argument), Arguments ). Prof. Dr. Dietmar Seipel 597 Deduktive Datenbanken Sommersemester 2012 Listen 2 Die []–Notation ist eine intuitive Abkürzung (syntactic sugar) für Listen. 2 Der (binäre) Listenfunktor ist ’.’. Falls X ein Element ist und Xs eine Liste, so kann man .(X,Xs) kurz als [X|Xs] schreiben. ?- [a, b, c] = .(a, .(b, .(c, []))), [a, b, c] = [a|[b,c]]. Yes 2 Falls Y keine Liste ist, so ist .(X,Y) immer noch ein erlaubter Term, der dann allerdings keine Liste mehr repräsentiert: ?- .(a, b) = [a|b]. Yes Prof. Dr. Dietmar Seipel 598 Deduktive Datenbanken Sommersemester 2012 Auch Listen können mittels ”=../2” zerlegt werden: ?- [a, b, c] =.. Ys. Ys = [’.’, a, [b, c]] Bekanntlich steht die Listennotation [a,b,c] für .(a,.(b,.(c,[]))). 2 Also ist der Funktor ’.’, 2 das erste Argument ist a, 2 und die Restliste ist .(b,.(c,[])), was wiederum als [b,c] angezeigt wird. Prof. Dr. Dietmar Seipel 599 Deduktive Datenbanken Sommersemester 2012 Datenstrukturen für Paare 2 Graph: Kantenmenge als Liste [a-b, a-d, b-c] 2 Multimenge: als Liste [a:2, b:3, c:1] Graph: Multimenge: b -c b a a b R c a d b 2 Liste von Koordinatenpaaren: [point(1,1), point(2,4)] Prof. Dr. Dietmar Seipel 600 Deduktive Datenbanken Sommersemester 2012 Mit pair_lists(Mode, Xs, Ys, Pairs) kann man zwei gleichlange Listen Xs und Ys zu einer genauso langen Liste Pairs paaren: /* pair_lists(Mode, Xs, Ys, Pairs) <Mode can be ’[]’, ’,’, ’;’, :, -, pair, ... */ pair_lists(Mode, [X|Xs], [Y|Ys], [Pair|Pairs]) :pair_elements(Mode, X, Y, Pair), pair_lists(Mode, Xs, Ys, Pairs). pair_lists(_, [], [], []). pair_elements(Mode, X, Y, Pair) :( Mode = ’[]’, Pair = [X, Y] ; Pair =.. [Mode, X, Y] ). Wenn man pair_elements mit If -> Then ; Else implementiert, dann funktioniert die Zerlegung von Pairs in Xs und Ys im allgemeinen nicht (z.B. nicht ohne die Angabe von Mode). Prof. Dr. Dietmar Seipel 601 Deduktive Datenbanken Sommersemester 2012 Man könnte pair_lists auch auf der Basis des Meta–Prädikats maplist/4 implementieren, welches einen Aufruf auf 3 Listen anwendet: pair_lists(Mode, Xs, Ys, Pairs) :maplist( pair_elements(Mode), Xs, Ys, Pairs ). Dies ist äquivalent zur folgenden Implementierung mittels foreach-do: pair_lists(Mode, Xs, Ys, Pairs) :foreach(X, Xs), foreach(Y, Ys), foreach(Pair, Pairs) do pair_elements(Mode, X, Y, Pair). Prof. Dr. Dietmar Seipel 602 Deduktive Datenbanken Sommersemester 2012 Für Mode sind beliebige binäre Funktoren erlaubt. ?- Xs = [a, b], Ys = [1, 2], pair_lists(’[]’, Xs, Ys, Pairs_1), pair_lists(’,’, Xs, Ys, Pairs_2), pair_lists(:, Xs, Ys, Pairs_3), pair_lists(-, Xs, Ys, Pairs_4), pair_lists(pair, Xs, Ys, Pairs_5). Pairs_1 Pairs_2 Pairs_3 Pairs_4 Pairs_5 Prof. Dr. Dietmar Seipel = = = = = [[a, 1], [b, 2]], [(a, 1), (b, 2)], [a:1, b:2], [a-1, b-2], [pair(a, 1), pair(b, 2)] 603 Deduktive Datenbanken Sommersemester 2012 Das Prädikat pair_lists/4 kann bidirectional verwendet werden: 2 Der Aufruf pair_lists(+Mode, +Xs, +Ys, -Pairs) bestimmt zu einem vorgegebenen Paarungsmodus und zwei gleichlangen Listen die Paarliste. 2 Der Aufruf pair_lists(?Mode, -Xs, -Ys, +Pairs) zerlegt eine vorgegebene Paarliste in zwei gleichlangen Listen, und er bestimmt gegebenenfalls sogar den Paarungsmodus. Xs 6 Prof. Dr. Dietmar Seipel Ys ? Pairs 6 604 Deduktive Datenbanken Sommersemester 2012 Man kann eine Paarliste Pairs in zwei gleichlange Listen Xs und Ys zerlegen und den Paarungsmodus Mode bestimmen. ?- Pairs = [pair(a, 1), pair(b, 2)], pair_lists(Mode, Xs, Ys, Pairs). Mode = pair, Xs = [a, b], Ys = [1, 2] Der Paarungsmodus Mode muß bei allen Paaren gleich sein; sonst schlägt der Aufruf fehl: ?- Pairs = [a:1, pair(b, 2)], pair_lists(Mode, Xs, Ys, Pairs). No Prof. Dr. Dietmar Seipel 605 Deduktive Datenbanken Sommersemester 2012 Operationen auf Graphen 2 Wegesuche, Erreichbarkeit (Bibliothek ugraphs.pl) 2 Bestimmung aller Knoten: edges_to_vertices(Edges, Vertices) :pair_lists(-, Xs, Ys, Edges), append(Xs, Ys, Zs), sort(Zs, Vertices). ?- Edges = [a-b, a-d, b-c], pair_lists(-, Xs, Ys, Edges), append(Xs, Ys, Zs), sort(Zs, Vertices). Xs = [a,a,b], Ys = [b,d,c], Zs = [a,a,b,b,d,c], Vertices = [a,b,c,d]. Prof. Dr. Dietmar Seipel 606 Deduktive Datenbanken Sommersemester 2012 Operationen auf Multimengen 2 Bestimmung aller Elemente bzw. der Kardinalität multiset_to_elements_and_cardinality( Set, Elements, N) :pair_lists(:, Elements, Ns, Set), add(Ns, N). ?- Set = [a:2, b:3, c:1], pair_lists(:, Elements, Ns, Set), add(Ns, N). Elements = [a, b, c], Ns = [2, 3, 1], N = 6. Prof. Dr. Dietmar Seipel 607 Deduktive Datenbanken Sommersemester 2012 P ROLOG–Operatoren Mittels des Aufrufs current_op(?Precedence, ?Type, ?Name) kann man die Präzedenz und den Typ von Operatoren ermitteln. ?- current_op(P, T, N). P = 1200, T = xfx, N = :- ; P = 1200, T = fx, N = :- ; P = 600, T = xfy, N = : ; P = 500, T = yfx, N = + ; P = 500, T = fx, N = + ; P = 400, T = yfx, N = * ; ... Momentan enthält S WI–P ROLOG etwa 60 vordefinierte Operatoren. Prof. Dr. Dietmar Seipel 608 Deduktive Datenbanken Sommersemester 2012 Der Regeloperator “:-” ist sowohl binär als auch unär: 2 Direktive (fx, unär): :- dynamic arc/2. 2 Regel (xfx, binär): tc(X, Y) :arc(X, Z), tc(Z, Y). In beiden Fällen hat er die Präzedenz 1200. Prof. Dr. Dietmar Seipel 609 Deduktive Datenbanken Sommersemester 2012 Präzedenz 2 Ein Term der Form a :- b :- c ist nicht erlaubt, da das “x” in “xfx” besagt, daß beide Argumente eine kleinere Präzedenz haben müssen als “:-”. 2 Klammerung setzt die Präzedenz auf “0” herab, so daß a :- (b :- c) (a :- b) :- c erlaubte Terme sind. 2 “X = a :- b” ist äquivalent zu “(X = a) :- b”, denn “=” (Präzedenz 700) bindet stärker als “:-” (Präzedenz 1200). Prof. Dr. Dietmar Seipel 610 Deduktive Datenbanken Sommersemester 2012 Konsequenzen: 2 Falls beim Typ das “f” in der Mitte steht, so handelt es sich um einen Infix–Operator. 2 “x” bedeutet, daß die Präzedenz eines Arguments echt kleiner sein muß als die Präzedenz des Operators, “y” bedeutet kleiner oder gleich. 2 Die kleinere Präzedenz bindet stärker. Es gilt also Punkt (“*”, 400, yfx) vor Strich (“+”, 500, yfx), d.h. |{z} 1 + 2|{z} ∗ 3 = 1 + (2 ∗ 3), und nicht |{z} ∗ |{z} 3 = (1 + 2) ∗ 3. 0 500 400 1| {z + 2} |{z} 500 400 0 2 Das “y” faßt zuerst zusammen. Es gilt also a:b:c = a:(b:c), da der Typ von “:” gleich “xfy” ist. 2 Operatoren können überladen sein. “+” ist z.B. auch ein unärer Präfix–Operator (“+”, fx). Prof. Dr. Dietmar Seipel 611 Deduktive Datenbanken Sommersemester 2012 Seien α und αi , für i = 1, 2, Terme mit den Präzedenzen γi . 2 Konstanten, Variablen und geklammerte Terme (α) haben die Präzedenz 0. 2 Einen binärer Term α1 ⊙ α2 hat dieselbe Präzedenz γ⊙ wie sein Operator ⊙. Der Typ t1 ft2 erfordert: ti = x =⇒ γi < γ⊙ und ti = y =⇒ γi ≤ γ⊙ . Z.B. ergibt sich für den Operator + mit der Präzedenz 500 und dem Typ yfx: 2 Der Term 1 + 2 + 3 muß in α1 = 1 + 2 und α2 = 3 zerlegt werden. Dann ist γ1 = 500 = γ+ und γ2 = 0 < γ+ : 1 + 2 + |{z} 3 . | {z } |{z} 500 500 0 2 Die Zerlegung in α1 = 1 und α2 = 2 + 3 ist nicht möglich, denn sie würde γ2 = 500 = γ+ ergeben und somit gegen die Bedingung γ2 < γ+ verstoßen: 1 |{z} + 2| {z + 3} . |{z} 0 Prof. Dr. Dietmar Seipel 500 500 612 Deduktive Datenbanken Sommersemester 2012 Assoziativität: 2 Für die Auswertung von arithmetischen Termen über assoziativen Operatoren wäre es eigentlich egal wie man zusammenfaßt. ?- X is 1+(2+3), X is (1+2)+3. X = 6. 2 Die ungeklammerte Fassung 1+2+3 ist äquivalent zu (1+2)+3, aber die unterschiedlichen Zusammenfassungen unifizieren nicht: ?- 1+2+3 = (1+2)+3. Yes ?- 1+(2+3) = (1+2)+3. No 2 Die Division ist nicht assoziativ, denn (16/8)/2 = 1 6= 4 = 16/(8/2). Prof. Dr. Dietmar Seipel 613 Deduktive Datenbanken Sommersemester 2012 Mittels des Aufrufs op(+Precedence, +Type, +Name) kann man die Präzedenz und den Typ eines neuen Operators definieren. ?- op(900, xfy, likes). Yes ?- current_op(800, yfx, and). Yes ?- read_term_to_picture. |: mary likes george and bill and books. Yes Prof. Dr. Dietmar Seipel 614 Deduktive Datenbanken Sommersemester 2012 Gegenwärtig sind in S WI–P ROLOG keine Standard–Operatoren mit den Typen xf bzw. yf definiert. Solche unären Postfix–Operatoren sind aber durchaus möglich: ?- op(500, yf, is_clever). Yes ?- X = is_clever(mary). X = mary is_clever. Dann werden Terme mit dem Operator (hier: is_clever ) in Postfix–Schreibweise angezeigt, selbst wenn sie in der Standard–Präfix–Schreibweise mit Klammerung eingegeben wurden. Prof. Dr. Dietmar Seipel 615 Deduktive Datenbanken Sommersemester 2012 P ROLOG–intern werden Terme als Listen repräsentiert: 2 arc(a,b) als [arc,a,b] , 2 +(2,3) als [+,2,3] . Wie in Lisp ist der Funktor das erste Listenelement, und er wird von den Argumenten gefolgt. So gesehen gibt der Operator “ =../2 ” lediglich den Blick auf die interne Listenrepräsentation frei. Die externe Präsentation eines Termes hängt vom Typ des Funktors ab: 2 Da zu arc nichts bekannt ist, wird arc(a,b) in Präfixschreibweise angezeigt. 2 Da + als Infix–Operator bekannt ist, wird +(2,3) in Infixschreibweise als 2+3 angezeigt. Prof. Dr. Dietmar Seipel 616 Deduktive Datenbanken Sommersemester 2012 Dynamischer Aufbau und Aufruf von Goals Wenn man zur Laufzeit dynamisch Goals aufbauen und aufrufen möchte, so verwendet man die Prädikate call/n , für n ≥ 1, oder apply/2 : 2 call(+Atom) , 2 call(+Atom, +Arg1 , ..., Argn−1 ) , 2 apply(+Atom, +Arguments) Dabei muß “Atom” ein atomares Goal sein und “Arguments” eine Liste, was man mit “is_list(Arguments)” testen kann. Man kann den Parameter a in einem Aufruf call(f(a),X,Y) wie bei einer mathematischen Funktionenschaar jeweils als fixiert ansehen: vgl. z.B. Y = fa (X) = a · X 2 . In der Programmierung nennt man diese Parametrisierung von Prädikaten Currying. Prof. Dr. Dietmar Seipel 617 Deduktive Datenbanken Sommersemester 2012 Wenn das Prädikatensymbol eines aufzurufenden Atoms erst zur Laufzeit berechnet oder eingelesen wird, dann muß man call/n oder apply/2 verwenden: ?- read(P), read(X), read(Y), call(P, X, Y). |: is. |: X. |: 2+3. P = (is), X = 5, Y = 2+3 Man kann hier nicht P(X,Y) anstelle von call(P,X,Y) schreiben, da das Prädikatensymbol eines Atoms immer ein P ROLOG–Atom sein muß – und folglich keine Variable sein kann. Im Aufruf call(P,X,Y) zum Meta–Prädikat call/3 taucht P dagegen – in erlaubter Weise – als Argument auf. Prof. Dr. Dietmar Seipel 618 Deduktive Datenbanken Sommersemester 2012 ?- A =.. [add, 2, 3, Z], call(A). A = add(2, 3, 5), Z = 5 ?- call((add(2, 3, Z), add(Z, 4, Y))). Z = 5, Y = 9 ?- apply(add, [2, 3, Z]). Z = 5 Äquivalent dazu kann man auch eines der folgenden 3 Goals aufrufen: apply(add(2), [3,Z]), apply(add(2,3), [Z]), apply(add(2,3,Z), []). Prof. Dr. Dietmar Seipel 619 Deduktive Datenbanken Sommersemester 2012 Man könnte apply/2 wie folgt implementieren: apply(A, Xs) :A =.. As, append(As, Xs, Bs), B =.. Bs, call(B). Zu einem atomaren Goal A und einer Liste Xs von weiteren Argumenten wird ein neues Goal B aufgebaut und aufgerufen: A = P(Y1 ,...,Yn ), Xs = [X1 ,...,Xm ], B = P(Y1 ,...,Yn ,X1 ,...,Xm ). Prof. Dr. Dietmar Seipel 620 Deduktive Datenbanken Sommersemester 2012 Das Meta–Prädikat fold/4 für assoziative Prädikate/Operatoren fold(Predicate, Acc, [X|Xs], Result) :!, apply(Predicate, [Acc, X, Acc_2]), fold(Predicate, Acc_2, Xs, Result). fold(_, Acc, [], Acc). Diese Listenrekursion kann nicht direkt mittels der bisher bekannten Meta–Prädikate ausgedrückt werden. Der Aufruf fold(+P,+I,+Xs,-O) führt für eine Liste Xs = [X1 ,...,Xn ] zu folgender Berechnung: 2 V1 = I . 2 Vi+1 wird aus Vi und Xi mittels P(Vi ,Xi ,Vi+1 ) bestimmt. 2 O = Vn+1 . Prof. Dr. Dietmar Seipel 621 Deduktive Datenbanken Sommersemester 2012 Die Reihenfolge der Regeln wurde aus Effizienzgründen ganz bewußt gewählt: 2 Die erste Regel für nicht–leere Listen [X|Xs] wird für alle Listenelemente X angewendet. 2 Durch den Cut weiß das System dann, daß die zweite Regel nicht verwendet werden kann; so kann der Choice Point frühzeitig aufgegeben werden. 2 Erst ganz am Ende der Berechnung wird einmal die zweite Regel auf die leere Liste [] angewendet. Wenn die Anfangsliste also n Elemente enthält, dann wird n mal die passende Regel, nämlich die erste, und nur diese, zuerst probiert. Nur einmal wird ganz am Ende der Berechnung zuerst die falsche Regel und dann die passende Regel, nämlich die zweite, probiert. Prof. Dr. Dietmar Seipel 622 Deduktive Datenbanken Sommersemester 2012 my_add(Xs, Y) :fold(add, 0, Xs, Y). add(X, Y, Z) :Z is X + Y. ?- my_add([2,3,4], Y). Y = 9 Aufrufe von fold/4 : fold(add, 0, [2,3,4], Y) U fold(add, 2, [3,4], Y) U fold(add, 5, [4], Y) Vi Xi U Vi+1 U fold(add, 9, [], Y) Prof. Dr. Dietmar Seipel 623 Deduktive Datenbanken Sommersemester 2012 Die Implementierung mittels fold/4 ist kürzer und eleganter als die bereits bekannte end–rekursive Implementierung mittels Akkumulatoren: sum(Xs, Sum) :sum(Xs, 0, Sum). sum([X|Xs], Acc, Sum) :Acc_2 is Acc + X, sum(Xs, Acc_2, Sum). sum([], Acc, Acc). Man kann die Parallelen in den Implementierungen von sum/3 und fold/4 erkennen. Letzteres verwendet anstelle von ”+” ein beliebiges Prädikat als Parameter. Prof. Dr. Dietmar Seipel 624 Deduktive Datenbanken Sommersemester 2012 Die Berechnung startet mit dem neutralen Element (Summe: 0, Produkt: 1). Darauf werden die Zahlen aus Xs von links beginnend addiert bzw. multipliziert: my_multiply(Xs, Y) :fold(multiply, 1, Xs, Y). ?- my_multiply([2,3,4], Y). Y = 24 ?- my_multiply([], Y). Y = 1 Die leere Summe ist 0, das leere Produkt ist 1. Prof. Dr. Dietmar Seipel 625 Deduktive Datenbanken Sommersemester 2012 Auch eine Liste von Listen kann man mittels fold/4 aneinander hängen: append(Lists, List) :fold(append, [], Lists, List). ?- append([[1, 2], [a, b, c], [x, y]], List). List = [1, 2, a, b, c, x, y] ?- append([], List). List = [] Für lange Listen wäre hier allerdings eine effizientere Implementierung vorzuziehen, da man sonst sehr oft an eine immer länger werdende Liste im Akkumulator hinten anhängt. Prof. Dr. Dietmar Seipel 626 Deduktive Datenbanken Sommersemester 2012 4.1.2 Logikprogramme als Klauseln oder als Terme Mit den folgenden D DK–Prädikaten kann man zwischen der Repräsentation von Fakten als P ROLOG–Klauseln bzw. als Listen wechseln: 2 assert_facts/1: speichert eine gegebene Liste von Fakten in der P ROLOG–Datenbank 2 collect_facts/2: sammelt alle Fakten zu einem gegebenen Prädikat aus der P ROLOG–Datenbank 2 retract_facts/2: sammelt alle Fakten zu einem gegebenen Prädikat aus der P ROLOG–Datenbank und löscht sie dort gleichzeitig Prof. Dr. Dietmar Seipel 627 Deduktive Datenbanken Sommersemester 2012 % assert_facts(+Facts) <assert_facts(Facts) :foreach(A, Facts) do assert(A). % collect_facts(+Predicate/Arity, -Facts) <collect_facts(Predicate/Arity, Facts) :functor(Fact, Predicate, Arity), findall( Fact, clause(Fact, true), Facts ). Prof. Dr. Dietmar Seipel 628 Deduktive Datenbanken Sommersemester 2012 Man muß in collect_facts/2 den Aufruf clause(Fact, true) machen, und nicht call(Fact). Sonst würde man das Programm auswerten anstelle nach Fakten zu suchen. Der Aufruf collect_facts(a/1, Facts) würde für das Programm a(1). a(2) :- b. b. z.B. falsche Resultate liefern: 2 mit clause/2: Facts = [a(1)]. 2 mit call/1: Facts = [a(1), a(2)]. Prof. Dr. Dietmar Seipel 629 Deduktive Datenbanken Sommersemester 2012 % retract_facts(+Predicate/Arity, -Facts) <retract_facts(Predicate/Arity) :functor(Fact, Predicate, Arity), retractall(Fact). retract_facts(Predicate/Arity, Facts) :functor(Fact, Predicate, Arity), findall( Fact, retract(Fact), Facts ). Würde man retract_facts(P/A) mittels retract_facts(P/A, _) implementieren, so würde die Liste der gelöschten Fakten umsonst berechnet. Prof. Dr. Dietmar Seipel 630 Deduktive Datenbanken Sommersemester 2012 ?- Facts = [ price(screw, 2), components(engine, cylinder, 4), components(engine, valve, 4) ], assert_facts(Facts). Yes ?- listing(components/3). :- dynamic components/3. components(engine, cylinder, 4). components(engine, valve, 4). Yes ?- retract_facts(components/3). Yes ?- listing(components/3). :- dynamic components/3. Yes Prof. Dr. Dietmar Seipel 631 Deduktive Datenbanken Sommersemester 2012 Regeln in D IS L OG 2 In D IS L OG können normale Regeln A ← B1 ∧ . . . ∧ Bm ∧ not C1 ∧ . . . ∧ not Cn als P ROLOG–Terme [A]-[B1,...,Bm]-[C1,...,Cn] repräsentiert werden. 2 Falls n = 0 ist, so können wir auch [A]-[B1,...,Bm] schreiben; falls n = m = 0 ist, so können wir auch [A] schreiben. 2 Beispiel einer definiten Regel: [tc(X, Y)]-[arc(X, Z), tc(Z, Y)] Prof. Dr. Dietmar Seipel 632 Deduktive Datenbanken Sommersemester 2012 Es wurde die Listennotation für Regelköpfe gewählt um Regeln mit beliebig vielen Kopfatomen (z.B. auch Goals mit 0 Kopfatomen) repräsentieren zu können. 2 In D IS L OG können disjunktive Regeln A1 ∨ . . . ∨ Ak ← B1 ∧ . . . ∧ Bm ∧ not C1 ∧ . . . ∧ not Cn als P ROLOG–Terme [A1,...,Ak]-[B1,...,Bm]-[C1,...,Cn] repräsentiert werden. Prof. Dr. Dietmar Seipel 633 Deduktive Datenbanken Sommersemester 2012 Input/Ouput für Files 2 Der Aufruf dread(+Type, +File, -Rules) lädt ein Logikprogramm aus einem File in eine Liste von D IS L OG–Regeln (für Type = lp ) bzw. P ROLOG–Regeln (für Type = pl ). 2 Der Aufruf dwrite(+Type, +File, +Rules) schreibt eine Liste von D IS L OG– (für Type = lp ) bzw. P ROLOG–Regeln (für Type = pl ) in ein File. 2 Falls File = user, so erfolgt die Ausgabe auf der Konsole. Dann kann man auch einfach dwrite(+Type, +Rules) aufrufen. Prof. Dr. Dietmar Seipel 634 Deduktive Datenbanken Sommersemester 2012 ?- dread(lp, ’tc.pl’, Program), tp_iteration(Program, Interpretation). ... Program = [ [tc(X, Y)]-[arc(X, Y)], [tc(X, Y)]-[arc(X, Z), tc(Z, Y)], [arc(a, b)], [arc(b, c)], [arc(c, d)] ] Interpretation = [ arc(a, b), arc(b, c), arc(c, d), tc(a, b), tc(a, c), tc(a, d), tc(b, c), tc(b, d), tc(c, d) ] Prof. Dr. Dietmar Seipel 635 Deduktive Datenbanken Sommersemester 2012 ?- Program = [ [tc(X, Y)]-[arc(X, Y)], [tc(X, Y)]-[arc(X, Z), tc(Z, Y)], [arc(a, b)], [arc(b, c)], [arc(c, d)] ], dwrite(lp, Program), dwrite(lp, ’tc_new.pl’, Program). tc(X1, tc(X1, arc(a, arc(b, arc(c, X2) :- arc(X1, X2). X2) :- arc(X1, X3),tc(X3, X2). b). c). d). Program = [...] Prof. Dr. Dietmar Seipel 636 Deduktive Datenbanken Sommersemester 2012 Konversion In P ROLOG würde eine D IS L OG–Regel [A]-[B1,...,Bm]-[C1,...,Cn] mit atomarem Regelkopf anstelle von Listen im Regelrumpf mit Hilfe von Komma–Strukturen repräsentiert werden als A :- (B1,...,Bm,not(C1),...,not(Cn)) 2 Die Umformung einer Liste in eine Komma–Struktur erfolgt mittels list_to_comma_structure(Atoms, Body). 2 Die Umformung einer Komma–Struktur in eine Liste erfolgt mittels comma_structure_to_list(Body, Atoms). Prof. Dr. Dietmar Seipel 637 Deduktive Datenbanken Sommersemester 2012 Das Prädikat dislog_rule_to_prolog_rule/2 überführt eine D IS L OG–Regel nach P ROLOG: % dislog_rule_to_prolog_rule(+Rule_1, -Rule_2) <dislog_rule_to_prolog_rule(Rule_1, Rule_2) :parse_dislog_rule(Rule_1, [A], [ ], [ ]), !, Rule_2 = A. dislog_rule_to_prolog_rule(Rule_1, Rule_2) :parse_dislog_rule(Rule_1, [A], Bs, Cs), ( foreach(C, Cs), foreach(D, Ds) do D = not(C) ), append(Bs, Ds, Atoms), list_to_comma_structure(Atoms, Body), Rule_2 = (A :- Body). Prof. Dr. Dietmar Seipel 638 Deduktive Datenbanken Sommersemester 2012 Das Prädikat prolog_rule_to_dislog_rule/2 überführt eine P ROLOG–Regel nach D IS L OG: % prolog_rule_to_dislog_rule(+Rule_1, -Rule_2) <prolog_rule_to_dislog_rule(Rule_1, Rule_2) :Rule_1 = (A :- Body), !, ( Body = true -> Rule_2 = [A] ; comma_structure_to_list(Body, Atoms), findall( B, ( member(B, Atoms), B \= not(_) ), Bs ), findall( C, member(not(C), Atoms), Cs ), Rule_2 = [A]-Bs-Cs ), !. prolog_rule_to_dislog_rule(A, [A]). Prof. Dr. Dietmar Seipel 639 Deduktive Datenbanken Sommersemester 2012 Die folgenden Bilder zeigen die Regel tc(X, Y) :arc(X, Z), tc(Z,Y). als P ROLOG–Term (links) bzw. als D IS L OG–Term (rechts): Prof. Dr. Dietmar Seipel 640 Deduktive Datenbanken Sommersemester 2012 % dislog_rules_to_prolog_rules(+Rules_1, -Rules_2) <dislog_rules_to_prolog_rules(Rules_1, Rules_2) :maplist( dislog_rule_to_prolog_rule, Rules_1, Rules_2 ). % prolog_rules_to_dislog_rules(+Rules_1, -Rules_2) <prolog_rules_to_dislog_rules(Rules_1, Rules_2) :maplist( prolog_rule_to_dislog_rule, Rules_1, Rules_2 ). Prof. Dr. Dietmar Seipel 641 Deduktive Datenbanken Sommersemester 2012 Einfügen und Löschen in der internen P ROLOG–Datenbank Mit den folgenden D DK–Prädikaten kann man zwischen der Repräsentation von Regeln als P ROLOG–Terme (auf Argumentebene) bzw. als P ROLOG–Klauseln (in der internen P ROLOG–Datenbank) wechseln: 2 assert_rules/1: speichert eine gegebene Liste von P ROLOG–Regeln in der P ROLOG–Datenbank 2 collect_rules/2: sammelt alle P ROLOG–Regeln zu einem gegebenen Prädikat aus der P ROLOG–Datenbank 2 retract_rules/2: sammelt alle P ROLOG–Regeln zu einem gegebenen Prädikat aus der P ROLOG–Datenbank und löscht sie dort gleichzeitig Es gibt jeweils eine entsprechende Version für D IS L OG–Regeln. Prof. Dr. Dietmar Seipel 642 Deduktive Datenbanken Sommersemester 2012 % assert_rules(+Rules) <assert_rules(Rules) :foreach(Rule, Rules) do assert(Rule). % assert_dislog_rules(+Rules) <assert_dislog_rules(Rules) :dislog_rules_to_prolog_rules(Rules, Rules_2), assert_rules(Rules_2). Ein P ROLOG–Fakt A ist dabei äquivalent zu einer Regel A :- true, und ein D IS L OG–Fakt [A] ist äquivalent zu einer Regel [A]-[]. Prof. Dr. Dietmar Seipel 643 Deduktive Datenbanken Sommersemester 2012 ?- Program = [ [tc(X, Y)]-[arc(X, Y)], [tc(X, Y)]-[arc(X, Z), tc(Z, Y)], [arc(a, b)], [arc(b, c)], [arc(c, d)] ], assert_dislog_rules(Program). Program = [...] ?- tc(a, Y). Y = b; Y = c; Y = d Prof. Dr. Dietmar Seipel 644 Deduktive Datenbanken Sommersemester 2012 % collect_rules(+Predicate/Arity, -Rules) <collect_rules(Predicate/Arity, Rules) :functor(A, Predicate, Arity), findall( Rule, ( clause(A, As), ( As = true -> Rule = A ; Rule = (A :- As) ) ), Rules ). % collect_dislog_rules(+Predicate/Arity, -Rules) <collect_dislog_rules(Predicate/Arity, Rules) :collect_rules(Predicate/Arity, Rules_2), prolog_rules_to_dislog_rules(Rules_2, Rules). Prof. Dr. Dietmar Seipel 645 Deduktive Datenbanken Sommersemester 2012 ?- collect_rules(tc/2, Rules). Rules = [ (tc(X, Y) :- arc(X, Y)), (tc(X, Y) :- arc(X, Z), tc(Z, Y)) ] ?- collect_dislog_rules(tc/2, Rules). Rules = [ [tc(X, Y)]-[arc(X, Y)], [tc(X, Y)]-[arc(X, Z), tc(Z, Y)] ] Prof. Dr. Dietmar Seipel 646 Deduktive Datenbanken Sommersemester 2012 % retract_rules(+Predicate/Arity, -Rules) <retract_rules(Predicate/Arity, Rules) :functor(A, Predicate, Arity), findall( Rule, ( retract(A :- As), ( As = true -> Rule = A ; Rule = (A :- As) ) ), Rules ). % retract_dislog_rules(+Predicate/Arity, -Rules) <retract_dislog_rules(Predicate/Arity, Rules) :retract_rules(Predicate/Arity, Rules_2), prolog_rules_to_dislog_rules(Rules_2, Rules). Prof. Dr. Dietmar Seipel 647 Deduktive Datenbanken Sommersemester 2012 Speichern in einem Modul der P ROLOG–Datenbank: % assert_facts(+Module, +Facts) <assert_facts(Module, Facts) :foreach(A, Facts) do assert(Module:A). % assert_rules(+Module, +Rules) <assert_rules(Module, Rules) :foreach(Rule, Rules) do Module:assert(Rule). assert(M:X) ist äquivalent zu M:assert(X) für Fakten und Regeln X. Als Spezialfälle für M = user ergeben sich die bisherigen Prädikate: assert_facts(Facts) :- assert_facts(user, Facts). assert_rules(Rules) :- assert_rules(user, Rules). Prof. Dr. Dietmar Seipel 648 Deduktive Datenbanken Sommersemester 2012 4.1.3 Die Field Notation für komplexe Objekte In einem P ROLOG–Fakt ergibt sich die Bedeutung der Argumente aus ihrer Position: person(’Sampras’, 1971, male) In X ML speichert man dagegen die Attribute mit: <person name="Sampras" born="1971" sex="male"/> Äquivalent dazu kann man natürlich auch in einem entsprechenden P ROLOG–Term die Attribute mitführen: person:[name:’Sampras’, born:1971, sex:male]:[] Die leere Liste am Ende des P ROLOG–Terms repräsentiert die leere Liste von Unterelementen des X ML–Elements. Prof. Dr. Dietmar Seipel 649 Deduktive Datenbanken Sommersemester 2012 Assoziationslisten 2 In P ROLOG kann man komplexe Objekte bestehend aus Paaren ai : vi , wobei ai ein Attributname ist und vi der zugehörige Attributwert, wie folgt als Listen abspeichern: [a1 : v1 , . . . , an : vn ]. 2 Diese Art der Speicherung nennt man Assoziationsliste. Da jeder Attributwert von seinem zugehörigen Attributnamen begleitet wird, ist die Reihenfolge der Listenelemente offensichtlich beliebig. 2 Dabei sind die “ai : vi ” P ROLOG–Terme in Infix–Notation mit dem Funktor “:” und den zwei Argumenten “ai ” und “vi ”. 2 Die Attributwerte vi können auch selbst wieder komplexe Objekte sein. Prof. Dr. Dietmar Seipel 650 Deduktive Datenbanken Sommersemester 2012 Vorteile 2 Man kann sehr komfortabel semistrukturierte Daten (wie z.B. X ML–Daten) repräsentieren und Anfragen daran stellen. 2 Man kann mit Attributnamen anstelle von Argumentpositionen arbeiten. Da jeder Attributwert von seinem zugehörigen Attributnamen begleitet wird, ist die Reihenfolge der Listenelemente beliebig. 2 Fehlende Attributwerte (Nullwerte) kann man einfach weglassen, und man kann jederzeit ohne Probleme bei beliebigen Objekten Attributwerte zu weiteren Attributnamen hinzufügen. 2 Dadurch kann man auch jederzeit das zugrundeliegende Datenbankschema erweitern. In der Objektorientierung wird dieses Problem mit der Vererbung gelöst. Prof. Dr. Dietmar Seipel 651 Deduktive Datenbanken Sommersemester 2012 Das Document Object Model (DOM) für X ML Auf der Basis von Assoziationslisten werden komplexe Objekte in Field Notation (FN) definiert, die FN–Tripel: 2 T und C seien P ROLOG–Terme und As eine Assoziationsliste. Dann ist O = T : As : C ein FN–Tripel mit dem Tag T und dem Inhalt C. 2 Bei einem FN–Tripel O = T : As : C, in dem C = [c1 , . . . , cm ] eine Liste mit FN–Objekten ist, wird jedes ci als Subelement von O bezeichnet. 2 Wenn As = [a1 : v1 , ..., an : vn ], dann wird jedes ai als Attribut von O und vi als der dazugehörige Wert bezeichnet. 2 Ist die Attributliste leer, kann man das FN–Tripel zu T : C vereinfachen. T : C ist also äquivalent zu T : [ ] : C. Der P ROLOG–Aufruf fn_item_parse(O, T:As:C) zerlegt ein FN–Tripel in seine Bestandteile. Für O = T : C erhalten wir As = [ ]. Prof. Dr. Dietmar Seipel 652 Deduktive Datenbanken Sommersemester 2012 Das FN–Tripel a:[b:1]:[c:[2]] zum X ML–Element <a b="1"> <c>2</c> </a> hat folgende Term–Struktur: Prof. Dr. Dietmar Seipel 653 Deduktive Datenbanken Sommersemester 2012 Vergleich von S WI und D DK 2 Im DOM von S WI–P ROLOG wird ein X ML–Element als Term der Form element(T,As,C) repräsentiert. Die Attribut/Wert–Paare werden als A=V in einer Assoziationsliste As repräsentiert, und die Unterelemente bilden auch wieder eine Liste C . Hier würde das X ML–Element <a b="1"> <c>2</c> </a> repräsentiert als element(a,[b=’1’],[element(c,[],[’2’])]). 2 Das DOM von S WI–P ROLOG ist offensichtlich äquivalent zu den FN–Tripeln T:As:C aus dem D DK; letztere sind allerdings etwas kompakter. Prof. Dr. Dietmar Seipel 654 Deduktive Datenbanken Sommersemester 2012 Beispiel (X ML vs. Field Notation) 2 Das folgende X ML–Objekt speichert Informationen über die Teile eines Autos: <components> <component name="engine"> <part name="sparkplug" quantity="4"/> <part name="cylinder" quantity="4"/> <part name="valve" quantity="4"/> ... </component> <component name="valve"> <part name="gasket" quantity="1"/> <part name="hanger" quantity="1"/> </component> ... </components> Prof. Dr. Dietmar Seipel 655 Deduktive Datenbanken Sommersemester 2012 2 Repräsentation in Field Notation: components:[ component:[name:engine]:[ part:[name:sparkplug, quantity:4]:[], part:[name:cylinder, quantity:4]:[], part:[name:valve, quantity:4]:[], ... ], component:[name:valve]:[ part:[name:gasket, quantity:1]:[], part:[name:hanger, quantity:1]:[] ], ... ] Leere Listen von Unterelementen muß man aufführen. Leere Attributlisten – wie bei components:[...] – kann man weglassen. Prof. Dr. Dietmar Seipel 656 Deduktive Datenbanken Sommersemester 2012 Ein– und Ausgabe von X ML–Dateien 2 Das Einlesen X ML–Datei erfolgt mittels dread(xml, +File, -List) . Dabei ist List eine Liste, deren letztes Element das FN–Tripel aus der Datei ist. Mögliche andere Elemente können Processing–Instructions etc. sein. 2 Das Ausgeben eines FN–Tripels in eine X ML–Datei erfolgt mittels dwrite(xml, +File, +Fn_Triple) . Hier wird also keine Liste verwendet. Das Einlesen basiert intern auf dem Parser und dem X ML–DOM von S WI–P ROLOG. Prof. Dr. Dietmar Seipel 657 Deduktive Datenbanken Sommersemester 2012 Deklarativer Zugriffsoperator im D DK Der deklarative Zugriffsoperator wurde mit Hilfe eines zweistelligen Prädikats “ := ” in Infix–Notation realisiert (vgl. is/2 ). Sei O = T : As : C ein FN–Tripel, X eine Variable und Y ein P ROLOG–Term: 2 Dann liefert X := O/Y in X die Sub–Elemente von O mit dem Tag Y. 2 Dann liefert X := O@Y in X den Attributwert von O zu Y. 2 Dann liefert fn_item_parse(O, X:_:_) in X das Tag T von O. Der Operator ”/” kann zur Bildung komplexer Pfadausdrücke iteriert werden: X := O/a/b@c selektiert z.B. der Reihe nach das a–Sub–Element von O, dann dessen b–Sub–Element, und dann dessen Attributwert zum Attribut c. Prof. Dr. Dietmar Seipel 658 Deduktive Datenbanken Sommersemester 2012 Beispiel (Zugriff auf Field Notation) 2 Die folgende Anfrage liefert die erste Komponente des Motors: ?- C = component:[name:engine]:[ part:[name:sparkplug, quantity:4]:[], part:[name:cylinder, quantity:4]:[], part:[name:valve, quantity:4]:[], ... ], P := C/part. P = part:[name:sparkplug, quantity:4]:[] Prof. Dr. Dietmar Seipel 659 Deduktive Datenbanken Sommersemester 2012 2 Die folgende Anfrage liefert den Namen des ersten Teils des Motors. Bei Backtracking liefert sie die Namen der weiteren Teile. ?- C = component:[name:engine]:[ part:[name:sparkplug, quantity:4]:[], part:[name:cylinder, quantity:4]:[], part:[name:valve, quantity:4]:[], ... ], N := C/part@name. N = sparkplug ; N = cylinder ; N = valve Prof. Dr. Dietmar Seipel 660 Deduktive Datenbanken Sommersemester 2012 Analyse von Spielsequenzen beim Tennis Es werden Tennis–Matches zusammen mit den entsprechenden Video–Sequenzen erfaßt. Die Taktikanalyse soll erfolgreiche Spielzüge identifizieren. Prof. Dr. Dietmar Seipel 661 Deduktive Datenbanken Sommersemester 2012 Die Ballwechsel werden in X ML (Field Notation) repräsentiert: <set id="1"> <game id="1" service="A"> <point id="1" top="B" winner="A"> <hit id="1" hand="forehand" type="ground" time="00:00:42" x="0.17" y="-12.07"/> <hit id="2" hand="backhand" type="ground" time="00:00:44" x="-0.49" y="5.89"/> <hit id="3" hand="backhand" type="ground" time="00:00:46" x="-3.92" y="-3.42"/> <hit id="4" hand="forehand" type="ground" time="00:00:48" x="3.56" y="2.06"/> </point> <point id="2" ...> ... </point> ... </game> ... </set> Prof. Dr. Dietmar Seipel 662 Deduktive Datenbanken Sommersemester 2012 Die Ballwechsel sind mit Video–Sequenzen hinterlegt: Es können Anfragen an die Daten gestellt werden, und die Ergebnisse können mit den entsprechenden Video–Sequenzen illustriert werden. Prof. Dr. Dietmar Seipel 663 Deduktive Datenbanken Sommersemester 2012 Beispiel: Anfrage in F N Query Für ein in X ML (Field Notation) gegebenes Tennis–Match werden nach Sätzen und Spielen aggregiert die durchschnittlichen Längen (Anzahl der Schläge bzw. Länge des Ballweges) der Ballwechsel ( point ) berechnet: average_point_distances(Match, Set, Tuples) :ddbase_aggregate( [Set, Game, Player, average(L), average(D)], ( Point := Match/set::[@id=Set]/ game::[@id=Game, @service=Service]/point, Player := Match/player::[@id=Service]@name, point_to_length_and_distance(Point, L, D) ), Tuples ). Auch der aufschlagende Spieler wird mit ausgegeben. Prof. Dr. Dietmar Seipel 664 Deduktive Datenbanken Sommersemester 2012 Wir wenden die Anfrage auf den ersten Satz des X ML–Files 2002_sampras_agassi_final.xml an und zeigen die berechneten Tupel in einer X PCE–Tabelle: ?- File = ’2002_sampras_agassi_final.xml’, dread(xml, File, [Match]), Set = ’1’, average_point_distances(Match, Set, Tuples), Attributes = [’Set’, ’Game’, ’Service’, ’Hits’, ’Dist’], xpce_display_table(Attributes, Tuples). Prof. Dr. Dietmar Seipel 665 Deduktive Datenbanken Sommersemester 2012 Wie erwartet zeigt sich, daß bei den Aufschlagspielen von Samprass die Ballwechsel im Schnitt deutlich kürzer sind. Als Serve&Volley–Spieler rückt er meist frühzeitig ans Netz auf, um den Ballwechsel zu beenden: Prof. Dr. Dietmar Seipel 666 Deduktive Datenbanken Sommersemester 2012 Analyse und Refaktorisierung von Logikprogrammen Natürlich kann man auch P ROLOG–Regeln in X ML repräsentieren. Ziele: 2 Programmanalyse hinsichtlich – Modularsierung, – Struktureigenschaften (Rekursion, Argumente), – Design Patterns; 2 Refaktorisierung; 2 Slicing (Extraktion einer Teilfunktion). Prof. Dr. Dietmar Seipel 667 Deduktive Datenbanken Sommersemester 2012 P ROLOG–Regeln in X ML: tc(X, Y) :- arc(X, Y). tc(X, Y) :- arc(X, Z), tc(Z, Y). <definition predicate="(user:tc)/2"> ... <rule file="tc.pl"> <head> <atom predicate="tc/2"> <var name="X"/> <var name="Y"/> </atom> </head> <body> <atom predicate="arc/2"> ... </atom> <atom predicate="tc/2"> ... </atom> </body> </rule> </definition> Prof. Dr. Dietmar Seipel 668 Deduktive Datenbanken Sommersemester 2012 X ML–Anfrage in F N Query Bestimme alle Atome in einem Regel–Kopf oder –Rumpf, die eine Variable namens “ X ” enthalten. Prof. Dr. Dietmar Seipel 669 Deduktive Datenbanken 4.2 Sommersemester 2012 Kontrollstrukturen und Meta–Prädikate von P ROLOG 2 Finden aller Lösungen: findall/3, bagof/3, setof/3 2 Test bzw. Filter: checklist/2, sublist/2 2 Transformation: maplist/3 2 Schleifen: – forall(Condition, Action), – for(I, N, M) do Goal, – foreach(X, Xs) do Goal mit dem Prädikatensymbol do/2 (Bibliothek loops.pl von J. Schimpf) 2 Verzweigungen: If -> Then; Else Prof. Dr. Dietmar Seipel 670 Deduktive Datenbanken Sommersemester 2012 4.2.1 Finden aller Lösungen Der Aufruf findall(Y, Goal, Ys) bestimmt die Liste Ys aller Lösungen Y von Goal. Dabei kommt Y meist in Goal vor, Ys sollte hingegen nicht darin vorkommen. Der folgende Aufruf selektiert alle positiven Zahlen aus einer Liste Xs : ?- Xs = [-1,2], findall( Y, ( member(Y, Xs), Y > 0 ), Ys ). Ys = [2] Prof. Dr. Dietmar Seipel 671 Deduktive Datenbanken Sommersemester 2012 Beim Aufruf <setof/bagof>(Y, Goal, Ys) werden alle Variablen aus Goal , die nicht in Y vorkommen, ebenfalls gebunden, und es wird nach ihnen gruppiert. Sei Xs die Liste dieser freien Variablen. Für jede Belegung von Xs werden mittels Goal alle Belegungen für Y berechnet, und sie bilden die Liste Ys : 2 setof/3 berechnet die Liste Ys ohne Wiederholungen. 2 bagof/3 berechnet die Liste Ys mit Wiederholungen. Nur die Variablen aus Y bleiben unverändert. Über Backtracking kann man die Lösungen für Xs und Ys durchgehen. 2 findall/3 erzeugt dagegen nur eine Bindung für Ys; die Variablen aus Y und Xs bleiben unverändert. Prof. Dr. Dietmar Seipel 672 Deduktive Datenbanken Sommersemester 2012 Im folgenden ist Y eine Variable, und Xs besteht nur aus der Variablen X : a(1, 2). a(1, 3). a(2, 4). a(1, 2). ?- setof( Y, a(X, Y), Ys ). Y = _G281, X = 2, Ys = [4] ; Y = _G281, X = 1, Ys = [2, 3] ?- bagof( Y, a(X, Y), Ys ). Y = _G281, X = 2, Ys = [4] ; Y = _G281, X = 1, Ys = [2, 3, 2] ?- findall( Y, a(X, Y), Ys ). Y = _G281, X = _G280, Ys = [2, 3, 4, 2] Prof. Dr. Dietmar Seipel 673 Deduktive Datenbanken Sommersemester 2012 Die Gruppierung nach X kann unterbunden werden, indem man X^ voranstellt; dieses ist ein Existenzquantor für X: a(1, 2). a(1, 3). a(2, 4). a(1, 2). ?- setof( Y, X^a(X, Y), Ys ). Y = _G281, X = _G280, Ys = [2, 3, 4] ?- bagof( Y, X^a(X, Y), Ys ). Y = _G281, X = _G280, Ys = [2, 3, 4, 2] 2 Dann verhält sich bagof/3 wie findall/3 , und setof/3 liefert eine sortierte Liste Ys ohne Duplikate. 2 Für findall/3 hat der Existenzquantor keinen Effekt. Prof. Dr. Dietmar Seipel 674 Deduktive Datenbanken Sommersemester 2012 Wenn Goal im Aufruf <setof/bagof>(Y, Goal, Ys) fehlschlägt, dann schlägt der gesamte Aufruf von setof/bagof fehl; dagegen liefert findall(Y, Goal, Ys) in diesem Fall eine leere Liste Ys als Resultat: a(1, 2). a(1, 3). a(2, 4). a(1, 2). ?- setof( Y, a(3, Y), Ys ). No. ?- bagof( Y, a(3, Y), Ys ). No. ?- findall( Y, a(3, Y), Ys ). Ys = []. Prof. Dr. Dietmar Seipel 675 Deduktive Datenbanken Sommersemester 2012 Mittels setof/3 kann man multiset_to_elements/2 eleganter implementieren: multiset_to_elements(Multiset, Xs) :setof( X, N^member(X:N, Multiset), Xs ). ?- multiset_to_elements([c:1, a:2, b:3, a:4], M). M = [a, b, c] Es werden alle ersten Komponenten X der Paare X:N aus Multiset berechnet und sortiert und ohne Duplikate zurückgegeben. Prof. Dr. Dietmar Seipel 676 Deduktive Datenbanken Sommersemester 2012 Mittels bagof/3 kann man multiset_normalize/2 kürzer implementieren: multiset_normalize(M1, M2) :findall( X:M, ( bagof( N, member(X:N, M1), Ns ), sum(Ns, M) ), M3 ), sort(M3, M2). ?- multiset_normalize([c:1, a:2, b:3, a:4], M). M = [a:6, b:3, c:1] bagof(N, member(X:N, M1), Ns) berechnet für jedes X die Liste Ns der Häufigkeiten N , mit denen X in M1 vorkommt. Prof. Dr. Dietmar Seipel 677 Deduktive Datenbanken Sommersemester 2012 Diese Aggregation kann man mittels ddbase_aggregate/3 , welches auf der Basis von findall/3 realisiert ist, noch eleganter implementieren: multiset_normalize(M1, M2) :ddbase_aggregate( [X, sum(N)], member(X:N, M1), Pairs ), re_pair_list(:, Pairs, M2). ?- multiset_normalize([c:1, a:2, b:3, a:4], M). M = [a:6, b:3, c:1] Die von ddbase_aggregate/3 gelieferte Liste Pairs aus Tupeln [X, S] muß hinterher mittels re_pair_list/3 zu einer Liste aus Paaren X:S transformiert werden. Prof. Dr. Dietmar Seipel 678 Deduktive Datenbanken Sommersemester 2012 Mittels setof/3 kann man einen Graphen von der Kantendarstellung in die Adjazenzdarstellung überführen: edges_to_ugraph(Edges, Ugraph) :findall( V-Ws, setof( W, member(V-W, Edges), Ws ), Xs ), setof( V-[], ( W^member(W-V, Edges), not(member(V-_, Edges)) ), Ys ), append(Xs, Ys, Zs), sort(Zs, Ugraph). ?- edges_to_ugraph([a-b, b-c, a-d], Graph). Ugraph = [a-[b, d], b-[c], c-[], d-[]] Prof. Dr. Dietmar Seipel 679 Deduktive Datenbanken Sommersemester 2012 Auf der Basis von findall/3 kann man die bekannte Mengenkonstruktion im Rahmen des funktionalen Auswertungsprädikats “ <= ” sehr intuitiv formulieren (syntactic sugar): X <= Y :Y = { T | Goal }, !, findall( T, Goal, X ). ?- Set <= { N | between(1, 5, N), even(N) }. Set = [2, 4]. In der Mathematik würde man schreiben: Set := { N | N ∈ IN0 ∧ 1 ≤ N ≤ 5 ∧ even(N ) }. {z } | between(1 ,5 ,N ) Prof. Dr. Dietmar Seipel 680 Deduktive Datenbanken Sommersemester 2012 Der P ROLOG–Term zur Mengenkonstruktion hat den folgenden Term–Graphen: Set <= { N | between(1, 5, N), even(N) }. Prof. Dr. Dietmar Seipel 681 Deduktive Datenbanken Sommersemester 2012 4.2.2 Filter und Transformationen Mittels checklist/2 und sublist/3 kann man testen bzw. filtern (selektieren). Die folgenden Aufrufe testen, ob alle Elemente einer Liste positiv sind, bzw. selektieren die positiven Elemente: ?- Xs = [-1,2], checklist( <(0), Xs ). No ?- Xs = [-1,2], sublist( <(0), Xs, Ys ). Ys = [2] <(0) wird mit einem weiteren Argument X , das zur Laufzeit aus der Liste Xs gespeist wird, zu einem Atom <(0,X) (in Infix–Notation: 0 < X ) aufgefüllt. Prof. Dr. Dietmar Seipel 682 Deduktive Datenbanken Sommersemester 2012 Transformationen maplist/3 transformiert eine Eingabeliste in eine gleichlange Ausgabeliste. ?- Xs = [-1,2], maplist( abs, Xs, Ys ). Ys = [1,2] Der Aufruf maplist(abs, Xs, Ys) erzeugt für jedes Element X aus der Eingabeliste Xs mittels abs(X,Y) ein neues Element Y für die Ausgabeliste Ys. Prof. Dr. Dietmar Seipel 683 Deduktive Datenbanken Sommersemester 2012 Wenn wir ein geeignetes Additions–Prädikat add/3 definieren, dann können wir auf alle Elemente einer Liste eine feste Zahl addieren: add(X, Y, Z) :Z is X + Y. ?- maplist( add(2), [1, 2, 4], Ys ). Ys = [3, 4, 6] Der Aufruf maplist(add(2), Xs, Ys) erzeugt für jedes Element X aus der Eingabeliste Xs mittels add(2,X,Y) ein neues Element Y für die Ausgabeliste Ys. Prof. Dr. Dietmar Seipel 684 Deduktive Datenbanken Sommersemester 2012 Wenn man add/3 geeignet umkehrbar macht, dann kann man auch in maplist/3 Eingabe und Ausgabe vertauschen: add(X, Y, Z) :( number(X), number(Y) -> Z is X + Y ; number(X), number(Z) -> Y is Z - X ; number(Y), number(Z) -> X is Z - Y ). ?- maplist( add(2), Xs, [3, 4, 6] ). Xs = [1, 2, 4] Außerdem kann es aufgrund der Tests mittels number/1 jetzt auch keine Typfehler mehr geben. Prof. Dr. Dietmar Seipel 685 Deduktive Datenbanken Sommersemester 2012 4.2.3 Schleifen und Verzweigungen 2 Der Aufruf forall(Condition, Action) generiert mittels Condition über Backtracking Variablenbindungen, die dann beim Aufruf von Action benutzt werden. Es erfolgt kein Backtracking über Action . 2 Der Aufruf Generator do Action der Prädikats do/2 aus der Bibliothek loops.pl von J. Schimpf generiert mittels Generator Variablenbindungen, die dann beim Aufruf von Action benutzt werden. In Generator können Konstrukte wie for(I, N, M) und foreach(X, Xs) gemischt werden. Im Vergleich zu maplist/(n + 1) kann man in Action jeweils flexibler die generierten Variablenbindungen benutzen. Die fixierten Parameter müssen beim Aufruf maplist(p(A1 ,...,Am ), Xs1 ,...,Xsn ) – wie wir gesehen haben – ja an den ersten m Stellen des Prädikats p/(n + m) stehen. Prof. Dr. Dietmar Seipel 686 Deduktive Datenbanken Sommersemester 2012 Iteration über eine Liste bzw. einen Zahlenbereich: ?- forall( member(I, [a, b, c, d]), ( write(I), write(’ - ’) ) ). a - b - c - d Yes ?- for(I, 2, 5) do ( write(I), write(’ - ’) ). 2 - 3 - 4 - 5 Yes Prof. Dr. Dietmar Seipel 687 Deduktive Datenbanken Sommersemester 2012 Alternative Implementierung mittels Rekursion: write_numbers(N, M) :N =< M, !, write(N), write(’ - ’), K is N + 1, write_numbers(K, M). write_numbers(_, _). Das Statement N is N+1 wäre sinnlos, da man den Wert einer bereits belegten Variablen N nicht verändern kann. Deswegen wird im rekursiven Aufruf eine frische Variable K mit dem inkrementierten Wert N+1 belegt. Eleganter ist aber in jedem Fall die Implementierung mittels for-do. Prof. Dr. Dietmar Seipel 688 Deduktive Datenbanken Sommersemester 2012 Transformation von Listen (Filter) Der Aufruf foreach(X, Xs), foreach(Y, Ys) do p(X, Y) transformiert eine Liste Xs in eine gleichlange Ergebnisliste Ys: Xs X Prof. Dr. Dietmar Seipel Ys - Y 689 Deduktive Datenbanken Sommersemester 2012 Multiplikation eines Vektors mit einem Skalar Multiplikation eines Vektors, der durch eine Liste Xs gegeben ist, mit einem skalaren Faktor F; das Ergebnis ist wieder eine Liste Ys: vector_multiply(F, Xs, Ys) :foreach(X, Xs), foreach(Y, Ys) do Y is F * X. ?- vector_multiply(3, [2, 4], Ys). Ys = [6, 12] Prof. Dr. Dietmar Seipel 690 Deduktive Datenbanken Sommersemester 2012 Die Verwendung von maplist/3 setzt eine geeignete Argumentreihenfolge im verwendeten Prädikat voraus, bei der die konstanten Parameter zuerst kommen und die zu transformierenden Argumente nachfolgen. Um die Multiplikation eines Vektors mittels maplist/3 ausdrücken zu können, müßte man erst ein geeignetes Hilfsprädikat multiply/3 implementieren: vector_multiply(F, Xs, Ys) :maplist( multiply(F), Xs, Ys ). multiply(F, X, Y) :Y is F * X. Das Prädikat is/2 kann hier nicht direkt herangezogen werden, da es nur zweistellig ist und eine Eingabe in Produktform erwartet. Prof. Dr. Dietmar Seipel 691 Deduktive Datenbanken Sommersemester 2012 Der Aufruf foreach(X, Xs), foreach(Y, Ys), foreach(Z, Zs) do p(X, Y, Z) transformiert zwei gleichlange Listen Xs und Ys in eine genausolange Ergebnisliste Zs: Xs X Zs ~ > Z Y Ys Prof. Dr. Dietmar Seipel 692 Deduktive Datenbanken Sommersemester 2012 Addition von Vektoren Die Addition zweier gleichlanger Vektoren x = (x1 , . . . , xn ) ∈ IRn und y = (y1 , . . . , yn ) ∈ IRn ist gegeben durch z = (z1 , . . . , zn ) ∈ IRn , mit zi = xi + yi . Man kann die Addition mittels do/2 oder maplist/4 implementieren: vector_add(Xs, Ys, Zs) :foreach(X, Xs), foreach(Y, Ys), foreach(Z, Zs) do Z is X + Y. vector_add(Xs, Ys, Zs) :maplist( add, Xs, Ys, Zs ). ? ? 6 add( X, Y, Z ) ?- vector_add([1,2], [3,4], Zs). Zs = [4,6] Prof. Dr. Dietmar Seipel 693 Deduktive Datenbanken Sommersemester 2012 Skalarprodukt von Vektoren Das Skalarprodukt zweier gleichlanger Vektoren x = (x1 , . . . , xn ) ∈ IRn und Pn n y = (y1 , . . . , yn ) ∈ IR ist gegeben durch x · y = i=1 xi · yi . scalar_product(Xs, Ys, Z) :( foreach(X, Xs), foreach(Y, Ys), foreach(Z, Zs) do Z is X * Y ), sum(Zs, Z). ?- scalar_product([1,2], [3,4], Z). Z = 11 Prof. Dr. Dietmar Seipel 694 Deduktive Datenbanken Sommersemester 2012 Durch Verknüpfung von for und foreach innerhalb von do/2 kann man auch die Liste der Fakultäten eleganter berechnen, die wir vorher schon mittels findall/3 und between/3 berechnet hatten: ?- for(N, 1, 5), foreach(F, Fs) do factorial(N, F). Fs = [1, 2, 6, 24, 120] Dabei generiert for(N, 1, 5) die ganzen Zahlen zwischen 1 und N, und foreach(F, Fs) sammelt die Fakultäten F in einer Liste Fs auf. Die Fakultäten werden wieder mittels factorial(N, F) berechnet. Anders als bei der Berechnung mittels findall/3 ist hier kein Cut in factorial/2 erforderlich, da kein Backtracking angestoßen wird. Prof. Dr. Dietmar Seipel 695 Deduktive Datenbanken Sommersemester 2012 Transformation von Listen mit Variablen 2 Wir haben gesehen, daß man für Listen aus Grundtermen mit findall/3, maplist/3 und foreach-do dieselben Effekte erzielen kann. 2 Für Listen mit Variablen verhält sich findall/3 aber anders als die beiden anderen: bei den letzten beiden teilt die Resultatsliste die Bindungen mit der Ausgangsliste, bei dem ersten nicht. 2 Dies kann man mit dem P ROLOG–Prädikat ==/2 nachweisen. Der Aufruf X == Y testet, ob X und Y exakt gleich sind. Dies ist eine stärkere Eigenschaft als die Unifizierbarkeit. ?- X = Y. Yes ?- X == Y. No ?- X == X. Yes Prof. Dr. Dietmar Seipel 696 Deduktive Datenbanken Sommersemester 2012 ?- Xs = [X1,X2], maplist( =, Xs, Ys ), Xs == Ys. Yes ?- Xs = [X1,X2], ( foreach(X, Xs), foreach(Y, Ys) do Y = X ), Xs == Ys. Yes ?- Xs = [X1,X2], findall( Y, ( member(X, Xs), Y = X ), Ys ), Xs == Ys. No Prof. Dr. Dietmar Seipel 697 Deduktive Datenbanken Sommersemester 2012 Das Paarungsprädikat pair_lists/4 Zur Implementierung des Paarungsprädikats pair_lists/4 sollten wir deswegen – wie bereits gezeigt – maplist/3 oder foreach-do verwenden, aber nicht findall/3. Dann erhalten wir folgendes Verhalten: pair_lists(Mode, Xs, Ys, Pairs) :foreach(X, Xs), foreach(Y, Ys), foreach(Pair, Pairs) do pair_elements(Mode, X, Y, Pair). ?- pair_lists(:, [a, b, c], [X, X, Z], Pairs). Pairs = [a:X, b:X, c:Z] Auch wenn man pair_lists/4 mit Listenrekursion implementiert, dann erhält man das gezeigte – und erwünschte – Verhalten. Prof. Dr. Dietmar Seipel 698 Deduktive Datenbanken Sommersemester 2012 Wenn man die Transformation dagegen mit findall/3 implementieren würde, dann ginge der Bezug zu den ursprünglichen Variablen und der Bezug innerhalb der Paarliste verloren: pair_lists(Mode, Xs, Ys, Pairs) :findall( Pair, ( nth(N, Xs, X), nth(N, Ys, Y), pair_elements(Mode, X, Y, Pair) ), Pairs ). ?- pair_lists(:, [a, b, c], [X, X, Z], Pairs). Pairs = [a:_G701, b:_G695, c:_G689] In der Paarliste enthalten die beiden ersten Paare hier nicht mehr dieselbe Variable, obwohl die Positionen in der Ausgangsliste gleich sind. Außerdem könnte die Paarliste aufgrund von Backtracking über pair_elements/4 eine andere Länge haben als die Ausgangslisten. Prof. Dr. Dietmar Seipel 699 Deduktive Datenbanken Sommersemester 2012 If -> Then ; Else Man kann die Wurzelberechnung wie folgt mit Hilfe von komplexen Zahlen der Form A+B*i erweitern: square_root(X, Y) :( X >= 0 -> sqrt(X, Y) ; sqrt(abs(X), Z), Y = Z*i ). ?- square_root(4, Y). Y = 2 ?- square_root(-270400, Y). Y = 520*i Prof. Dr. Dietmar Seipel 700 Deduktive Datenbanken Sommersemester 2012 multiply_complex(X, Y, Z) :normalize_complex(X, A1+B1*i), normalize_complex(Y, A2+B2*i), A3 is A1*A2 - B1*B2, B3 is A1*B2 + A2*B1, simplify_complex(A3+B3*i, Z). normalize_complex(X, Y) :( X = A+B*i -> Y = A+B*i ; X = B*i -> Y = 0+B*i ; X = A -> Y = A+0*i ). ?- multiply_complex(520*i, 520*i, Z). Z = -270400 Prof. Dr. Dietmar Seipel 701 Deduktive Datenbanken Sommersemester 2012 Implementierung in P ROLOG: 2 A->B schlägt fehl, falls A fehlschlägt, und ruft ansonsten B auf. ?- listing(->). :- module_transparent (->)/2. A->B :A, !, B. Yes 2 A->B;C steht für (A->B);C und ist durch eine Regel für “ ; ” definiert. 2 Der Cut unterbindet in jedem Falle das Backtracking über A. Prof. Dr. Dietmar Seipel 702 Deduktive Datenbanken Sommersemester 2012 Würde man den Cut anstelle von -> in einem Goal schreiben, so würden auch vorherige Backtrackpunkte (unten wegen between/3) gelöscht: ?- findall( N, ( between(1, 3, N), ( N > 1, !, write(yes(N)) ; write(no(N)) ) ), Ns ). no(1)yes(2) Ns = [1, 2]. ?- findall( N, ( between(1, 3, N), ( N > 1 -> write(yes(N)) ; write(no(N)) ) ), Ns ). no(1)yes(2)yes(3) Ns = [1, 2, 3]. Prof. Dr. Dietmar Seipel 703 Deduktive Datenbanken Sommersemester 2012 Wenn man den If -> Then; Else –Teil dagegen in eine eigene Regel auslagert, dann verhalten sich beide Realisierungen gleich: treat_number(cut, N) :( N > 1, !, write(yes(N)) ; write(no(N)) ). treat_number(ite, N) :( N > 1 -> write(yes(N)) ; write(no(N)) ). ?- findall( N, ( between(1, 3, N), treat_number(cut, N) ), Ns ). no(1)yes(2)yes(3) Ns = [1, 2, 3]. Prof. Dr. Dietmar Seipel ?- findall( N, ( between(1, 3, N), treat_number(ite, N) ), Ns ). no(1)yes(2)yes(3) Ns = [1, 2, 3]. 704 Deduktive Datenbanken 4.3 Sommersemester 2012 Struktureigenschaften von Logikprogrammen Abhängigkeitsgraphen geben an, welche Prädikate welche anderen Prädikate in einem Logikprogrammen aufrufen. Sie werden im Software Engineering z.B. für folgende Zwecke benutzt: 2 Analyse von Programmen, 2 Analyse und Verständnis von Softwarepaketen, 2 Refaktorisierung, 2 Slicing. Prof. Dr. Dietmar Seipel 705 Deduktive Datenbanken Sommersemester 2012 Definition 4.1 (Abhängigkeitsgraph, Rule–Goal–Graph) Sei P ein definites Logikprogramm: 2 Der Abhängigkeitsgraph GdP = h ΠP , EPd i von P ist gegeben durch – ΠP ist die Menge aller Prädikatensymbole in P , – EPd = { h pA , pBi i | A ← B1 ∧ . . . ∧ Bm ∈ P, 1 ≤ i ≤ m }. rg rg 2 Der Rule–Goal–Graph Grg = h V , E P P P i von P ist gegeben durch – VPrg = ΠP ∪ P , – EPrg = { h pA , r i, h r, pBi i | r = A ← B1 ∧ . . . ∧ Bm ∈ P, 1 ≤ i ≤ m }. Der Abhängigkeitsgraph ergibt sich also aus dem Rule–Goal–Graphen durch transitive Verbindung der Kopf– und Rumpfprädikatensymbole unter Weglassung der dazwischen liegenden Regelknoten. Eingeschränkt auf die Prädikatensymbole haben beide Graphen dieselben Pfade. Prof. Dr. Dietmar Seipel 706 Deduktive Datenbanken Sommersemester 2012 Graphen zur Regel r = A ← B1 ∧ . . . ∧ Bm : GPd : pA GPrg : pA ? r pB1 W . . . pBm pB1 U . . . pBm pA bezeichnet das Prädikatensymbol eines Atoms A. Prof. Dr. Dietmar Seipel 707 Deduktive Datenbanken Sommersemester 2012 d Der Rule–Goal–Graph Grg P ist genauer als der Abhängigkeitsgraph GP . Die folgenden Logikprogramme P1 = { p ← q1 , p ← q2 }, P2 = { p ← q1 ∧ q2 }, haben denselben Abhängigkeitsgraphen GPd , aber unterschiedliche Rule–Goal–Graphen GPrg1 bzw. GPrg2 : GPd : GPrg1 : p r1 q1 Prof. Dr. Dietmar Seipel W q2 p U ? q1 GPrg2 : ? r r2 ? q2 p q1 U q2 708 Deduktive Datenbanken Sommersemester 2012 Beispiel (Abhängigkeitsgraph, Rule–Goal–Graph) Der Abhängigkeitsgraph und der Rule–Goal–Graph für P = { r, s } mit r = p(X0 , X3 ) ← a(X0 , X2 ) ∧ q(X1 , X2 , X3 ), s = q(X1 , X2 , X3 ) ← b(X1 , X2 ) ∧ c(X1 , X3 ), sehen wie folgt aus: GdP : Grg P : p p ? r a N q R q a ? s b Prof. Dr. Dietmar Seipel N c R c b 709 Deduktive Datenbanken Sommersemester 2012 Falls in einem Programm dasselbe Prädikatensymbol mit unterschiedlichen Stelligkeiten auftritt, so kann man dies in den Graphen unterscheiden: graph_search(X, Path) :graph_search(X, [X], Path). ... Grg P : graph_search/2 ? r ? graph_search/3 Prof. Dr. Dietmar Seipel 710 Deduktive Datenbanken Sommersemester 2012 Für P ROLOG–Regeln, deren Rümpfe “ , ” und “ ; ” enthalten können, muß man eigentlich extra Knoten einführen, um die Struktur adäquat abzubilden: tc(X, Y) :( arc(X, Y) ; arc(X, Z),tc(Z, Y) ). Grg P : tc/2 ?] r ? ; R, arc/2 Prof. Dr. Dietmar Seipel 711 Deduktive Datenbanken Sommersemester 2012 Die Infix–Notation des obigen Regelrumpfes ist äquivalent zur Präfix–Notation in der folgenden Regel. Würde man aber “ ; ” lediglich als binäres Prädikatensymbol auffassen, so ginge verloren, daß tc/2 sich selbst (Rekursion) und arc/2 aufruft: tc(X, Y) :’;’(arc(X, Y), ’,’(arc(X, Z),tc(Z, Y))). Grg P : tc/2 ? r ? ; /2 Prof. Dr. Dietmar Seipel 712 Deduktive Datenbanken Sommersemester 2012 Wenn wir dagegen die zwei üblichen definiten Regeln für die transitive Hülle verwenden, die zusammen zur obigen Regel äquivalent sind, dann können die üblichen Graphen die Struktur adäquat abilden: tc(X, Y) :- arc(X, Y). tc(X, Y) :- arc(X, Z), tc(Z, Y). GPrg : tc/2 r1 I R r2 R arc/2 Prof. Dr. Dietmar Seipel 713 Deduktive Datenbanken Sommersemester 2012 ?- Program = [ [tc(X, Y)]-[arc(X, Y)], [tc(X, Y)]-[arc(X, Z), tc(Z, Y)], [arc(a, b)], [arc(b, c)], [arc(c, d)] ], program_to_rule_goal_graph( GPrg : Program, Vs, Es, Fs). Vs = [ arc, fact_1, fact_2, fact_3, rule_1, rule_2, tc ] Es = [ arc-fact_1, arc-fact_2, arc-fact_3, tc-rule_1, tc-rule_2, rule_1-arc, rule_2-arc, rule_2-tc ] Fs = [ ] Prof. Dr. Dietmar Seipel tc/2 r1 I R r2 R arc/2 ?R f1 f2 f3 714 Deduktive Datenbanken Sommersemester 2012 Für normale Logikprogramme (mit Negation) wie P = { p ← a ∧ not b } werden die Kanten zu den Prädikatensymbolen der positiven bzw. negativen Rumpfatome in separaten Listen zurückgeliefert: ?- Program = [ [p]-[a]-[b] ], program_to_rule_goal_graph( Program, Vs, Es, Fs). Grg P : p ? r not Vs = [ a, b, p, rule_1 ] Es = [ p-rule_1, rule_1-a ] Fs = [ rule_1-b ] Prof. Dr. Dietmar Seipel R a b 715 Deduktive Datenbanken Sommersemester 2012 Abhängigkeitsgraph in DD BASE Prof. Dr. Dietmar Seipel 716 Deduktive Datenbanken Sommersemester 2012 Definition 4.2 (Rekursion) Sei P ein definites Logikprogramm. 2 Ein Prädikatensymbol p ∈ ΠP ist rekursiv, wenn p in einem Zykel von GdP liegt. Zwei Prädikatensymbole p, q ∈ ΠP sind wechselseitig rekursiv, wenn p und q zusammen in einem Zykel von GdP liegen. 2 Eine Regel r = A ← B1 ∧ . . . ∧ Bm ∈ P ist rekursiv, wenn mindestens ein Prädikatensymbol pBi wechselseitig rekursiv zu pA ist. r ist direkt–rekursiv, wenn mindestens ein Prädikatensymbol pBi gleich pA ist. 2 P ist rekursiv, wenn der Abhängigkeitsgraph GdP von P zyklisch ist. Ein Programm ist genau dann rekursiv, wenn es eine rekursive Regel enthält. Es gibt rekursive Programme ohne direkt–rekursive Regeln: in P = { p ← q, q ← p } sind z.B. p und q wechselseitig rekursiv. Prof. Dr. Dietmar Seipel GPrg : r1 p K r2 U q 717 Deduktive Datenbanken Sommersemester 2012 Beispiel (Rekursion) Für das rekursive DATALOG–Programm P = { r1 , r2 , f1 , f2 , f3 } mit r1 = tc(X , Z ) ← arc(X, Z), r2 = tc(X , Z ) ← arc(X, Y ) ∧ tc(Y, Z), f1 = arc(a, b), f2 = arc(b, c), f3 = arc(c, d ), erhalten wir die folgenden zyklischen Graphen: GPd : ... ......... tc ........ GPrg : tc I R r1 r2 ? arc R arc ? R f1 f2 f3 Prof. Dr. Dietmar Seipel 718 Deduktive Datenbanken Sommersemester 2012 % predicate_is_recursive(+Program, ?Predicate) <predicate_is_recursive(Program, Predicate) :program_to_rule_goal_graph(Program, Vs, Es, Fs), ord_union(Es, Fs, Edges), transitive_closure_edges(Edges, Tc_Edges), member(Predicate-Predicate, Tc_Edges). ?- Program = [ [tc(X, Y)]-[arc(X, Y)], [tc(X, Y)]-[arc(X, Z), tc(Z, Y)] ], predicate_is_recursive(Program, Predicate). Predicate = tc Prof. Dr. Dietmar Seipel 719 Deduktive Datenbanken Sommersemester 2012 Transitive Hülle Man kann die transitive Hülle eines gerichteten Graphen basierend auf der Bibliothek ugraphs.pl von S WI–P ROLOG berechen; in dieser werden Graphen als Adjazenzlisten dargestellt: ?- Graph_1 = [ a-[b], b-[c], c-[b,d] ], transitive_closure(Graph_1, Graph_2). Graph_2 = [a-[b, c, d], b-[c, d], c-[b, d]]. Dann ergibt sich transitive_closure_edges/2 daraus über Konversion von der Kantendarstellung in die Adjazenzlistendarstellung: transitive_closure_edges(Edges, Tc_Edges) :edges_to_ugraph(Edges, Graph), transitive_closure(Graph, Tc_Graph), ugraph_to_edges(Tc_Graph, Tc_Edges). Prof. Dr. Dietmar Seipel 720 Deduktive Datenbanken Sommersemester 2012 Transitive Hülle im D DK Wir können die transitive Hülle eines gerichteten Graphen aber auch basierend auf tp_iteration/2 berechnen, wenn wir aus der Kantendarstellung eine geeignete Faktendarstellung erzeugen: % transitive_closure_edges(+Edges, -Tc_Edges) <transitive_closure_edges(Edges, Tc_Edges) :( foreach(Edge, Edges), foreach(Fact, Facts) do Edge = X-Y, Fact = [arc(X, Y)] ), tc_program_generic(tc, arc, Tc_Rules), append(Facts, Tc_Rules, Tc_Program), tp_iteration(Tc_Program, Interpretation), findall( X-Y, member(tc(X, Y), Interpretation), Tc_Edges ). Dies ist insofern interessant als es zeigt, daß wir die Technologie der deduktiven Datenbanken auch innerhalb der eigenen Domäne anwenden können. Prof. Dr. Dietmar Seipel 721 Deduktive Datenbanken Sommersemester 2012 Zu vorgegebenen Pädikatensymbolen Tc und Arc wird ein rechts–rekursives, lineares DATALOG–Programm erzeugt: % tc_generic(+Tc, +Arc, -Program) <tc_program_generic(Tc, Arc, Program) :Tc_xy =.. [Tc, X, Y], Arc_xy =.. [Arc, X, Y], Arc_xz =.. [Arc, X, Z], Tc_zy =.. [Tc, Z, Y], Program = [ [Tc_xy]-[Arc_xy], [Tc_xy]-[Arc_xz, Tc_zy] ]. ?- tc_program_generic(tc, arc, Program). Program = [ [tc(X, Y)]-[arc(X, Y)], [tc(X, Y)]-[arc(X, Z), tc(Z, Y)] ] Prof. Dr. Dietmar Seipel 722 Deduktive Datenbanken Sommersemester 2012 Bei der D DK–Implementierung von transitive_closure_edges/2 generiert tp_iteration/2 iterativ die ordinalen Potenzen zur Faktendarstellung der Kanten des Graphen: ?- transitive_closure_edges([a-b, b-c], Tc_Edges). [ ] [arc(a, b), arc(b, c)] [arc(a, b), arc(b, c), tc(a, b), tc(b, c)] [arc(a, b), arc(b, c), tc(a, b), tc(a, c), tc(b, c)] Tc_Edges = [a-b, a-c, b-c] Der obige Graph ist azyklisch, da keine Kanten der Form V-V berechnet wurden. Prof. Dr. Dietmar Seipel 723 Deduktive Datenbanken Sommersemester 2012 Definition 4.3 (Linearität) Sei P ein definites Logikprogramm: 2 Eine definite Regel r = A ← B1 ∧ . . . ∧ Bm ∈ P ist linear, wenn in P höchstens ein Prädikatensymbol pBi wechselseitig rekursiv zu pA ist. 2 P ist linear, wenn alle Regeln r ∈ P linear sind. 2 P ist linear–rekursiv, wenn P linear und rekursiv ist. Ein linear–rekursives definites Logikprogramm P enthält mindestens eine rekursive Regel. Man nennt es lineares Single–Recursive–Rule–Program (S IRUP), falls es – neben nicht–rekursiven Regeln – genau eine rekursive Regel enthält. Wenn P nur eine rekursive Regel r = A ← B1 ∧ . . . ∧ Bm enthält, dann ist genau ein Prädikatensymbol pBi wechselseitig rekursiv zu pA , und zusätzlich ist pA = pBi . Offensichtlich ist r dann auch direkt–rekursiv. Prof. Dr. Dietmar Seipel 724 Deduktive Datenbanken Sommersemester 2012 Beispiel (Lineare Rekursion) 2 Die Regeln r1 und r2 sind linear. Man nennt sie links– (r1 ) bzw. rechts–linear (r2 ). r3 ist dagegen nicht linear. Man nennt r3 quadratisch, da das rekursive Prädikatensymbol tc in zwei Rumpfatomen auftritt. r1 = tc(X, Z) ← tc(X, Y ) ∧ arc(Y, Z), r2 = tc(X, Z) ← arc(X, Y ) ∧ tc(Y, Z), r3 = tc(X, Z) ← tc(X, Y ) ∧ tc(Y, Z). 2 Das Programm P = { r4 , r5 } ist linear–rekursiv. Das Programm P = { r5 , r6 } ist nicht linear wegen der Regel r6 : r4 = p(X, Y ) ← q(X, Y ), r5 = q(X, Y ) ← p(Y, X), r6 = p(X, Y ) ← p(X, Z) ∧ q(Z, Y ). Prof. Dr. Dietmar Seipel 725 Deduktive Datenbanken Sommersemester 2012 Stabilität von Regeln 2 Man kann bei der SLD–Resolution eine ausgefeiltere Selektionsfuntion s als sl verwenden, welche möglichst Atome auswählt, die schon teilweise gebunden sind. 2 Analog kann der TP –Operator die Reihenfolge der auszuwertenden Rumpfatome geeignet wählen. Entsprechend würde auch ein Optimierer bei der Auswertung von S QL–Anfragen in relationalen Datenbanksystemen vorgehen, um eine geeignete Join–Reihenfolge zu bestimmen. 2 Man kann die Auswertung von linear–rekursiven Programmen optimieren, wenn der rekursive Aufruf im Regelrumpf dasselbe Bindungsmuster hat wie der Aufruf des Kopfatoms. Prof. Dr. Dietmar Seipel 726 Deduktive Datenbanken Sommersemester 2012 Definition 4.4 (Stabilität) 2 Eine Folge h Bi0 , Bi1 , . . . , Bik i von verschiedenen Atomen aus einer linearen, direkt–rekursiven Regel r = A ← B1 ∧ . . . ∧ Bm ist eine Kette in r, wenn gilt: – Bi0 = A und pBik = pA , und – Bij und Bij+1 haben (mindestens) eine Variable Xj+1 (Kettvariable) gemeinsam (0 ≤ j ≤ k − 1). 2 Die Kette heißt stabil, wenn die initiale Variable X1 im Kopf auf derselben Argumentposition steht wie die finale Variable Xk im Rumpf. 2 r heißt stabil, wenn alle Ketten in r stabil sind. Die Stabilität ist eine sehr häufige Eigenschaft von rekursiven Regeln. Prof. Dr. Dietmar Seipel 727 Deduktive Datenbanken Sommersemester 2012 Beispiel (Stabilität) 2 Die folgende stabile Regel hat zwei stabile Ketten: p(X1 , Y1 ) ← a(X1 , X2 ) ∧ p(X3 , Y1 ) ∧ b(X2 , X3 ) – Bi0 = p(X1 , Y1 ), Bi1 = a(X1 , X2 ), Bi2 = b(X2 , X3 ), Bi3 = p(X3 , Y1 ), mit den Kettvariablen X1 , X2 , X3 , und – Bi0 = p(X1 , Y1 ), Bi1 = p(X3 , Y1 ), mit der Kettvariablen Y1 . 2 Die folgende stabile Regel hat zwei stabile Ketten: p(X1 , Y1 ) ← up(X1 , X2 ) ∧ p(X2 , Y2 ) ∧ down(Y2 , Y1 ). – Bi0 = p(X1 , Y1 ), Bi1 = up(X1 , X2 ), Bi2 = p(X2 , Y2 ), mit den Kettvariablen X1 , X2 , und – Bi0 = p(X1 , Y1 ), Bi1 = down(Y1 , Y2 ), Bi2 = p(X2 , Y2 ), mit den Kettvariablen Y1 , Y2 . Prof. Dr. Dietmar Seipel 728 Deduktive Datenbanken Sommersemester 2012 2 Die folgende stabile Regel hat ebenfalls zwei stabile Ketten: sg(X1 , Y1 ) ← par(X1 , X2 ) ∧ sg(X2 , Y2 ) ∧ par(Y1 , Y2 ). Sie entsteht aus der vorherigen, wenn man – up(X1 , X2 ) durch par(X1 , X2 ) und – down(Y2 , Y1 ) durch par(Y1 , Y2 ) ersetzt. 2 Die folgende instabile Regel hat eine stabile und zwei instabile Ketten: p(X1 , Y1 , Z1 ) ← a(X1 , X2 ) ∧ p(Y1 , X2 , Z1 ), – stabil: Bi0 = p(X1 , Y1 , Z1 ), Bi1 = p(Y1 , X2 , Z1 ), mit der Kettvariablen Z1 , – instabil: Bi0 = p(X1 , Y1 , Z1 ), Bi1 = a(X1 , X2 ), Bi2 = p(Y1 , X2 , Z1 ), mit den Kettvariablen X1 , X2 , und – Bi0 = p(X1 , Y1 , Z1 ), Bi1 = p(Y1 , X2 , Z1 ), mit der Kettvariablen Y1 . Sobald eine Kette nicht stabil ist, ist die Regel nicht stabil. Prof. Dr. Dietmar Seipel 729 Deduktive Datenbanken Sommersemester 2012 2 Die folgende instabile Regel hat zwei instabile Ketten: p(X1 , Y1 ) ← up(X1 , X2 ) ∧ p(Y2 , X2 ) ∧ down(Y2 , Y1 ). – Bi0 = p(X1 , Y1 ), Bi1 = up(X1 , X2 ), Bi2 = p(Y2 , X2 ), mit den Kettvariablen X1 , X2 , und – Bi0 = p(X1 , Y1 ), Bi1 = down(Y1 , Y2 ), Bi2 = p(Y2 , X2 ), mit den Kettvariablen Y1 , Y2 . 2 Die folgende instabile Regel hat ebenfalls zwei instabile Ketten: sg(X1 , Y1 ) ← par(X1 , X2 ) ∧ sg(Y2 , X2 ) ∧ par(Y1 , Y2 ). Sie entsteht aus der vorherigen, wenn man – up(X1 , X2 ) durch par(X1 , X2 ) und – down(Y2 , Y1 ) durch par(Y1 , Y2 ) ersetzt. Prof. Dr. Dietmar Seipel 730 Deduktive Datenbanken Sommersemester 2012 Eigentlich muß man Tupel von Kettvariablen betrachten: 2 Die folgende stabile Regel hat zwei stabile Ketten: p(X1 , Y1 , U , V ) ← a(X1 , Y1 , X2 , Y2 ) ∧ p(X2 , Y2 , U, V ) – Bi0 = p(X1 , Y1 , U, V ), Bi1 = a(X1 , Y1 , X2 , Y2 ), Bi2 = p(X2 , Y2 , U, V ), mit den Tupeln von Kettvariablen (X1 , Y1 ), (X2 , Y2 ). Falls man nur die einzelnen Kettvariablen X1 , Y2 betrachten würde, so würde die Kette als instabil erscheinen. – Bi0 = p(X1 , Y1 , U, V ), Bi1 = p(X2 , Y2 , U, V ), mit dem Tupel von Kettvariablen (U, V ). Prof. Dr. Dietmar Seipel 731 Deduktive Datenbanken Sommersemester 2012 Verhalten bei SLD–Resolution Die SLD–Resolution mit der Selektionsfunktion sl ruft bei der stabilen Same Generation–Regel sg/2 im Kopf mit demselben Bindungsmuster ( sg(+,-) ) wie im Rumpf auf: ← sg(a, Y ) sg(X1 , Y1 ) ← par(X1 , X2 ) ∧ sg(X2 , Y2 ) ∧ par(Y1 , Y2 ) ?) ← par(a, X2 ) ∧ sg(X2 , Y2 ) ∧ par(Y, Y2 ) par (a, b) ?) ← sg(b, Y2 ) ∧ par(Y, Y2 ) Dies gilt analog auch wenn man das Bindungsmuster sg(-,+) mit der Selektionsfunktion sr evaluiert. Prof. Dr. Dietmar Seipel 732 Deduktive Datenbanken Sommersemester 2012 Die SLD–Resolution mit der Selektionsfunktion sl ruft bei der instabilen Same Generation–Regel sg/2 im Kopf mit einem anderen Bindungsmuster ( sg(+,-) ) als im Rumpf ( sg(-,+) ) auf: ← sg(a, Y ) sg(X1 , Y1 ) ← par(X1 , X2 ) ∧ sg(Y2 , X2 ) ∧ par(Y1 , Y2 ) ?) ← par(a, X2 ) ∧ sg(Y2 , X2 ) ∧ par(Y, Y2 ) par (a, b) ?) ← sg(Y2 , b) ∧ par(Y, Y2 ) Dies gilt analog auch wenn man das Bindungsmuster sg(-,+) mit der Selektionsfunktion sr evaluiert. Prof. Dr. Dietmar Seipel 733 Deduktive Datenbanken Sommersemester 2012 Wenn man das obige Beispiel weiter resolviert, dann landet zuerst die Bindung b in einem mittleren par –Atom und dann die Bindung c wieder an der ersten Stelle eines sg–Atoms: ← sg(Y2 , b) ∧ par(Y, Y2 ) sg(X1′ , Y1′ ) ← par(X1′ , X2′ ) ∧ sg(Y2′ , X2′ ) ∧ par(Y1′ , Y2′ ) ?) ← par(Y2 , X2′ ) ∧ sg(Y2′ , X2′ ) ∧ par(b, Y2′ ) ∧ par(Y, Y2 ) par (b, c) ?) ← par(Y2 , X2′ ) ∧ sg(c, X2′ ) ∧ par(Y, Y2 ) Die bis hierher resolvierten par –Atome par(a, b) und par(b, c) bilden genauso eine Kette wie die beiden noch verbliebenen par –Atome par(Y2 , X2′ ) und par(Y, Y2 ). Prof. Dr. Dietmar Seipel 734 Deduktive Datenbanken 4.4 Sommersemester 2012 Äquivalenz und Transformation von Logikprogrammen Wir betrachten vier unterschiedlich starke Formen der Äquivalenz. Sei Q eine Anfrage und Π eine Menge von Prädikatensymbolen. Zwei Logikprogramme P und P ′ heißen (≡) äquivalent, falls für alle Herbrandinterpretationen I gilt MP ∪I = MP ′ ∪I . (≡Π ) äquivalent bezüglich Π, falls für alle Herbrandinterpretationen I über den Prädikatensymbolen aus Π gilt MP ∪I = MP ′ ∪I . (≡Q ) äquivalent bezüglich Q, falls für alle Herbrandinterpretationen I gilt MP ∪I,Q = MP ′ ∪I,Q . ≡ R ≡Q ≡Π R ≡Π,Q (≡Π,Q ) äquivalent bezüglich Π und Q, falls für alle Herbrandinterpretationen I über den Prädikatensymbolen aus Π gilt MP ∪I,Q = MP ′ ∪I,Q . Prof. Dr. Dietmar Seipel 735 Deduktive Datenbanken Sommersemester 2012 Offensichtlich ist die erste Form die stärkste, die letzte Form ist die schwächste, und die beiden mittleren Formen sind unvergleichbar. Die Einschränkungen auf Π und Q dienen dazu, temporäre Hilfsprädikate für die Eingabe (Π) bzw. die Ausgabe (Q) auszublenden. Das Up–Down–Schema: Pup,down 2 Wir verwenden im folgenden wiederholt das zwei–dimensionale, stabile up–down–Schema Pup,down = { rup,down , eup,down } mit rup,down = p(X , Y ) ← up(X, X1 ) ∧ p(X1 , Y1 ) ∧ down(Y1 , Y ) eup,down = p(X , Y ) ← f lat(X, Y ) 2 In Kapitel 5 werden wir sehen, wie man Pup,down effizient auswerten kann. Wir werden sogar zeigen, daß sich alle linearen S IRUPs (z.B. anc, tc, sg) auf Verallgemeinerungen des up–down–Schemas normalisieren lassen. Prof. Dr. Dietmar Seipel 736 Deduktive Datenbanken Sommersemester 2012 2 Zur Faktenmenge up(a1 , a2 ), up(a2 , a3 ), flat(a3 , b3 ), down(b3 , b2 ), down(b2 , b1 ), leitet Pup,down der Reihe nach folgende Fakten ab: p(a3 , b3 ), p(a2 , b2 ), p(a1 , b1 ). a3 up a2 up a1 flat - b3 U down b2 U down b1 Ein Fakt p(a, b) kann abgeleitet werden, wenn es eine Brücke gibt, die von a über k Schritte nach oben (up) geht, dann über flat nach rechts, und dann ebenfalls über k Schritte nach unten (down) zu b. Prof. Dr. Dietmar Seipel 737 Deduktive Datenbanken Sommersemester 2012 Das Fakt p(a1 , b1 ) wird z.B. mit folgendem Beweisbaum abgeleitet: Man erkennt, daß die verwendeten up–Atome und die verwendeten down–Atome zwei separate Ketten up(a1 , a2 ), up(a2 , a3 ) und down(b3 , b2 ), down(b2 , b1 ) bilden. Prof. Dr. Dietmar Seipel 738 Deduktive Datenbanken Sommersemester 2012 l r q Ancestor: Panc , Panc , Panc l l = { ranc , eanc } mit 2 Das links–lineare Logikprogramm Panc l ranc = anc(X , Y ) ← anc(X, Z) ∧ par(Z, Y ) eanc = anc(X , Y ) ← par(X, Y ) ist bezüglich Π = { par } äquivalent zum rechts–linearen Logikprogramm r r Panc = { ranc , eanc } mit der rechts–rekursiven Regel r ranc = anc(X , Y ) ← par(X, Z) ∧ anc(Z, Y ) l r ∪ I und Panc ∪I Für alle Herbrandinterpretationen I über Π haben Panc sogar dieselben ordinalen Potenzen. Sie sind auch beide bezüglich Π = { par } äquivalent zum quadratischen q q Logikprogramm Panc = { ranc , eanc } mit der rekursiven Regel q ranc = anc(X , Y ) ← anc(X, Z) ∧ anc(Z, Y ) Prof. Dr. Dietmar Seipel 739 Deduktive Datenbanken Sommersemester 2012 2 Betrachten wir z.B. die Faktenmenge I = { par (a1 , a2 ), par (a2 , a3 ), par (a3 , a4 ), par (a4 , a5 ) }. a1 - a2 - a3 - a4 - a5 l r Dann erhalten wir sowohl für P = Panc ∪ I als auch für P = Panc ∪ I die folgenden ordinalen Potenzen und MP = TP ↑ 5 : TP ↑ 0 = ∅, TP ↑ 1 = I, TP ↑ 2 = I ∪ { anc(a1 , a2 ), anc(a2 , a3 ), anc(a3 , a4 ), anc(a4 , a5 ) }, TP ↑ 3 = TP ↑ 2 ∪ { anc(a1 , a3 ), anc(a2 , a4 ), anc(a3 , a5 ) }, TP ↑ 4 = TP ↑ 3 ∪ { anc(a1 , a4 ), anc(a2 , a5 ) }, TP ↑ n = TP ↑ 4 ∪ { anc(a1 , a5 ) }, für n ≥ 5. Die Fakten anc(ai , ai+k ) zur Pfadlänge k werden also in Iteration k + 1 abgeleitet. Wenn k die maximale Pfadlänge ist, dann sind ab n = k + 1 alle ordinalen Potenzen gleich. Prof. Dr. Dietmar Seipel 740 Deduktive Datenbanken Sommersemester 2012 Das Fakt anc(a1 , a5 ) wird z.B. mit folgendem Beweisbaum abgeleitet: Der Beweisbaum benutzt an der Wurzel die Regelinstanz anc(a1 , a5 ) ← anc(a1 , a4 ) ∧ par (a4 , a5 ). Prof. Dr. Dietmar Seipel 741 Deduktive Datenbanken Sommersemester 2012 q Auch für P = Panc ∪ I erhalten wir dasselbe minimale Herbrandmodell MP = TP ↑ 4, aber schneller und über andere ordinale Potenzen: TP ↑ 0 = ∅, TP ↑ 1 = I, TP ↑ 2 = I ∪ { anc(a1 , a2 ), anc(a2 , a3 ), anc(a3 , a4 ), anc(a4 , a5 ) }, TP ↑ 3 = TP ↑ 2 ∪ { anc(a1 , a3 ), anc(a2 , a4 ), anc(a3 , a5 ) }, TP ↑ n = TP ↑ 3 ∪ { anc(a1 , a4 ), anc(a2 , a5 ), anc(a1 , a5 ) }, für n ≥ 4. Nach n Schritten sind die Pfade der Länge k = 2n−2 durchlaufen. Die Instanz anc(a1 , a5 ) ← anc(a1 , a3 ) ∧ anc(a3 , a5 ) | {z } | {z } | {z } f1,5 f1,3 f3,5 der Regel r leitet z.B. für n = 4 aus den zwei Fakten f1,3 , f3,5 ∈ TP ↑ 3 zur Pfadlänge 2n−3 = 2 ein Fakt f1,5 ∈ TP ↑ 4 zur Pfadlänge 2n−2 = 4 ab. Wenn k die maximale Pfadlänge ist, dann sind insgesamt nur n = ⌈log2 k⌉ + 2 Iterationen erforderlich. Prof. Dr. Dietmar Seipel 742 Deduktive Datenbanken Sommersemester 2012 q l Für das quadratische Logikprogramm Panc gibt es – anders als für Panc r und Panc – sogar mehrere Beweisbäume zum Fakt anc(a1 , a5 ): Dieser Beweisbaum benutzt an der Wurzel die Regelinstanz anc(a1 , a5 ) ← anc(a1 , a3 ) ∧ anc(a3 , a5 ). Prof. Dr. Dietmar Seipel 743 Deduktive Datenbanken Sommersemester 2012 Der folgende Beweisbaum benutzt an der Wurzel die Regelinstanz anc(a1 , a5 ) ← anc(a1 , a4 ) ∧ anc(a4 , a5 ). Schließlich gibt es auch einen Beweisbaum, der an der Wurzel die folgende Regelinstanz benutzt: anc(a1 , a5 ) ← anc(a1 , a2 ) ∧ anc(a2 , a5 ). Prof. Dr. Dietmar Seipel 744 Deduktive Datenbanken Sommersemester 2012 l r 2 Die linearen Logikprogramme Panc und Panc sind bezüglich Π = { anc, par } nicht äquivalent. Für I = { anc(a1 , a2 ), par (a2 , a3 ) } unterscheiden sich z.B. MPanc l ∪I = I ∪ { anc(a1 , a3 ) } und MP r ∪I = I. anc l r 2 Panc und Panc sind bereits bezüglich Π = { anc } nicht äquivalent zum q quadratischen Logikprogramm Panc . Für I = { anc(a1 , a2 ), anc(a2 , a3 ) } gilt z.B. MPanc l ∪I = MP r ∪I = I 6= I ∪ { anc(a1 , a3 ) } = MP q ∪I . anc anc Im allgemeinen gilt für eine Herbrandinterpretation I nur MPanc l ∪I ⊆ MP q ∪I und MP r ∪I ⊆ MP q ∪I . anc anc anc r l q ist im allgemeinen stärker als Panc und Panc . D.h., Panc Prof. Dr. Dietmar Seipel 745 Deduktive Datenbanken Sommersemester 2012 l l 2 Außerdem ist das links–lineare Logikprogramm Panc = { ranc , eanc } mit l ranc = anc(X , Y ) ← anc(X, Z) ∧ par(Z, Y ) eanc = anc(X , Y ) ← par(X, Y ) auch bezüglich der Anfrage Q = ← anc(X, Y ) und der Menge Π = { par } äquivalent zum Logikprogramm u,d Panc = Pup,down ∪ { e1anc , e2anc , e3anc , e4anc } mit den Regeln e1anc = anc(X , Y ) ← p(X, Y ) e2anc = up(X , X ) ← e3anc = down(X , Y ) ← par (X, Y ) e4anc = flat(X , Y ) ← par (X, Y ) Prof. Dr. Dietmar Seipel 746 Deduktive Datenbanken Sommersemester 2012 Same Generation: Psg 2 Das Logikprogramm Psg = { rsg , esg } mit rsg = sg(X , Y ) ← par(X, X1 ) ∧ sg(X1 , Y1 ) ∧ par(Y, Y1 ) esg = sg(X , Y ) ← par(X, Z) ∧ par(Y, Z) ist bezüglich der Anfrage Q = ← sg(X, Y ) und der Menge Π = { par } äquivalent zum Logikprogramm Psgu,d = Pup,down ∪ { e1sg , e2sg , e3sg , e4sg } mit den Regeln e1sg = sg(X , Y ) ← p(X, Y ) e2sg = up(X , Y ) ← par (X, Y ) e3sg = down(X , Y ) ← par (Y, X) e4sg = flat(X , Y ) ← par (X, Z) ∧ par (Y, Z) Prof. Dr. Dietmar Seipel 747 Deduktive Datenbanken Sommersemester 2012 Man kann also Psg auf der Basis von Pup,down auswerten, indem man die Eingabe mittels Ppre = { e2sg , e3sg , e4sg } für Pup,down aufbereitet und die Ausgabe von Pup,down mittels Ppost = { e1sg } in die gewünschte Ausgabe umsetzt. 6 Psg Ppost Postprocessing 6 Pup,down rekursive Auswertung 6 Ppre Preprocessing 6 Prof. Dr. Dietmar Seipel 748 Deduktive Datenbanken Sommersemester 2012 Methodenextraktion und Methodenexpansion 2 Das Logikprogramm Pclone = { r1 , r2 } mit r1 = p1 (X3 ) ← a(X1 ) ∧ b(X1 , X2 ) ∧ c(X2 , X3 ), r2 = p2 (X1 , X4 ) ← a(X1 ) ∧ b(X1 , X2 ) ∧ c(X2 , X3 ) ∧ d(X3 , X4 ), ist bezüglich aller Anfragen Q = ← p(t1 , . . . , tn ) mit p 6= clone und der Menge Π = { p1 , p2 , a, b, c, d } von Prädikatensymbolen äquivalent zum ex = { r1′ , r2′ , r3 } mit den Regeln Logikprogramm Pclone r1′ = p1 (X3 ) ← clone(X1 , X3 ), r2′ = p2 (X1 , X4 ) ← clone(X1 , X3 ) ∧ d(X3 , X4 ), r3 = clone(X1 , X3 ) ← a(X1 ) ∧ b(X1 , X2 ) ∧ c(X2 , X3 ). Der gemeinsame Teil der Rümpfe der Regeln r1 und r2 könnte z.B. mit einem Klonerkennungsverfahren gefunden und in Form der Regel r3 extrahiert worden sein. Prof. Dr. Dietmar Seipel 749 Deduktive Datenbanken Sommersemester 2012 Die Methodenextraktion soll den Programm–Code lesbarer machen. Bei Programm–Transformationen, die Hilfsprädikate einführen, darf man natürlich keine Anfragen an bzw. Basis–Fakten für die Hilfsprädikate zulassen: 2 Natürlich sind l u,d – Panc und Panc bzw. – Psg und Psgu,d u,d nicht äquivalent im stärksten Sinne, da Panc und Psgu,d Fakten zu den l Hilfsprädikaten p, up, down und flat ableiten, welche in Panc und Psg überhaupt nicht vorkommen. 2 Ebenso sind aufgrund des Hilfsprädikats clone die beiden obigen ex nicht äquivalent im stärksten Sinne. Logikprogramme Pclone und Pclone 2 Auch die beiden mittleren Formen von Äquivalenz liegen in allen drei Fällen nicht vor. Prof. Dr. Dietmar Seipel 750 Deduktive Datenbanken Sommersemester 2012 Die Methodenexpansion ist invers zur Methodenextraktion. 2 Das Logikprogramm p(X ) ← q(X) ∧ b(X), q(X ) ← a(X), ist bezüglich der Anfrage Q = ← p(X) und Π = { a, b } äquivalent zu p(X ) ← a(X) ∧ b(X). 2 Im weiteren, allgemeinen Sinne sind die beiden natürlich nicht äquivalent, – denn das zweite Programm kann keine Anfragen an q/1 beantworten, – und es ist immun gegen Fakten für q/1 in der Eingabe. Die Methodenexpansion kann dazu dienen, nicht mehr benötigte Methoden zu entfernen, indem man die Methodenaufrufe durch die entsprechenden Statements ersetzt. Prof. Dr. Dietmar Seipel 751 Deduktive Datenbanken Sommersemester 2012 Methodenexpansion für rekursive Regeln Wir betrachten hierzu wieder das links–rekursive Ancestor–Beispiel l l Panc = { ranc , eanc } mit l ranc = anc(X , Y ) ← anc(X, Z) ∧ par (Z, Y ), eanc = anc(X , Y ) ← par (X, Y ), und die Faktenmenge I = { par (a1 , a2 ), par (a2 , a3 ), par (a3 , a4 ), par (a4 , a5 ) }. a1 - a2 - a3 - a4 - a5 l Wenn wir die Variante anc(X , Z ) ← anc(X, Z ′ ) ∧ par (Z ′ , Z) von r = ranc in r einsetzen, dann erhalten wir eine neue Regel r ′′ = anc(X , Y ) ← anc(X, Z ′ ) ∧ par (Z ′ , Z) ∧ par (Z, Y ), die wir die zweite Iterierte von r nennen, da ihre Anwendung einer zweifachen Anwendung von r entspricht. r ′′ leitet aus einem anc–Fakt zur Pfadlänge k ein anc–Fakt zur Pfadlänge k + 2 ab. Prof. Dr. Dietmar Seipel 752 Deduktive Datenbanken Sommersemester 2012 Das ebenfalls links–rekursive, definite Logikprogramm P ′′ = { r ′′ , eanc } kann nur die Fakten zu ungeraden Pfadlängen ableiten. Für P = P ′′ ∪ I erhalten wir: TP ↑ 0 = ∅, TP ↑ 1 = I, TP ↑ 2 = I ∪ { anc(a1 , a2 ), anc(a2 , a3 ), anc(a3 , a4 ), anc(a4 , a5 ) }, TP ↑ n = TP ↑ 2 ∪ { anc(a1 , a4 ), anc(a2 , a5 ) }, für n ≥ 3. Nach n Schritten sind die Pfade der ungeraden Längen k ≤ 2 · n − 3 durchlaufen. Die Instanz anc(a1 , a4 ) ← anc(a1 , a2 ) ∧ par (a2 , a3 ) ∧ par (a3 , a4 ) | {z } | {z } | {z } | {z } f1,4 f1,2 f2,3 f3,4 der Regel r leitet für n = 3 z.B. aus den drei Fakten f1,2 , f2,3 , f3,4 ∈ TP ↑ 2 zur Pfadlänge 1 ein Fakt f1,4 ∈ TP ↑ 3 zur Pfadlänge 2 · n − 3 = 3 ab. Wenn k die maximale ungerade Pfadlänge ist, dann sind ab n = ⌈(k + 3)/2⌉ alle ordinalen Potenzen gleich. Prof. Dr. Dietmar Seipel 753 Deduktive Datenbanken Sommersemester 2012 l P ′′ = { r ′′ , eanc } ist bezüglich Π = { par } also nicht äquivalent zu Panc . Oben wurde z.B. das Fakt anc(a1 , a5 ) zur geraden Pfadlänge 4 nicht abgeleitet. Um auch die Fakten zu den geraden Pfadlängen ableiten zu können, nehmen wir die Regel e′ = anc(X , Y ) ← par (X, Z) ∧ par (Z, Y ) hinzu. Das ebenfalls links–rekursive, definite Logikprogramm P ′ = { r ′′ , e′ , eanc } kann nun die Fakten zu allen Pfadlängen ableiten: r ′′ = anc(X , Y ) ← anc(X, Z ′ ) ∧ par (Z ′ , Z) ∧ par (Z, Y ), e′ = anc(X , Y ) ← par (X, Z) ∧ par (Z, Y ), eanc = anc(X , Y ) ← par (X, Y ). Die nicht–rekursiven Regeln eanc und e′ leiten offensichtlich anc–Fakten zu den Pfadlängen 1 und 2 ab. Die rekursive Regel r ′′ kann aus einem anc–Fakt zur Pfadlänge k und zwei par –Fakten ein anc–Fakt zur Pfadlänge k + 2 ableiten. l r P ′ ist ist bezüglich Π = { par } äquivalent zu Panc und Panc . Prof. Dr. Dietmar Seipel 754 Deduktive Datenbanken Sommersemester 2012 Das Fakt anc(a1 , a5 ) zur geraden Pfadlänge 4 kann jetzt mit folgendem Beweisbaum abgeleitet werden: Dieser Beweisbaum benutzt an der Wurzel die folgende Regelinstanz von r ′′ : anc(a1 , a5 ) ← anc(a1 , a3 ) ∧ par (a3 , a4 ) ∧ par (a4 , a5 ). Außerdem werden die Fakten f1 , . . . , f4 und die folgende Instanz von e′ benutzt: anc(a1 , a3 ) ← par (a1 , a2 ) ∧ par (a2 , a3 ). Prof. Dr. Dietmar Seipel 755 Deduktive Datenbanken Sommersemester 2012 Für P = P ′ ∪ I erhalten wir die folgenden ordinalen Potenzen: TP ↑ 0 = ∅, TP ↑ 1 = I, TP ↑ 2 = I ∪ { anc(a1 , a2 ), anc(a2 , a3 ), anc(a3 , a4 ), anc(a4 , a5 ), anc(a1 , a3 ), anc(a2 , a4 ), anc(a3 , a5 ) }, TP ↑ n = TP ↑ 2 ∪ { anc(a1 , a4 ), anc(a2 , a5 ), anc(a1 , a5 ) }, für n ≥ 3. In Iteration 2 werden die anc–Fakten zu den Pfadlängen 1 und 2 berechnet (z.B. anc(a1 , a2 ) und anc(a1 , a3 )), in Iteration 3 die anc–Fakten zu den Pfadlängen 3 und 4 (z.B. anc(a1 , a4 ) und anc(a1 , a5 )). In Iteration n werden die anc–Fakten zu den Pfadlängen k = 2 · n − 3 und k = 2 · n − 2 neu berechnet. Nach n Schritten sind alle Pfade der Längen k ≤ 2 · n − 2 durchlaufen. Wenn k die maximale Pfadlänge ist, dann sind ab n = ⌈(k + 2)/2⌉ also alle ordinalen Potenzen gleich. Prof. Dr. Dietmar Seipel 756 Deduktive Datenbanken Sommersemester 2012 Programm–Transformation basierend auf der Methodenexpansion – Iteration von Regeln Auch für das modifizierte up–down–Beispiel P = { r, e } mit r = p(X , Y ) ← up′ (X, X1 ) ∧ p(Y1 , X1 ) ∧ down ′ (Y1 , Y ) e = p(X , Y ) ← flat ′ (X, Y ) kann man die Variante p(Y1 , X1 ) ← up′ (Y1 , X1′ ) ∧ p(Y1′ , X1′ ) ∧ down ′ (Y1′ , X1 ) der Regel r in r einsetzen (Methodenexpansion) und erhält die Iterierte r ′′ = p(X , Y ) ← up′ (X, X1 ) ∧ down ′ (Y1′ , X1 ) ∧ p(Y1′ , X1′ )∧ up′ (Y1 , X1′ ) ∧ down ′ (Y1 , Y ). Die Anwendung von r ′′ entspricht einer zweifachen Anwendung von r. Im Gegensatz zu r ist r ′′ stabil. Prof. Dr. Dietmar Seipel 757 Deduktive Datenbanken Sommersemester 2012 Zur Faktenmenge up ′ (a1 , a2 ), down ′ (a3 , a2 ), flat ′ (a3 , b3 ), up ′ (b2 , b3 ), down ′ (b2 , b1 ), leitet P der Reihe nach folgende Fakten ab: p(a3 , b3 ), p(b2 , a2 ), p(a1 , b1 ). a3 down ′ a2 up ′ a1 flat ′ - b3 K up ′ b2 down ′ U b1 Ein Fakt p(a, b) kann von r′′ zusammen mit e abgeleitet werden, wenn es eine Brücke gibt, die von a aus 2 · k Schritte unter alternierender Verwendung von up ′ und vom Inversen von down ′ macht, dann über flat ′ nach rechts geht, und dann 2 · k Schritte unter alternierender Verwendung vom Inversen von up ′ und von down ′ zu b macht. Prof. Dr. Dietmar Seipel 758 Deduktive Datenbanken Sommersemester 2012 Das Fakt p(a1 , b1 ) wird von P mit folgendem Beweisbaum abgeleitet – wir verwenden im Bild up, down und flat anstelle von up ′ , down ′ und flat ′ : Man erkennt, daß die verwendeten up ′ –Atome und die verwendeten down ′ –Atome nun zwei gemischte Ketten up ′ (a1 , a2 ), down ′ (a3 , a2 ) und up ′ (b2 , b3 ), down ′ (b2 , b1 ) bilden. Prof. Dr. Dietmar Seipel 759 Deduktive Datenbanken Sommersemester 2012 Das Fakt p(a1 , b1 ) wird von P ′′ = { r ′′ , e } und der Faktenmenge up ′ (a1 , a2 ), down ′ (a3 , a2 ), flat ′ (a3 , b3 ), up ′ (b2 , b3 ), down ′ (b2 , b1 ), mit folgendem Beweisbaum abgeleitet: Der Beweisbaum für P ′′ ist flacher als der vorherige Beweisbaum für P , da die Anwendung der Regel r ′′ der zweifachen Anwendung von r entspricht. Prof. Dr. Dietmar Seipel 760 Deduktive Datenbanken Sommersemester 2012 2 Dann gilt für P ′′ = { r ′′ , e } und eine Herbrandinterpretation I: ∆TP ′′ ∪I ↑ n = ∆TP ∪I ↑ 2 · n − 1, für n ≥ 1, wobei ∆T ↑ n = T ↑ n \ T ↑ n − 1. 2 Die Auswertung der iterierten Regel r ′′ zusammen mit e würde also nur die ungeraden Potenzen von TP ∪I ↑ ω liefern. 2 Um auch die geraden Potenzen zu erhalten, nehmen wir die Regel e′ hinzu: e′ = p(X , Y ) ← up′ (X, X1 ) ∧ flat ′ (Y1 , X1 ) ∧ down ′ (Y1 , Y ). 2 Dann ist das Logikprogramm P ′ = { r ′′ , e′ , e } bezüglich der Anfrage Q = ← p(X, Y ) und Π = { up′ , flat ′ , down′ } äquivalent zu P . 2 Die Regel e′ entspricht der Anwendung von e gefolgt von r, also r ◦ e, und die Regel r ′′ entspricht der zweifachen Anwendung von r, also r 2 = r ◦ r; somit entspricht die Umformung von P zu P ′ der folgenden Umformung: ′′ n ′ 2·n n ∞ ◦ (r ◦ e ∪ e) = ∪∞ ∪∞ n=0 (r ) ◦ (e ∪ e). n=0 r ◦ e = ∪n=0 r Prof. Dr. Dietmar Seipel 761 Deduktive Datenbanken Sommersemester 2012 2 Man kann jetzt r ′′ noch mit zwei Hilfsregeln zu rup,down vereinfachen: e1 = up(X , Y1′ ) ← up′ (X, X1 ) ∧ down ′ (Y1′ , X1 ), e2 = down(X1′ , Y ) ← up′ (Y1 , X1′ ) ∧ down ′ (Y1 , Y ). 2 Zusammen mit den Regeln e3 = flat(X , Y ) ← up′ (X, X1 ) ∧ flat ′ (Y1 , X1 ) ∧ down ′ (Y1 , Y ) e4 = flat(X , Y ) ← flat ′ (X, Y ) kann man ein Logikprogramm P ′′ = Pup,down ∪ { e1 , e2 , e3 , e4 } bilden, das ebenfalls bezüglich der Anfrage Q und der Menge Π äquivalent zu P ist. 2 P ′′ kann auf der Basis von Pup,down effizient ausgewertet werden. Die Regeln e1 , e2 , e3 , e4 definieren geeignete Faktenmengen, für up, down und flat, auf die dann Pup,down angewendet werden kann. Prof. Dr. Dietmar Seipel 762 Deduktive Datenbanken Sommersemester 2012 Man erkennt, daß Pup,down und P strukturell sehr unterschiedlich sind: 2 Im stabilen Pup,down verbindet up die erste Argumentposition des p–Atoms des Kopfes und Rumpfes, und down die zweiten Argumentpositionen. 2 Im instabilen P verbindet up′ die erste Argumentposition des Kopfes mit der zweiten Argumentposition des Rumpfes, und down′ die zweite des Kopfes mit der ersten des Rumpfes. Pup,down : P: 1 .. .... .. ... . ... .. ... ... ... ... ... . ... ... ... ... ... .. .. . .. ... .. .... . .. up Prof. Dr. Dietmar Seipel 2 ... .. . .. ... . ... .. ... ... ... ... ... . 2 1 ... ... ... ... ... .. .. . .. ... .. .. . . ... down . .. .. . .. ... . ... .. ... ... ... ... ... . o U up′ 7 ... ... ... ... ... .. .. . .. ... .. .. . .. .. down′ 763 Deduktive Datenbanken Sommersemester 2012 Die obigen Graphen nennt man AS–Graphen. In ihnen unterscheiden sich Pup,down und P essentiell. Die Rule–Goal–Graphen der beiden Programme sind dagegen strukturell gleich. GPrgup,down : p/2 eup,down flat/2 Prof. Dr. Dietmar Seipel GPrg : p/2 I R rup,down up/2 R down/2 e flat /2 ′ I R r R ′ up /2 down ′ /2 764 Deduktive Datenbanken Sommersemester 2012 ′′ Vergleicht man r ′′ mit der Iterierten rup,down r ′′ = p(X , Y ) ← up′ (X, X1 ) ∧ down′ (Y1′ , X1 ) ∧ p(Y1′ , X1′ ) ∧ up′ (Y1 , X1′ ) ∧ down′ (Y1 , Y ), ′′ rup,down = p(X , Y ) ← up(X, X1 ) ∧ up(X1 , X1′ ) ∧ p(X1′ , Y1′ ) ∧ down(Y1′ , Y1 ) ∧ down(Y1 , Y ), so erkennt man: in Pup,down liefern die up– bzw. down–Atome unterschiedliche Ketten, während die up′ – und down′ –Atome in P verschränkt sind. Durch die Programm–Transformation P ′′ = Pup,down ∪ { e1 , e2 , e3 , e4 } kann man aber P auf Pup,down zurückführen. Da es effiziente Auswertungsmethoden für Pup,down gibt, ist das ein Vorteil. Prof. Dr. Dietmar Seipel 765 Deduktive Datenbanken Sommersemester 2012 Kettennormalisierung In Abschnitt 5.3 werden wir zeigen wie beliebige linear–rekursive Regeln auf der Basis der AS–Graphen normalisiert werden können. r = p(X1 , X2 , X3 , X4 , X5 , X6 ) ← p(U1 , U2 , U3 , X3 , X5 , U6 ) ∧ a(X1 , U1 ) ∧ b(X2 , U3 ) ∧ c(X4 , U2 ) ∧ d(X6 ). 1 1 .. ... .. . .. ... .. ... ... ... ... ... . 1 2 ... ... ... ... ... . 1 .... . 2 ... . .. ... . a Prof. Dr. Dietmar Seipel 2 k 1 2 3 U b 1 -4 1 2 1 2 c 1 2 5 6 1 2 ? d 766 Deduktive Datenbanken Sommersemester 2012 Die Normalform kann man sich vereinfacht wie folgt vorstellen: p(X1 , . . . , Xn ) ← p(U1 , . . . , Un ) ∧ a1 (X1 , U1 ) ∧ . . . ∧ an (Xn , Un ). 1 .. .. . .. ... ... ... ... ... ... 1 2 ... ... ... ... . 1 ..... 2 ..... .. .. a1 n .. .. . .. ... ... ... ... ... ... ··· 1 2 ... ... ... ... . 1 .... 2 .... .. .. an Wenn wir für n = 2 die Prädikatensymbole a1 = up und a2 = down−1 setzen, dann erhalten wir als Spezialfall eine Variante p(X1 , X2 ) ← p(U1 , U2 ) ∧ up(X1 , U1 ) ∧ down(U2 , X2 ) der rekursiven Regel rup,down des Up–Down–Schemas. Dabei ist das Inverse down−1 durch Vertauschung der beiden Argumentpositionen definiert. Prof. Dr. Dietmar Seipel 767 Deduktive Datenbanken Sommersemester 2012 Programm–Transformation durch Ausnutzen von Selektionsbedingungen l l Hierzu betrachten wir die Ancestor–Beispiele Panc = { ranc , eanc } r r (links–rekursiv) und Panc = { ranc , eanc } (rechts–rekursiv) mit l = anc(X , Y ) ← anc(X, Z) ∧ par (Z, Y ), ranc r ranc = anc(X , Y ) ← par(X, Z) ∧ anc(Z, Y ), eanc = anc(X , Y ) ← par (X, Y ), und die Anfrage Qa = ← anc(a, Y ). *d *a b -f c -h je jg Prof. Dr. Dietmar Seipel 768 Deduktive Datenbanken Sommersemester 2012 2 Die naive Bottom–Up–Auswertung berechnet zur Faktenmenge PAR = { h a, d i, h a, e i, h b, a i, h b, g i, h c, h i, h d, f i } zuerst die Relation A NC = PAR ∪ { h a, f i, h b, d i, h b, e i, h b, f i }. und selektiert erst dann daraus die Resultatrelation σA NC.1=a (A NC ) = { h a, d i, h a, e i, h a, f i }. 2 Eigentlich müssten die von b und c ausgehenden Kanten nicht bei der Berechnung der Vorfahren von a berücksichtigt werden. 2 Im folgenden werden wir sehen, wie man das durch geeignete Programm–Transformationen erreichen kann. Prof. Dr. Dietmar Seipel 769 Deduktive Datenbanken Sommersemester 2012 Einsetzen der Selektionsbedingung 2 Eine effizientere Version der Ancestor–Regeln, zugeschnitten auf die Anfrage, erhält man durch Anwendung der Substitution θ = { X 7→ a } : l ranc,a = anc(a, Y ) ← anc(a, Z) ∧ par(Z, Y ) eanc,a = anc(a, Y ) ← par(a, Y ) Sie berechnet anstelle von A NC nur die sehr viel kleinere Relation A NC a = { h a, d i, h a, e i, h a, f i } welche ausschließlich aus Antworttupeln besteht. Diese Optimierung kann bei großen Faktenbasen entscheident sein. l l l l Panc = { ranc , eanc } und Panc,a = { ranc,a , eanc,a } sind äquivalent bezüglich der Anfrage Qa = ← anc(a, Y ), aber sie sind natürlich nicht äquivalent bezüglich der Anfrage Qb = ← anc(b, Y ) mit a 6= b. Prof. Dr. Dietmar Seipel 770 Deduktive Datenbanken Sommersemester 2012 l r 2 Panc (links–rekursiv) und Panc (rechts–rekursiv) sind bezüglich Π = { par } äquivalent (bezüglich beliebiger Anfragen). 2 Das naive Einsetzen der Selektionsbedingung funktioniert nicht immer. r r r Panc und Panc,a = { ranc,a , eanc,a } sind nicht äquivalent bezüglich der Anfrage Qa = ← anc(a, Y ) : r ranc,a = anc(a, Y ) ← par(a, Z) ∧ anc(Z, Y ) eanc,a = anc(a, Y ) ← par(a, Y ) denn für I = { par(a, d), par(d, f ) } gilt r ∪I,Q MPanc a = { anc(a, d), anc(a, f ) }, r MPanc,a ∪I,Qa = { anc(a, d) }. Um anc(a, f ) abzuleiten, müßte man vorher anc(d, f ) ableiten, was aber r natürlich nicht möglich ist. mit den Regeln aus Panc,a Prof. Dr. Dietmar Seipel 771 Deduktive Datenbanken Sommersemester 2012 Propagieren der Selektionsbedingung r Man kann also die Konstante a nicht in die Regeln von Panc hinein propagieren; man kann sie aber mittels Hilfsregeln propagieren. r 2 Aus einer Bindung für “X” im Regelkopf von ranc kann man mit Hilfe der folgenden DATALOG–Regel eine Bindung für “Z” im Regelrumpf berechnen: ancmagic (Z ) ← ancmagic (X) ∧ par(X, Z). 2 Die Verankerung von ancmagic erfolgt mittels des Fakts ancmagic (a). 2 Diese beiden Regeln leiten alle Konstanten ab, die bei der Top–Down–Auswertung (mittels SLD–Resolution) der Anfrage r Qa = ← anc(a, Y ) an Panc in anc–Atomen an der ersten Argumentposition auftreten. Prof. Dr. Dietmar Seipel 772 Deduktive Datenbanken Sommersemester 2012 2 Beispiel: G0 = ← anc(a, Y ), G1 = ← par(a, Z) ∧ anc(Z, Y ), G2 = ← anc(d, Y ). r und dann mit dem Fakt par(a, d) Hier wurde zuerst mit der Regel ranc resolviert. r 2 Um ein Fakt anc(a, Y ) mit dem TP –Operator für P = Panc abzuleiten, benötigt man eine Grundinstanz ra θ der Regel ra = anc(a, Y ) ← par(a, Z) ∧ anc(Z, Y ). Bevor diese Regel feuern kann, muß wiederum das Fakt anc(Z, Y )θ für den par–Nachfolger Zθ von a mit dem TP –Operator abgeleitet worden sein. Prof. Dr. Dietmar Seipel 773 Deduktive Datenbanken Sommersemester 2012 2 Per Induktion kann man zeigen, daß alle Fakten anc(z, y) zu den transitiven par–Nachfolgern z relevant für die Beantwortung unserer Anfrage Qa = ← anc(a, Y ) sind. 2 Die transitiven par–Nachfolger im Erreichbarkeitskegel von a werden mittels der folgenden magischen Regeln berechnet: a-x-z ancmagic (Z ) ← ancmagic (X) ∧ par(X, Z), ancmagic (a). r 2 Mit dem Filter ancmagic kann die Anwendbarkeit von ranc und eanc bei der r Bottom–Up–Auswertung (mit dem TP –Operator für P = Panc ) geeignet eingeschränkt werden: anc(X , Y ) ← ancmagic (X) ∧ par(X, Z) ∧ anc(Z, Y ), anc(X , Y ) ← ancmagic (X) ∧ par(X, Y ). Diese Regeln nennen wir modifizierte Regeln. Prof. Dr. Dietmar Seipel 774 Deduktive Datenbanken Sommersemester 2012 Für den Stammbaum *d *a b -f c -h je jg wird dann abgeleitet: ancmagic (a), ancmagic (d), ancmagic (e), ancmagic (f ). Deshalb feuern nur noch folgende Grundinstanzen der modifizierten Regeln: anc(a, f ) ← ancmagic (a) ∧ par(a, d) ∧ anc(d, f ), anc(a, d ) ← ancmagic (a) ∧ par(a, d), anc(a, e) ← ancmagic (a) ∧ par(a, e), anc(d , f ) ← ancmagic (d) ∧ par(d, f ). Prof. Dr. Dietmar Seipel 775 Deduktive Datenbanken Sommersemester 2012 r Sei weiter P = Panc . Abgesehen von den magischen Fakten ancmagic (a), . . . , ancmagic (f ) und den Basisfakten par(a, d), par(a, e), par(b, a), par(b, g), par(c, h), par(d, f ), liegt dann die Menge I der abgeleiteten Fakten zwischen MP und MP,Qa = { anc(a, d), anc(a, e), anc(a, f ) } : 2 I = MP,Qa ∪ { anc(d, f ) }. 2 Das Fakt anc(d, f ) wird nur abgeleitet, da es zur Ableitung von anc(a, f ) benötigt wird. 2 Es werden also nur noch 4 der 10 anc–Fakten aus der naiven Bottom–Up–Auswertung abgeleitet. In diesem – relativ einfachen – Beispiel könnte man die Anfrage sogar alleine aufgrund der abgeleiteten magischen Fakten beantworten. Prof. Dr. Dietmar Seipel 776 Deduktive Datenbanken Sommersemester 2012 Für das modifizierte up–down–Beispiel P = { r, e } und die Anfrage Q = ← p(a, Y ) ist die Situation komplizierter. Hier erzeugt der Magic Sets–Algorithmus folgendes augmentierte Programm Magic(P, Q): h b,f i p h b,f i (X , Y ) ← pmagic (X) ∧ up′ (X, X1 ) ∧ ph f,b i (Y1 , X1 ) ∧ down′ (Y1 , Y ) h f,b i p h f ,b i (X , Y ) ← pmagic (Y ) ∧ up′ (X, X1 ) ∧ ph b,f i (Y1 , X1 ) ∧ down′ (Y1 , Y ) h b,f i p h b,f i (X , Y ) ← pmagic (X) ∧ f lat′ (X, Y ) h f,b i p h f ,b i (X , Y ) ← pmagic (Y ) ∧ f lat′ (X, Y ) Für r und e werden jeweils zwei modifizierte Regeln mit unterschiedlichen Augmenten, h b, f i bzw. h b, f i, erzeugt. Die Kopfprädikatensymbole ph b,f i und ph f,b i der modifizierten Regeln für r sind wechselseitig rekursiv. Prof. Dr. Dietmar Seipel 777 Deduktive Datenbanken Sommersemester 2012 Außerdem gibt es drei magische Regeln zur Berechnung der magischen Atome: h f ,b i h b,f i h b,f i h f,b i pmagic (X1 ) ← pmagic (X) ∧ up′ (X, X1 ) pmagic (Y1 ) ← pmagic (Y ) ∧ down′ (Y1 , Y ) h b,f i pmagic (a). Die beiden ersten magischen Regeln leiten sich aus r ab, die dritte aus der Anfrage. Man braucht hier zwei Augmente, da sich bei der SLD–Resolution abwechselnd Bindungen für die beiden Argumente der p–Atome ergeben: 2 Aus einer Bindung für die erste Variable X des Kopfatoms – vgl. h b,f i pmagic (X) – ergibt sich durch den Aufruf von up′ (X, X1 ) eine Bindung für h f,b i die zweite Variable X1 des p–Atoms im Rumpf – vgl. pmagic (X1 ). 2 Analog ergibt sich aus einer Bindung für die zweite Variable Y des h f,b i Kopfatoms – vgl. pmagic (Y ) – durch den Aufruf von down′ (Y1 , Y ) eine h b,f i Bindung für die erste Variable Y1 des p–Atoms im Rumpf – vgl. pmagic (Y1 ). Prof. Dr. Dietmar Seipel 778