voriges Kapitel | Startseite | Inhalt | nächstes Kapitel

© 2001 François Bry
Dieses Lehrmaterial wird ausschließlich zur privaten Verwendung angeboten. Eine nichtprivate Nutzung (z.B. im Unterricht oder eine Veröffentlichung von Kopien oder Übersetzungen) dieses Lehrmaterials bedarf der Erlaubnis des Autors.


PROLOG-Hilfsprädikate und -programme


  1. Metainterpretation
  2. Einfache Metainterpretierer
  3. All-Antwort- und Systemprädikate berücksichtigen
  4. Metainterpretierer zur Darstellung von Beweisbäumen für "reines PROLOG"
  5. Behandlung von cut

Metainterpretation


In PROLOG sind Fakten und Regeln gewöhnliche Datenstrukturen. Im Ausdruck
> p(a, f(b))
kann p sowohl als Relations- als auch als Funktionssymbol angesehen werden. Die Interpretation von p als Relations- oder Funktionssymbol hängt lediglich davon ab, wo der Ausdruck p(a, f(b)) sich im Programm befindet.
Ein Metaprogramm ist ein Programm, das andere Programme, Objektprogramme genannt, als Eingabe erhält. Ein Metainterpretierer ist ein Metaprogramm, das Objektprogramme auswertet.

2. Einfache Metainterpretierer

Bemerkung: In vielen PROLOG-Systemen muß, um das Systemprädikat clause auf Klauseln, d.h. Fakten und Regeln, anwenden zu können, das durch diese Klauseln definierte Relationssymbol als dynamisch deklariert worden sein.
Bemerkung: Programm P47 wurde von Sven Panne vorgeschlagen.

zum Seitenanfang

Einfache Metainterpretierer


Der einfachste PROLOG-Metainterpretierer für PROLOG-Programme ist wohl das folgende Programm:
45
demo(X) :- X.
Ein einfacher Metainterpretierer, der jedoch die Auswertung näher spezifiziert, ist:
46
demo(true) :- !. demo( (X,Y) ) :- !, demo(X), demo(Y). demo(X) :- clause(X, Rumpf), demo(Rumpf).
Bemerkung: In vielen PROLOG-Systemen muß, um das Systemprädikat clause auf Klauseln, d.h. Fakten und Regeln, anwenden zu können, das durch diese Klauseln definierte Relationssymbol als dynamisch deklariert worden sein.

All-Antwort- und Systemprädikate berücksichtigen


Der Metainterpretierer P46 ist unzufriedenstellend, wenn er auf Objektprogramme angewandt wird, die PROLOG-Systemprädikate oder All-Antwort-Prädikate aufrufen. Das folgende Programm verbessert P46 in diesem Punkt:
48
demo(true) :- !. demo( (X,Y) ) :- !, demo(X), demo(Y). demo(findall(X, Y, Z)) :- !, findall(X, demo(Y), Z). demo(X^A) :- !, X^demo(A). demo(bagof(X, Y, Z)) :- !, bagof(X, demo(Y), Z). demo(coverof(X, Y, Z)) :- !, coverof(X, demo(Y), Z). demo(setof(X, Y, Z)) :- !, setof(X, demo(Y), Z). demo(X) :- system(X), !, X. demo(X) :- clause(X, Rumpf), demo(Rumpf).

4. Metainterpretierer zur Darstellung von Beweisbäumen für "reines PROLOG"

Die folgende Sitzung bezieht sich auf die Programme P49 und P50:
:- dynamic(kante/2), dynamic(verbunden/2). :- [user]. kante(a, b1). kante(b1, c1). kante(b1, c2). kante(a, b2). kante(b2, c1). kante(c1, a). verbunden(X, Y) :- kante(X, Y). verbunden(X, Y) :- kante(X, Z), verbunden(Z, Y). yes. :- demo(verbunden(a,a), B), darstellen(B). verbunden(a, a) weil kante(a, b1) und verbunden(b1, a) weil kante(b1, c1) und verbunden(c1, a) weil kante(c1, a) B = verbunden(a, a) <-- (kante(a, b1) <-- true, verbunden(b1, a) <-- (kante(b1, c1) <-- true, verbunden(c1, a) <-- kante(c1, a) <-- true)) More?
Bemerkung: der Wert von B wurde hier zur besseren Verständlichkeit mit Einrückungen versehen, die den Einrückungen bei der Ausgabe von darstellen(B) entsprechen. Das Prolog-System gibt den Wert von B natürlich ohne Einrückungen aus.

zum Seitenanfang

Metainterpretierer zur Darstellung von Beweisbäumen für "reines PROLOG"


Mit "reines PROLOG" bezeichnet man oft das Fragment von PROLOG ohne Negation und ohne nichtlogische Systemprädikate. Für "reine" PROLOG-Programme liefert der folgende Metainterpretierer die Beweisbäume zu den ausgewerteten Anfragen:
49
:- op(120, xfy, <--). demo(true, true) :- !. demo((X,Y), (BeweisX,BeweisY)) :- !, demo(X,BeweisX), demo(Y,BeweisY). demo(X, (X <-- BeweisR)) :- clause(X, R), demo(R, BeweisR).

5. Behandlung von cut

Wie die folgende Sitzung aber zeigt, erfüllt Programm P51 seinen Zweck nicht:
:- dynamic(p/1). yes. :- [user]. p(1). p(2). p(3). yes. :- p(A), !. A = 1 yes. :- demo( (p(A), !) ). A = 1 More? (;) ; A = 2 More? (;) ; A = 3 yes. :-
Warum? Die zusätzliche Klausel demo(!) :- !. behandelt eigentlich das Cut wie true, d. h. hat nicht den gewünschten Effekt. Die Anfrage
demo( (p(A), !) ).
wird bearbeitet wie
demo(p(A)), demo(!).
d. h. wie
demo(p(A)), demo(true).
d. h. wie
demo(p(A)).
Kein Rücksetzungspunkt wird dadurch beseitigt.
Zum Verständnis mag es helfen, die folgende Sitzung nachzuvollziehen, die sich auf Programm P52 bezieht:
:- dynamic(p/1). yes. :- [user]. p(1). p(2). p(3). yes. :- demo( (p(A),!), M ). A = 1 M = M More? (;) ; A = 1 M = cut_rueck More? (;) ; A = 2 M = M More? (;) ; A = 2 M = cut_rueck More? (;) ; A = 3 M = M More? (;) ; A = 3 M = cut_rueck yes. :- demo( (p(A),!) ). A = 1 More? (;) ; no (more) solution.
Die folgende Sitzung zeigt das korrekte Verhalten in einem komplizierteren Fall:
:- dynamic(p/1), dynamic(q/1), dynamic(r/1), dynamic(s/1), dynamic(t/1). yes. :- [user]. p(Z) :- q(Z). p(Z) :- t(Z). q(Z) :- r(Z), !. q(Z) :- s(Z). r(1). r(2). s(3). s(4). t(a). t(b). yes. :- demo( p(Z) ). Z = 1 More? (;) ; Z = a More? (;) ; Z = b yes.
Bemerkungen:
  1. In demo/1 sowie in der ersten und letzten Klausel von demo/2 wird   !,fail   statt not verwendet, um ein unerwünschtes Rücksetzen über die Disjunktion zu vermeiden. Man überprüfe, warum die folgende Definition von demo/1 nicht das Gewünschte leisten würde:
    demo(X) :- demo(X,M), M \== cut_rueck.

zum Seitenanfang

Behandlung von cut (1)


Eine naheliegende Lösung zur Behandlung des Cuts in Objektprogramme ist Programm P51 (als Ausarbeitung von Programm P46).
Wie die folgende Sitzung aber zeigt, erfüllt Programm P51 seinen Zweck nicht:
:- dynamic(p/1). yes. :- [user]. p(1). p(2). p(3). yes. :- p(A), !. A = 1 yes. :- demo( (p(A), !) ). A = 1 More? (;) ; A = 2 More? (;) ; A = 3 yes. :-

Behandlung von cut (2)


Warum? Die zusätzliche Klausel demo(!) :- !. behandelt eigentlich das Cut wie true, d. h. hat nicht den gewünschten Effekt. Die Anfrage
demo( (p(A), !) ).
wird bearbeitet wie
demo(p(A)), demo(!).
d. h. wie
demo(p(A)), demo(true).
d. h. wie
demo(p(A)).
Kein Rücksetzungspunkt wird dadurch beseitigt.
voriges Kapitel | Startseite | Inhalt | nächstes Kapitel

Letzte Änderung: 18. August 1998

Valid
	     XHTML 1.0!