Prolog - TUM · Prolog In diesem Kapitel wollen wir uns mit Logik-Programmierungbeschaftigen,¨...

35
Kapitel 4 Prolog In diesem Kapitel wollen wir uns mit Logik-Programmierung besch¨ aftigen, konkret mit der Program- miersprache Prolog. Bei kommando-orientierten Programmiersprachen wie Java und C, aber auch As- sembler, Fortran, Pascal usw. ist ein Programm eine Abfolge von Statements, Tests, Schleifen, Unter- funktionen usw., die von einem Interpreter oder (nach einer Kompilierung) von einem Prozessor abgear- beitet werden. Prolog geht einen anderen Weg. Ein Prolog-Programm kann als eine Menge von Axiomen, den Regeln und Fakten, aufgefasst werden. Ein Programm-Aufruf ist die Beantwortung einer Anfrage, d.h. das Testen, ob eine Aussage aus den Regeln und Fakten hergeleitet werden kann. Dieser Test wird automatisch im Hintergrund von einer sogenannten Inferenzmaschine (Inferenz Folgerung) ausgef¨ uhrt. Wir wollen diese Grundbegriffe (Fakten, Regeln, Anfragen) kurz einf¨ uhren, um uns einen ersten Ein- druck von (und Lust auf) Prolog zu verschaffen. In den darauf folgenden Abschnitten werden wir die Funktionsweise von Prolog formal erl¨ autern und zeigen, was Prolog mit der Aussagenlogik und der Pr¨ adikatenlogik zu tun hat. Wir werden die Bedeutung der Konzepte Resolution, Hornformeln, Substitu- tion und Skolemform f ¨ ur die Logik-Programmierung sehen und dann die komplexeren Sprachkonstrukte kennenlernen. Den Abschluss bildet ein Beispielprogramm aus der Praxis, das die M¨ achtigkeit und Ele- ganz der Logik-Programmierung demonstriert. 4.1 Syntax und Semantik von Prolog In diesem Abschnitt wollen wir die Syntax von Prolog–Programmen sowie deren Semantik, d.h. ihre pr¨ adikatenlogische Entsprechung behandeln. Wir werden neben den Prolog–Beispielen auch die ¨ aquiva- lente pr¨ adikatenlogische Formel angeben. Eine Zusammenfassung der Syntax findet sich in Tabelle 4.1. Variablen, Atome, Terme, Strukturen. Die Grundkonstrukte von Prolog sind Variablen und Atome. Variablen sind alle gross geschriebenen Worte, wie z.B. X, N15 und Ypsilon. Atome sind alle klein- geschriebenen Worte, wie z.B. vater, hase, a und bRUDER27. Die Atome sind die Platzhalter f¨ ur die Konstanten, die Funktionensymbole und die Pr¨ adikatensymbole in der Pr¨ adikatenlogik. Man muss aber unbedingt den syntaktischen Unterschied von Prolog zur Pr¨ adikatenlogik beachten, um nicht durchein- anderzukommen: in der Pr¨ adikatenlogik wurden die Variablen kleingeschrieben, die Pr¨ adikatensymbole gross und die Funktionensymbole wieder klein. Es ist in Prolog nicht aus einem Namen erkenntlich, ob es sich um eine Funktion oder ein Pr¨ adikat handelt. Das wird aber immer sofort aus der Verwendung im Programm sichtbar. Auf der n¨ achsten Stufe stehen die Strukturen und Terme. Sie sind wie folgt rekursiv definiert: Ein Term ist eine Variable oder eine Struktur; eine Struktur ist entweder ein Atom oder ein Atom gefolgt von 91

Transcript of Prolog - TUM · Prolog In diesem Kapitel wollen wir uns mit Logik-Programmierungbeschaftigen,¨...

  • Kapitel 4

    Prolog

    In diesemKapitel wollen wir unsmit Logik-Programmierungbescḧaftigen,konkretmit der Program-mierspracheProlog.Bei kommando-orientierten Programmiersprachenwie Java und C, aberauchAs-sembler, Fortran,Pascalusw. ist ein ProgrammeineAbfolge von Statements,Tests,Schleifen,Unter-funktionenusw., dievon einemInterpreteroder(nacheinerKompilierung)voneinemProzessorabgear-beitetwerden.ProloggehteinenanderenWeg.Ein Prolog-ProgrammkannalseineMengevonAxiomen,denRegeln undFakten, aufgefasstwerden.Ein Programm-Aufrufist die BeantwortungeinerAnfrage,d.h.dasTesten,ob eineAussageausdenRegelnundFaktenhergeleitetwerdenkann.DieserTestwirdautomatischim HintergrundvoneinersogenanntenInferenzmaschine(Inferenz� Folgerung)ausgef̈uhrt.Wir wollen dieseGrundbegriffe (Fakten,Regeln,Anfragen)kurz einführen,um unseinenerstenEin-druck von (und Lust auf) Prologzu verschaffen. In dendarauffolgendenAbschnittenwerdenwir dieFunktionsweisevon Prolog formal erläuternund zeigen,was Prolog mit der Aussagenlogikund derPr̈adikatenlogikzu tunhat.Wir werdendieBedeutungderKonzepteResolution,Hornformeln,Substitu-tion undSkolemformfür dieLogik-ProgrammierungsehenunddanndiekomplexerenSprachkonstruktekennenlernen.DenAbschlussbildet ein BeispielprogrammausderPraxis,dasdie Mächtigkeit undEle-ganzderLogik-Programmierungdemonstriert.

    4.1 Syntaxund Semantik von Prolog

    In diesemAbschnittwollen wir die Syntaxvon Prolog–Programmensowie derenSemantik,d.h. ihreprädikatenlogischeEntsprechungbehandeln.Wir werdennebendenProlog–Beispielenauchdie äquiva-lenteprädikatenlogischeFormelangeben.EineZusammenfassungderSyntaxfindetsichin Tabelle4.1.

    Variablen, Atome, Terme, Struktur en. Die Grundkonstruktevon Prologsind Variablenund Atome.Variablen sind alle grossgeschriebenenWorte, wie z.B. X, N15 und Ypsilon . Atomesind alle klein-geschriebenenWorte, wie z.B. vater , hase , a und bRUDER27. Die Atome sind die Platzhalterfür dieKonstanten,die Funktionensymboleunddie Pr̈adikatensymbolein derPr̈adikatenlogik.Man mussaberunbedingtdensyntaktischenUnterschiedvon Prologzur Pr̈adikatenlogikbeachten,um nicht durchein-anderzukommen:in derPr̈adikatenlogikwurdendie Variablenkleingeschrieben, die Pr̈adikatensymbolegrossunddie Funktionensymbolewiederklein. Esist in Prolognicht auseinemNamenerkenntlich,obessichum eineFunktionoderein Pr̈adikathandelt.Daswird aberimmersofortausderVerwendungimProgrammsichtbar.

    Auf dernächstenStufestehendie StrukturenundTerme.Siesindwie folgt rekursiv definiert:Ein Termist eine Variableoder eine Struktur; eine Struktur ist entwederein Atom oder ein Atom gefolgt von

    91

  • Was? Definition BeispielAtom kleingeschriebenesWort a, bruder , zwEI2

    Variable grossgeschriebenesWort X, Bruder , Y15

    Sonder-zeichen

    :- (das”wenn“ )

    ?- (dasAnfragensymbol)

    ”, “ (das

    ”und“ in RegelnundAnfragen)

    ”. “ (dasKlauselendzeichen)

    ”( “ (dieKlammernzumErschaffen von

    ”) “ Strukturen)

    Term Variable X15Struktur

    Struktur Atom adamAtom( Term) f(x)Atom( Term , Term) vater(adam,peter)Atom( Term , Term, ����� ) add(f(f(a)),f(a),X)

    Fakt Struktur. liebt(gott,X).

    Regel Struktur:- Struktur. kauft(sibylle,X):-b ill ig (X) .Struktur:- Struktur, Struktur. opa(X,Y):-vater(X,Z ),v at er( Z,Y ).Struktur:- Struktur, Struktur, ����� .

    Programm (leeresProgramm)Regel ProgrammFakt Programm

    Anfrage ?- Struktur. ?-opa(andrea,claus) .?- Struktur, Struktur. ?-add(a,f(a),X),add (X, Y, f(f (a) )).?- Struktur, Struktur, ����� .

    Tabelle4.1:Syntaxvon Prolog

    einerListevonTermen,die in KlammerneingeschlossenunddurchKommasgetrenntsind.BeispielefürTermesindPlatzDa , wegda(Du) , komme(ich,jetzt) , wobeidererstekeineStrukturist.

    Auf obersterEbenestehenin Prologdie Klauseln. Esgibt drei Arten von Klauseln:Fakten,RegelnundAnfragen.Diesist einestarke Parallelezuden(aussagenlogischen)Hornformelnin Abschnitt1.21.

    Fakten und Regeln.Ein Fakt ist eineStruktur, dievoneinemPunktgefolgtwird. In derPr̈adikatenlogikentspr̈achedaseinemPr̈adikat,welchesfür sichsteht.WenneineVariablevorkommt,somussmansiesichdurchein

    �quantisiertvorstellen:

    habeHunger. HabeHunger ���vater(frank,ruedi). Vater � f rank� ruedi �add(a,a,a). Add � a � a � a�add(a,X,X)

    �xAdd � a � x � x�

    SemantischlassensichdieFaktenwie Pr̈adikatemit einergewissenAnzahlvonArgumenteninterpretie-ren.DerzweiteFakt liestsichdannumgangssprachlich:

    ”Frankist derVatervonRuedi“ , dervierteFakt:

    ”Für allex gilt 0 � x � x“ (die Konstantea wird wie in derPr̈adikatenlogikalsNull interpretiert).

    Die zweiteKlauselartist die Regel. SiebestehtauseinerStruktur(dem”Kopf“ ), derZeichenkette

    ”:- “ ,

    einerListe von Strukturen(dem”Rumpf“ ), ebenfalls abgeschlossendurcheinemPunkt.Das

    ”:- “ wird

    92

  • als”wenn“ ausgesprochenundwird mit demumgekehrtenFolgerungspfeil übersetzt.Die Strukturen

    im RumpfwerdendurchKommasgetrennt,die als”und“ ( ) interpretiertwerden:

    endloseFreiheit(X) :- übe rde nWolk en( X).�x � EndloseFreiheit� x�� ÜberdenWolken� x���

    add(f(X),Y,f(Z)):- add(X ,Y, Z). �x�

    y�

    z� Add � f � x��� y� f � z��� Add � x � y� z���opa(X,Y):-vater(X, Z) ,va ter (Z, Y) . �

    x�

    y�

    z� Opa� x � y���� Vater � x � z�� Vater � z� y�����Wir wollenversuchen,die Regelnumgangssprachlichzuverstehen.Wir behaupten,die Regel

    opa(X,Y):-vater(X,Z ),v ate r(Z ,Y ).

    übersetztsich folgendermassenins Deutsche:”Herr X ist der Grossvater von Herrn Y, wenn eseinen

    Herrn Z gibt, dessenVaterX ist undderselberderVatervon Y ist.“ Bisherhattenwir gesagt,dassalleVariablenallquantisiertsind. Dassdie o.g. Übersetzungtrotzdemrichtig ist, sehenwir an folgenderprädikatenlogischerUmformung:�

    x�

    y�

    z� Opa� x � y���� Vater � x � z�� Vater � z� y������ � x� y� z� Opa� x � y������� Vater � x � z�� Vater � z� y����� (Def. von undDeMorgan)� � x� y � Opa� x � y��� � z��� Vater � x � z�� Vater � z� y����� (zkommtin Opa��������� nicht frei vor)� � x� y � Opa� x � y������� z� Vater � x � z�� Vater � z� y����� (� � � ��� )� � x� y � Opa� x � y���� z� Vater � x � z�� Vater � z� y����� Heureka!FaktenundRegelnzusammengenommenstellendasProlog–Programmdar. Als prädikatenlogische For-melnsinddie Klauselndurch verkn̈upft.Anfragen. Man betrachtetein Prolog–ProgrammgernealsDatenbankvon Wahrheiten,andie manAn-fragen (auchgerneZielklauselngenannt)stellenkann.EineAnfragebeginnt mit einem

    ”?- “ , demAn-

    fragesymbol(als”Stimmt es,dass ����� ?“ zu lesen).Es wird von einerListe von Strukturengefolgt,die

    wiederdurchKommasgetrenntunddurcheinenPunktabgeschlossenwird. AuchdieseListenenntmanRumpf. In eineprädikatenlogischeForm bringt mandie Anfragen(derHornklausel–Enthusiastahntesschon)durchDavorschreibeneinesNegationszeichensundderInterpretationallerKommasals

    ”und“ :

    ?-froh(reinhard). � Froh� reinhard �?-opa(claus,X).

    �x� Opa� claus� x�

    ?-add(X,Y,f(f(f(a)) )) ,ad d(X ,f( a) ,Y) .�

    x�

    y ��� Add � x � y� f � f � f � a�������� Add � x � f � a��� y���Diesist ganzwie beidenHornformeln:umeineAnfrageauseinerKlauselmengezufolgern,gen̈ugtees,ihr Gegenteilanzunehmenunddie unerf̈ullbareFormelzu folgern.AuchwennVariablenins Spielkom-men,stimmtdiesesBild: Im letztenBeispielistdieprädikatenlogischeFormeläquivalentzu ��� xOpa� claus� x� ,wasderFrageentspricht

    ”Stimmtes,dassesein X gibt, dessenGrossvaterClausist?“ Beziehungsweise

    garein zweifelndes”HatClausEnkel?“ Die letzteBeispielformelwürdesichals

    ”Gibt esx undy, deren

    Summe3 undderenDifferenz1 ist?“ übersetzen.

    4.2 Prologund Hornklauseln

    4.2.1 Einf ührendeBeispiele

    Betrachtenwir dasBeispielprogrammfiktiver Familienbeziehungen:

    93

  • 1 : vater(adam,bertold).2 : vater(bertold,claus) .3 : vater(adam,dieter).4 : vater(ede,frank).5 : opa(X,Y):-vater(X,Z) ,v ate r(Z ,Y) .6 : onkel(X,Y):-vater(Z, X) ,op a(Z ,Y) .

    Die vier Faktenlassensichin einemStammbaumverdeutlichen:

    Adam

    Bertold

    Claus

    DieterEde

    Frank

    Die anderenzwei Zeilenenthaltendie Regeln. Alle Variablensindallquantisiert.Daherkönnenwir fürX, Y, Z beliebigeTermeeinsetzen(substituieren)und erhalteneineFolgerungder Regel. Zum Beispielergibt die Substitution[X/adam][Y/claus][Z /b ert old ] die Regel

    5� : opa(adam,claus):-va ter (ad am,berto ld) ,va te r(b ert old ,c lau s).Eine Prolog–Klausel(ein Fakt odereineRegel), die keineVariableentḧalt, könnenwir als (aussagen-logische)Hornklauselauffassen,indem wir jedenTerm mit einer entsprechendenaussagenlogischenatomarenFormelidentifizieren.

    vater(adam,bertold) . Va � bvater(bertold,claus ). Vb � copa(adam,claus):-

    vater(adam,bertold ),vater(bertold,clau s).

    "!# Oa � c ��� Va � b ��� Vb � c

    ?-opa(adam,claus). � Oa � cIn Abschnitt1.21habenwir gesehen,dasseseinenAlgorithmusgibt, um zu entscheiden,ob ausHorn-formel F ein weitererFakt A folgt. Dazunahmenwir dennegiertenFakt � A alsAnfragedazuundver-suchtenmit Hilfe vonResolutionendieleereKlausel $ zufolgern.Wennunsdasgelang,sowusstenwir,dassdiegesamteFormelF %� A unerf̈ullbar seinmussteunddarumA ausF folgenmuss.Hierzugabeszwei Strategien,einebottom–up–Strategie undeinetop–down–Strategie. Die top–down–Strategie gehtvon derAnfrageaus,suchtnachRegelnoderFakten,ausdenendie Anfragefolgenkönnteundnimmtggf. die HypothesendieserRegel alsneueAnfragen.DieserAlgorithmusarbeitetrekursiv (für jedeAn-fragewerdenallemöglichenRegelnundFaktengesuchtundnacheinanderausprobiert),bisentwederdieleereAnfragegefundenwurde(A folgt ausF) oderalle MöglichkeitenohneErfolg ausprobiertwurden(A folgt nichtausF).

    Prologfolgt diesertop–down–Strategie.DerAbschnitt4.3wird sichausf̈uhrlichmit denDetailsbescḧafti-gen.Wir wollen jetzt schonamBeispielderAnfrageopa(adam,claus) einenÜberblickgeben.Linksist derBaumderHornklauselresolutionen,rechtsdieentsprechendenResolutionenderProlog–Klauseln.

    94

  • DieseBäumewerdenauchResolutionsb̈aumeoderAbleitungsb̈aumegenannt:

    ?-opa(adam,claus). opa(X,Y):-vater(X,Z),vater(Z,Y).

    ?-vater(adam,Z),vater(Z,claus). vater(adam,bertold).

    ?-vater(bertold,claus). vater(bertold,claus).

    [X/adam][Y/claus]

    [Z/bertold]

    ?-.

    PSfragreplacements

    $

    � Oa � c��� Va � b Vb� c �� Vb � c

    Oa � c ��� Va � b ��� Vb � cVa � bVb � c

    An diesemBeispielsiehtmanauch,dassProlognichtalleVariablensofortauseinerRegelheraussubsti-tutiert, sondernnur immersoviele, wie geradenotwendigsind. In dererstenZeile sinddiesnur X undY, Z wird nochin die zweiteZeile übernommen.Für die Resolutionist esnämlich lediglich notwendig,dass(nachVariablensubstitutionen) opa(adam,claus) undopa(X,Y) gleichsind.Im allgemeinenmusszur Resolutionder Kopf der Regel unddie (ersteStrukturder)Anfrage übereinstimmen. DasAuffindeneinerSubstitution,diedieseÜbereinstimmungbewirkt, wird alsUnifikationbezeichnet(sieheAbschnitt4.3.1).

    Die Anfrage?-opa(adam,claus) übersetztesich in die Frage”Ist Adam der Grossvatervon Claus?“

    Die Antwort ist mit derAnwendungdero.g.umgangssprachlichenRegel”Ja“ , dennAdamist derVater

    vonBertold,derselbstwiederderVatervonClausist. Wir wollenversuchen,dieAbleitungin umgangs-sprachlichenSätzennachzuvollziehen:Um die Regel

    ”Für alle MenschenX und Y ����� “ zu verwenden,

    habenwir für X Adamundfür Y Clauseingesetzt(odersubstituiert). NachderResolutionbleibt die An-frage?-vater(adam,Z),v ate r(Z ,c lau s) bzw. dieFrage:

    ”ExistierteinMenschZ, dessenVaterAdam

    ist undderselbstVatervonClausist?“ DasDurchsuchenderFaktenliefert”Adamist VatervonBertold“ .

    Wir setzenin unsererRegelBertoldin Z einundmüssennunüberpr̈ufen,obBertoldVatervon Clausist.Diesist wiederein Faktundwir können

    ”Ja“ antworten.

    WannantwortetPrologmit”Nein“ ? Hier mussmanAcht geben,denndiesgeschiehtnichtnur, wenndie

    Anfragefalschist, sondernimmer, wennProlog die Anfrage nicht ausdenFaktenund Regeln folgernkann. Zum Beispielkanndie Anfrage?-onkel(dieter,fran k) nicht auf die beschriebeneWeiseausdemProgrammgefolgertwerden.Man musssichaberklar machen,dassdiesnicht heisst,dassPrologeinenGegenbeweisgefundenhat,d.h.dasGegenteilderAnfrageausdenRegelnfolgernkonnte.Nein,esheisstlediglich,dassalleVersuche,die Anfragezubeweisen,gescheitertsind.

    Bisherhabenwir nur Ja/Nein–Anfragengestellt(”Ist eswahr, dassAdamderVatervon Bertold ist?“ ).

    EssindaberauchFragennacheinemWert denkbar:”Wasist 2 � 2?“ Für ein Pr̈adikatadd(X,Y,Z) , das

    genaudannwahrwird, wennx � y � z ist, könntenwir fragen?-add(f(f(a)),f(f(a )) ,X) . Um solcheinPr̈adikatzu definieren,betrachtenwir dasProgramm:

    add(a,X,X).add(f(X),Y,f(Z)):- add (X ,Y, Z).

    DiesesProgrammerinnertsehrandie rekursive ModellierungdernaẗurlichenZahlenin derPr̈adikaten-logik. In dererstenZeilestehtderFakt:

    ”�

    x0 � x � x“ (a stehtfür dieNull). Die zweiteZeileentḧalt dieRegel:

    ”�

    x�

    y�

    z � f � x�&� y � f � z���'(� x � y � z� “ . Wie auchschonbeiunserenBetrachtungenzurPr̈adika-tenlogikinterpretierenwir f alsNachfolgerfunktionf � x� � x � 1. Die RegelentsprichtalsoderAussage

    95

  • übernaẗurlicheZahlen � x � 1�)� y � � x � y�)� 1. KonkretenaẗurlicheZahlensinddanndurchwiederholteAnwendungderFunktionf auf a erḧaltlich: f(f(f(a))) entsprichtgerade��� 0 � 1��� 1��� 1 � 3.Wir wollenunsanschauen,wiemanPrologmit diesemProgrammundderAnfrage?-add(f(f(a)),f(f( a) ),X )zumRechnenbringt.UnterAnwendungnurderbeideno.g.Programmzeilenist dieseAnfragebeantwort-bar. DerAbleitungsbaumsiehtdannfolgendermassenaus:

    ?-add(f(f(a)),f(f(a)),X). add(f(X1),Y1,f(Z1)):-add(X1,Y1,Z1).

    ?-add(f(a),f(f(a)),Z1). add(f(X2),Y2,f(Z2)):-add(X2,Y2,Z2).

    ?-add(a,f(f(a)),Z2). add(a,X3,X3).

    [X/f(Z1)] [X1/f(a)][Y1/f(f(a))]

    [Z1/f(Z2)] [X2/a][Y2/f(f(a))]

    [Z2/f(f(a)) [X3/f(f(a))]

    PSfragreplacements $Gleich in der erstenZeile fällt auf, dasszwar sinngem̈assdie zweiteZeile desProgrammsverwendetwurde,dieVariablenaberumbenanntwurden.Wir wollenverstehen,warumdiesmöglichist.Manmachesich zun̈achstklar, dasses nicht von Bedeutungist, ob die Allquantorender Variablenganzaussenodernur ausserhalbjederKlauselstehen.Dies ist eineKonsequenzausder Äquivalenz

    �x � F G� �� � xF ��*� � xG� . DasobigeProgrammlautetzumBeispielin eineprädikatenlogischeFormelübersetzt:�

    x�

    y�

    z � Add � a � x � x��+� Add � f � x��� y� f � z���, Add � x � y� z������ � x � Add � a � x � x�� � y� z � Add � f � x��� y� f � z���, Add � x � y� z������ � � xAdd � a � x � x����*� � x� y� z � Add � f � x��� y� f � z���, Add � x � y� z������ � � x1 Add � a � x1 � x1 ����*� � x2� y2 � z2 � Add � f � x2 ��� y2 � f � z2 ���� Add � x2 � y2 � z2 �����Die ersteÄquivalenzist Ausklammernvon

    �x, die zweitekommtvon derRegel

    �x � F G� � � � xF �-� � xG� . Wir sehenauch,dassdurchdiegebundeneUmbenennung(dritte Äquivalenz)dieVariableneiner

    Klausel(einesFaktsodereinerRegel) umbenanntwerdenkönnen,ohnedenSinnderFormel(desPro-gramms)zu ver̈andern.Dasheisst,dasProgrammkannauchohneSinn̈anderungwie folgt geschriebenwerden.

    add(a,X1,X1).add(f(X2),Y2,f(Z2) ):- add (X 2,Y 2,Z 2).

    DieseUmbenennungwird von Prologimmerautomatischvorgenommen.Nur sokönnenwir die RegelnundFaktenviele Male unabḧangigverwenden.Nocheinmal:Prologbenenntdie Variablenderverwen-detenRegel (oderdesverwendetenFaktes)immer so um, dassdiesekeineVariablemit der aktuellenAnfragegemeinhat.

    WennmandenÜbergangvonderersten(urspr̈unglichen)Anfragezurnächstengenauansieht,sobemerktman,dassmit Hilfe derRegeldieAnfragevereinfacht wurde:von

    ”Wasist 2 � 2?“ gehteszu

    ”Wasist 1 �

    2?“ über. Diesist ja genauderSinnvon rekursivenProgrammen:In jedemSchrittwird die Aufgabeeinwenigvereinfacht,gleichtabergrunds̈atzlichderurspr̈unglichenAufgabe.Am EndebleibteineeinfacheAnfrage(

    ”Wasist 0 � 1“ ) übrig, die nur nocheineneinfachenFakt zur Beantwortungben̈otigt. Dies ist

    dasGrundprinzipder Rekursion.Es ist extrem wichtig für dasProgrammierenin Prolog,da praktischalleetwaskomplexerenProgrammeRekursion(meistsogarmehrfach)enthalten.

    96

  • Die Antwort von PrologaufdieseAnfrageentḧalt auchdenerrechnetenWert: Prologantwortet

    X=f(f(f(f(a)))) Yes

    DenWertvon X bekommtmandurchAnwendungaller Substitutionenauf X:

    X [X/f(Z1)][X1/f(a)][ Y1/f( f(a ))] [Z 1/f (Z2 )][ X2/a] [Y2 /f( f( a)) ][Z 2/f (f (a) )][ X3/ f( f(a ))]� X [X/f(Z1)][Z1/f(Z2)][ Z2/f( f(a ))]� f(f(f(f(a)))) �welchesdemrichtigenErgebnis

    ”4“ entspricht.

    4.2.2 Prologklauselnsind Hornklauseln

    Um nochbesserzu verstehen,wasPrologmit der Aussagenlogikund mit der Pr̈adikatenlogikzu tunhat,wollenwir FaktenundRegelnsowie Anfragennochmehrformalisieren.Die allgemeinsteFormderRegel ist

    B:- C1, ����� , Cm.wobeimeinenaẗurlicheZahl ist. Wennwir dieSyntaxvon Prologleicht ab̈andern,fallenauchFaktenindieseForm:Für m � 0 ist derRumpfderRegel leer. DiesmachtauchSinn,denndieprädikatenlogischeÜbersetzungeinerRegel mit denVariablenx1 ����� xr würdedannlauten:�

    x1 ����� � xr � B ��� C1 �.��������� Cm ���Für m � 0 fallendanneinfachkeineC1 ����� Cm an,esist einFakt.Wir führendieseAnpassungderSyntaxjedochnur in unserenKöpfendurch,Prologwürdehungrig(ich):-. nichtverstehen.

    Ebensokönnenwir auchdieSyntaxderAnfragendurch

    ?- D1, ����� , Dn.formalisieren,wiedersindD1 ��������� Dn Strukturenundn einenaẗurlicheZahl.Fürn � 0 erhaltenwir die(inProloglegale)leereAnfrage.Die Übersetzungin eineprädikatenlogischeFormellautetdementsprechend�

    x1 ����� � xs ��� D1 �/�����0��� Dn ���wobeiwiederx1 �������1� xs die in derAnfragevorkommendenVariablensind.Wir wollen unsüberlegen,welcheprädikatenlogischenFormelnwir als Prolog–Programmeschreibenkönnen.Zunächsthabenwir gesehen,dassin einervon PrologstammendenFormelalle Quantorenvor-ne stehenund dasssie alle Allquantorensind. Ausserdemist einesolcheFormel nachWegnahmederQuantoreneineKonjunktion(Ver-und-ung)derKlauseln,derFakten,RegelnundAnfragen.DieseKlau-selnsind wiederumDisjunktionen(Ver-oder-ungen)von Strukturen,von denenalle bis auf höchstenseinenegiert sind.(Die Disjunktionenohnepositive StrukturensinddieAnfragen.Die DisjunktionenmitnureinereinzigenStruktur, dieauchnochpositiv ist, sinddie Fakten.Alle anderensinddie Regeln.)

    Satz4.2.1 Die prädikatenlogischen Formeln, die Prolog–Programmen(inkl. Anfragen) entsprechen,sindgenaudie Formelnin Skolemform,derenBoole’scheFormeineHornformelist.

    97

  • Ist dieseineEinschr̈ankung?Die Antwort lautetleider ja. Beispielsweiseist die Definition desonkel –Pr̈adikatsdurch

    onkel(X,Y):-vater(Z ,X) ,op a(Z ,Y ).

    nurunvollständig.Sieschliesstnämlichnichtaus,dassX derVatervon Y ist: auchdanngibt eseinZ, dasVatervonX undGrossvatervonY ist. Einerichtigeprädikatenlogische Formulierungmüsstedannlauten:�

    x�

    yOnkel � x � y��2��� zVater � z� x�� Opa� z� y��%� Vater � x � y���� � x� y� z� Onkel � x � y��� Vater � x � y���%� Vater � z� x����� Opa� z� y�1���DieseFormel ist zwar in Skolemform (man kann ja jede Formel in Skolemform bringen),aber ihreBoole’scheFormist keineHornformel,dazweiLiteralepositiv sind.AuchdurchweitereUmformungenist sie nicht in einesolcheForm zu bringen.Wir werdenjedocham EndediesesKapitelseinenWegsehen,wie manmit Hilfe derexpliziten AusnutzungderAuswertungsstrategie ein Programmverhaltenerreichenkann,welchesdie obigeFormelsimuliert.

    98

  • 4.3 Unifikation und Auswertungsstrategie

    FürHornformelnhattenwir zweiArtenvonAlgorithmen,umzuentscheiden,obsieunerf̈ullbarsind(Ab-schnitt1.21):einebottom–up–Strategie undeinetop–down–Strategie.Die Prolog–Auswertungstrategie,derAlgorithmuszur Beantwortungvon Anfragen,folgt der top–down–Strategie: die Anfragewird so-langemit RegelnundFaktenresolviert,bis die leereAnfrageherauskommt.Da bei PrologjedochnochVariableninsSpielkommen,müssenwir unszun̈achstdemsystematischenEinsetzenvonVariablen,derUnifikationzuwenden.

    4.3.1 Unifikation

    Wir definierendieSubstitutionvonVariablenin KlauselnanalogzurPr̈adikatenlogik:wennF eineKlau-selist undt einTerm,sosoll F [X/ t] jedesAuftretenvon X in F durcht ersetzen.Substitutionenkönnenauchverkettet (nacheinanderausgef̈uhrt) werden.Zum Beispielsoll die Substitutionfolgendermassenwirken:

    add(X,f(a),f(X))[X /f (f( a)) ] � add(f(f(a)),f(a),f (f( f( a)) )) �Wendenwir unsnocheinmaldemim Einführungsabschnitt4.2gebrachtenBeispielzu. Dort sollteher-ausgefundenwerden,obAdamderGrossvatervonClausist (?-opa(adam,claus) ), unddabeidieRegelopa(X,Y):-vater(X,Z ),v ate r(Z ,Y ) angewendetwerden.Zu diesemZweck führtenwir die Substi-tution [X/adam][Y/claus] durch,damit in der Anfrage und im Kopf der anzuwendendenRegel dasGleichesteht. DiesnenntmanUnifikation: für zweiTermesoll eineSubstitutiongefundenwerden,nachderenAnwendungdie Termegleichsind.

    Definition 4.3.1 (Unifikation in Prolog)ZweiTermeF undG heissenunifizierbar, wenneseineSubsti-tutionsubgibt, sodassnach Ausf̈uhrungdesUnifikators für beidedasGleich herauskommt,d.h.

    F sub � Gsub�EinesolcheSubstitutionnenntmaneinenUnifikator.

    Beispielsweisesind add(X,a,X) und add(f(B),Z,Y) mittels [X/f(a)][B/a][Y/f( a)] [Z /a] unifi-zierbar(checkit!), es kommt beideMale add(f(a),a,f(a)) heraus.Bei genaueremHinsehenfälltauf, dasszu viel substituiertwurde:eswar überhauptnicht nötig, B zu substituieren,die Substitution[X/f(B)][Y/f(B)][Z/ a] hättegen̈ugt. Dies ist ein sog.allgemeinsterUnifikator, denerstgenanntenUnifikator erḧalt mandurchNachschaltenderSubstitution[B/a] . Ähnlicheshattenwir schonbei demeinführendenBeispielauf S. 92 gesehen.Ein allgemeinsterUnifikator ist, umgangssprachlichgespro-chen,ein Unifikator, der so viele Variablenwie möglich unber̈uhrt lässt.JederandereUnifikator kanndanndurchNachschalteneinerweiterenSubstitutionerhaltenwerden.

    Definition 4.3.2 (Allgemeinster Unifikator) Der allgemeinsteUnifikator ist ein Unifikator subvonFundG, sodassjederweitereUnifikatorsub� vonF undG durch NachschalteneinerweiterenSubstitutionssub3 erhaltenwerdenkann,d.h.sub� � subssub3 . (ZweiSubstitutionengeltenalsgleich, wennsieauf jedeVariableangewendetdasGleicheergeben.)

    EsgibtaberauchKlauseln,dienichtunifizierbarsind:dieTermevater(X,j ürgen) undbruder(johannes,Y)sindein solcherFall. Esgibt keineSubstitution,die,auf beideSeitenangewendetdasGleicheergibt, daschondie führendenAtomevater undbruder unterschiedlichsind.

    99

  • Schauenwir unsfür einebessereIntuition nochein letztesBeispielan:

    vater(X,peter) undvater(f(g(Y,a),Z),Z ) �DasführendeAtom vater stimmtüberein.DochschonbeieinererstenInspektiondesInnerenderKlau-seln fällt ins Auge, dassX substituiertwerdenmuss.Es ist sogarnotwendig,schonjetzt festzulegen,dassX mit f(g(Y,a),Z) zu substituierenist, obwohl Y undZ sp̈aterwomöglich selbstnochsubstituiertwerden.DieseEinsichtbringtunszueinemAlgorithmus,derzuzweiStrukturendenallgemeinstenUni-fikator berechnet,wenndieserexistiert,und

    ”failure“ liefert, wenndie zwei Strukturennicht unfizierbar

    sind.DerAlgorithmuswird jeweils versuchen,Paarevon Termenzuunifizieren:

    4 WenneinerderTermeeineVariableist, dannwird dieseVariablemit demanderenTermsubstitu-iert,4 WennbeideTermeStrukturensind,somussdasführendeAtom gleichsein.In diesemFall wirddannversucht,alleTeilterm-Paarezuunifizieren,4 Wennbeidesnicht funktioniert,sinddie Termenicht unifizierbar.

    Algorithmus 4.3.3Input: ZweiStrukturenF undG, die keineVariablengemeinsamhaben.

    Output: Der allgemeinsteUnifikatorsubvonF undG, sonst”failure“ .

    Algorithmus:Initialisieredie Substitutionsubzur leerenSubstitution.InitialisiereeineleereListe l ist.

    HängedasTermpaar”F

    ?� G“ vornean l ist an.while (l ist ist nicht leer)do

    HängedasersteTermpaar”F1

    ?� G1“ von l ist ab.if (F1 ist eineVariableX, die im TermG1 nichtvorkommt)

    Substituiere[ X/ G1] in allenTermpaarenin l ist.Setzesub: � sub[ X/ G1] .

    if (G1 ist eineVariableX, die im TermF1 nichtvorkommt)Substituiere[ X/ F1] in allenTermpaarenin l ist.Setzesub: � sub[ X/ F1] .

    if (F1 undG1 sindidentischeKonstantenoderVariablen)Fahrefort.

    if (F1 � f ( F �1, ����� , F �n) undG1 � f ( G�1, ����� , G�n) für ein Atom f undeineZahln)Hänge

    ”F �1 ?� G�1 ��������� F �n ?� G�n“ vornean l ist an.

    if (dieobigenvier Fällesindallenichteingetreten)Gib

    ”failure“ aus.

    endwhile

    Gib denallgemeinstenUnifikator subaus.

    100

  • Satz4.3.4 Der Unifikationsalgorithmusist korrekt, d.h. er findetdenallgemeinstenUnifikator zweierTermeF undG, falls dieserexistiert, undgibt sonst

    ”failure“ aus.Insbesondere gibt esfür zweiunifi-

    zierbare TermeF undG immereinenallgemeinstenUnifikator.

    Beweis:Wir erweiternzun̈achstdenBegriff Unifikator:EineListevonTermpaaren� F1 � G1 ���5�������6� Fk � Gk �heisstunifizierbar, wenneseineSubstitutionsubgibt, die alle Paaresimultanunifiziert (d.h. Fi sub �Gi subfür alle i). AllgemeinsterUnifikator wird analogdefiniert.

    Der Algorithmusterminiert,daentwederin jedemSchritteineVariableausderListe verschwindet(dieerstenbeidenif–Abfragen)oderdie Gesamtzahlder Zeichenin der Liste geringerwird (in der drittenundviertenif–Abfragewird je ein Atom ausderListe eliminiert).Um die KorrektheitdesAlgorithmuszubeweisen,wollenwir in jedemSchrittfolgendeInvariantenachpr̈ufen:

    Invariante: Bei jedemTestderwhile-Schleifegilt, dassdie Liste l ist genaudannunifizierbarist, wenndie UrsprungstermeF und G unifizierbarsind. Weiterhin gilt zu diesenZeitpunktenfür die aktuelleSubstitutionsub: EineSubstitutiont ist genaudannein allgemeinsterUnifikator von l ist, wennsubt einallgemeinsterUnifikator von F undG ist.

    Die Invariantegilt offenbarbei der Initialisierung:anfangsist nur F undG in derListe unddie Substi-tution ist leer. Wennesunsgelingtzuzeigen,dassdie InvariantewährendjedesSchrittesgilt, dannauchwennl ist letztendlichleer ist. In diesemFall habenwir alsoeinenallgemeinstenUnifikator von F undG gefunden.Und umgekehrt, falls F und G nicht unifizierbarsind, so kanndiesnicht passieren,alsomüssenwir irgendwannin die fünfte if–Abfragehineinlaufenund

    ”failure“ ausgeben.

    Behauptung1. Sei � F1 � G1 ���������1��� Fk � Gk � eineListe von Termpaaren,s allgemeinsterUnifikator von F1undG1 sowie s� allgemeinsterUnifikatorderListe � F2 s� G2 s���7�������7� Fk s� Gk s� , dannist ss� allgemeinsterUnifikatorderurspr̈unglichenListe.

    Diesbedeutet:Um einenallgemeinstenUnifikatoreinerListevonTermpaarenzufinden,kannzuerstderallgemeinsteUnifikator deserstenTermpaares� F1 � G1 � berechnetwerden,dieserauf denRestderListeangewendetund von diesemRestdannder allgemeinsteUnifikator gefundenwerden.Wir wollen unsdie Gültigkeit derBehauptungklarmachen:Da s ein Unifikator von � F1 � G1 � ist, ist auchss� einer. Da s�die Termpaare� Fi s� Gi s� unifiziert, ist ss� ein Unifikator derTermpaare� F2 � G2 ���������1�8� Fn � Gn � . Also istss� ein Unifikator dergesamtenListe.Esbleibt zu zeigen,dasser auchallgemeinsterUnifikator ist. Seialsot einweitererUnifikatordergesamtenListe.Dannist t aucheinUnifikatorvon � F1 � G1 � , alsogibt esnachDefinition desallgemeinstenUnifikatorss eineSubstitutiont � , sodasst � st � . Da t auchdenRestderListe unifiziert, ist t � ein Unifikator derListe � F2 s� G2 s�����������8� Fn s� Gn s� . Ebenfalls nachDefinitionvons� gibt eseineSubstitutiont � � , sodasst � � s� t � � . Also ist t � ss� t � � , undss� ist allgemeinsterUnifikator.Wastut nunderAlgorithmus?Er beginntdamit,diebeidenzuunifizierendenTermeF undG in eineListezu speichern.Dannnimmt er sich jeweils dasersteTermpaarderListe undversucht,eszu unifizieren.Zunächstgibt esdrei Regeln,wie mit VariablenoderKonstantenzu verfahrenist, unddanneineRegel,wie mit komplizierterenStrukturenumgegangenwird. Diesewerdennämlich auf gleichesführendesAtom undgleicheStelligkeit überpr̈uft. DannwerdenalleneuenTermpaareausdenArgumentengebildetundandie Liste angeḧangt.

    Wendenwir unszun̈achstdenerstenbeidenRegelnzu.

    Behauptung 2. WennX eineVariableist, für die entwederT � X gilt oderdie im Term T nicht vor-kommt, so ist [ X/ T ] ein allgemeinsterUnifikator. Wenndie VariableX hingegenin T vorkommt, sosindX undT nichtunifizierbar.

    WennX nicht in T vorkommt, so ist offenbarsub � [ X/ T ] ein Unifikator der beidenTermeX undT. Warumist subaberein allgemeinsterUnifikator?Seisub� ein weitererUnifikator von X undT. Die

    101

  • Behauptungist nun, dasssub� � subsub� . Zwei Substitutionensind gleich, wenn sie auf jedenTermangewendetdasGleicheergeben.Es gilt aberX sub� � T sub� , da sub� ein Unifikator ist, dies ist aberwegenT � XsubgleichX subsub� . Damit ist dieBehauptungfür dieVariableX gezeigt.Für jedeweitereVariablebewirkendie beidenSubstitutionenebenfalls dasGleiche,dasubkeineVer̈anderungbewirkt.

    WennX nundochin T vorkommt,sokanneskeinenUnifikatorgeben.DerTermT ist dannlängeralsX(in Zeichengerechnet).Weiterhinwird T durcheineSubstitutionmindestenssoviele Zeichenverlängertwie X, daX ja in G vorkommt.Also ist T subimmerlängeralsX sub.

    Wir wollendieBeweissẗuckenunzusammenf̈ugenundeinenDurchlaufderwhile-Schleifedurchspielen.Wir habenschongesehen,dassdie Invariantezu Beginn gilt. Wenndie ersteif -Abfragepositiv beant-wortetwird, soist wegenBehauptung2 derallgemeinsteUnifikator s von F1 � X undG1 � T bekannt:s � [ X/ T ] . subwird aufsubsgesetztunddieListe l ist durch � F2 s� G2 s���9�������7� Fn s� Gn s� ersetzt.WegenBehauptung1 ist die Invarianteimmernocherfüllt. Ebenso,wenndiezweiteif -Abfrageerfüllt wird. Diedritte ber̈uhrt die Invariantetrivialerweisenicht. Die Erhaltungder Invariantein dervierten if -Abfragewird durchdie folgendeAussagegezeigt:

    Behauptung3. WennF1 � f ( F �1, ����� , F �n) undG1 � f ( G�1, ����� , G�n) (für gleichesAtom f undgleicheStelligkeit n) undwennl ist � � F1 � G1 ���1� F2 � G2 ������������� Fk � Gk � , dannsindsämtlicheTermpaarein l ist ge-naudannunifizierbar, wennesdie Listenvon Termpaaren� F �1 � G�1 ������������� F �n � G�n ���1� F2 � G2 ������������� Fk � Gk �sind.Die allgemeinstenUnifikatorenstimmenüberein.

    Hierzuist nurzubemerken,dassF1s � f ( F �1 s, ����� , F �n s) ist. Für G1 gilt Analoges.Die Behauptungfolgtdirekt.

    Wennkeineder erstenvier if -Abfragenzu einempositiven Ergebniskommt, liegt dasentwederdaran,dasseinerderTermeF1 und G1 eineVariableist, der im jeweils anderenTermvorkommt (nicht unifi-zierbarnachBehauptung2), dasssieunterschiedlicheKonstantensind(demnachnichtunifizierbar)oderdasssieStrukturenmit unterschiedlichenAtomenoderStelligkeitensind(auchnicht unifizierbar).

    Wir wollenunszweiBeispieleanschauen.Hierbeiist in jedemSchrittderInhaltderListe l ist (übereinan-

    102

  • der),dieaktuelleSubstitutionsubsowie dieNummerdernächstenangewendetenif–Abfrageangegeben:

    ErsterTerm ZweiterTerm Substitution if#q(g(f(X),Y),g(X,g(Y,Y)))

    ?: q(Z,g(f(a),Z)) [] 4g(f(X),Y)

    ?: Z [] 2g(X,g(Y,Y))

    ?: g(f(a),Z)g(X,g(Y,Y))

    ?: g(f(a),g(f(X),Y)) [Z/g(f(X),Y)] 4X

    ?: f(a) [Z/g(f(X),Y)] 1g(Y,Y)

    ?: g(f(X),Y)g(Y,Y)

    ?: g(f(f(a)),Y) [Z/g(f(X),Y)][X/f(a)] 4Y

    ?: f(f(a)) [Z/g(f(X),Y)][X/f(a)] 1Y

    ?: Yf(f(a))

    ?: f(f(a)) [Z/g(f(X),Y)][X/f(a)][Y/f(f(a))] 4f(a)

    ?: f(a) [Z/g(f(X),Y)][X/f(a)][Y/f(f(a))] 4a

    ?: a [Z/g(f(X),Y)][X/f(a)][Y/f(f(a))] 3Ausgabe: [Z/g(f(X),Y)][X/f( a)] [Y /f( f(a ))]

    ErsterTerm ZweiterTerm Substitution if#und(name(mein,Z),weiss(Y,Z))

    ?: und(name(X,hase),weiss(nichts,X)) [] 4name(mein,Z)

    ?: name(X,hase) [] 4weiss(Y,Z)

    ?: weiss(nichts,X)mein

    ?: X [] 2Z

    ?: haseweiss(Y,Z)

    ?: weiss(nicht,X)Z

    ?: hase [X/mein] 1weiss(Y,Z)

    ?: weiss(nicht,mein)weiss(Y,hase)

    ?: weiss(nicht,mein) [X/mein][Z/hase] 4Y

    ?: nicht [X/mein][Z/hase] 1hase

    ?: meinhase

    ?: mein [X/mein][Z/hase][Y/nicht] 5Ausgabe: failure

    4.3.2 Resolution

    Die Resolutionin Prologist der Resolutionaussagenlogischer Klauselnin KNF sehrähnlich.Auch inPrologwird positivesundnegativesAuftreteneinerStruktur(damalseineratomarenFormel)gegenein-ander

    ”gek̈urzt“ . Positiv tretenStrukturennuralsKopf in Regelnundin Faktenauf.NegativesAuftreten

    interessiertunsnur in Anfragen.Um resolvierenzukönnen,müssenwir die in FragekommendenStruk-turen unifizieren,also gleichsamdie Regel (den Fakt) und die Anfrage auf einen

    ”gleichen“ Nenner

    bringen.

    Definition 4.3.5 (Resolvierbar, Resolvent) GegebenseieneineAnfrage undeineRegel (oderein Fakt)

    ?- D1, ����� , Dm. und B:- C1, ����� , Cn. �die (ggf. nach UmbenennungvonVariablen)keineVariablengemeinsamhaben.(Ein Fakt wird als eineRegel ohneRumpfbetrachtet, d.h. n � 0.) DiesebeidenKlauselnheissenresolvierbar, wennD1 und Bunifizierbarsind.SeisubderallgemeinsteUnifikatorvonD1 undB. Dannist

    ?- C1 sub, ����� , Cmsub, D2 sub, ����� , Dn sub.derResolventderbeidenFormeln.

    103

  • Washeisstdasim BeispielzuBeginndiesesKapitels?AnfangsstehensichdiefolgendeAnfragebzw. Re-gelgegeben̈uber:

    ?-opa(adam,claus) und opa(X,Y):-vater(X ,Z) ,va te r(Z ,Y) .

    Also,n � 1,m � 2,D1 � opa(adam,claus) , B � opa(X,Y) ,C1 � vater(X,Z) undC2 � vater(Z, Y) .DerallgemeinsteUnifikatorvonopa(adam,claus) undopa(X,Y) ist sub � [X/adam][Y/claus] . Alsoerhaltenwir alsResolventdie Anfrage

    ?- vater(adam,Z); = ?C1 sub

    � vater(Z,claus); = ?C2 sub

    .

    Beachte,dassdie Anfragein diesemFall ausnur einemTerm bestand(n � 1), alsodie TermeD2 �������nichtexistieren,alsoeinfachnichtshintenangeḧangtwird. In dernächstenResolutionunseresBeispielsist diesabernichtmehrso:

    ?-vater(adam,Z),v ate r(Z ,c lau s). und vater(adam,bertold ).

    sollenresolviertwerden.Der Fakt vater(adam,bertold) passt(mit Hilfe derobengenanntenkleinenSyntaẍanderung)durchm � 0 in unserMusterder Resolutionen.Wir habendannalson � 2, m � 0,D1 � vater(adam,Z) , D2 � vater(Z,claus) , B � vater(adam,bertold ) undfertig: keinC1 ������� Cm.DaderallgemeinsteUnifikator sub � [Z/bertold] ist, lautetderResolventzwingend:

    ?- vater(bertold,clau s); = ?D2 sub

    .

    Der Leserüberzeugesichdavon, dassessichauchbeimletztenSchrittunseresBeipielsum einelegaleResolutionhandelt.

    Satz4.3.6 Der ResolventeinerRegel (einesFaktes)undeinerAnfrage ist eineFolgerungausdiesen(imprädikatenlogischenSinne).

    Konkreter:GegebeneineRegel (odereinFakt)B:- C1, ����� , Cm. undeineAnfrage ?- D1, ����� , Dn. Seisubder allgemeinsteUnifikator von B und D1. Dann ist die prädikatenlogische Entsprechung desResol-venten?- C1 sub, ����� , Cmsub, D2 sub, ����� , Dn sub. eineFolgerungausdenprädikatenlogischenEntspre-chungenderRegel undderAnfrage.

    Wie schonin der Aussagenlogikbedeutetdies,dassdie Bildung desResolventeneinealgorithmischeMöglichkeit darstellt,Folgerungeneiner gewissenFormelmengezu generieren.Prolog benutztdieseMöglichkeit, um ausdemProgramm(denRegelnund Fakten)undeinerAnfragedie leereAnfragezufolgern,alsodie Anfragemit

    ”Ja“ zubeantworten.Nur wenndiesnicht geht,wird

    ”Nein“ ausgegeben.

    Beweis: Die Ideeist im Grundedie Gleichewie bei deraussagenlogischenResolution,nur die prädi-katenlogischenEigenheitenwie VariablenundQuantorenmachendasArgumentein wenigtechnischer.Die prädikatenlogischeEntsprechungderRegelundderAnfrageist:

    F � � x1 ����� � xr ��� B ��� C1 �.��������� Cm��*��� D1 �/�������%� Dn �����wobeix1 ��������� xr die in RegelundAnfragevorkommendenVariablensind.DurchdenallgemeinstenUni-fikator werdeneinigedieserVariablendurchandereTermeersetzt.Die Formel,die nachdieserSubsti-tution erhaltenwird, ist eineFolgerung,da lediglich allquantisierteVariablendurcheinenspeziellerenTerm(odereineandereallquantisierteVariable)ersetztwerden.

    F @ � F sub� � x1 ����� � xr ��� Bsub��� C1 sub�.�����1��� Cmsub��*��� D1 sub�/��������� Dn sub���104

  • Sei nun A ein Modell von F sub. Also mussfür alle Einsetzungen,die manfür x1 ��������� xr vornehmenkann, ����� Bsub�CBD�/�E� C1 sub�CBD�F�����G�+��� Cm sub�CB��HI����� D1 sub�CBI�+�E� D2 sub�CBD�F�����G�+��� Dn sub�CBE���wahr sein.Da nun aberBsub � D1 sub, so mussentweder� Bsub�CB oder ��� D1 sub�CB wahr sein.Alsomussmindestenseinerder Ausdr̈ucke ��� C1 sub�J�����K�L� Cm sub�CB und ��� D2 sub�����G�L� Dn sub�CB wahrsein.Dasbedeutetaber, dassdie Formel�

    x1 ����� � xr ����� C1 sub�.�����1��� Cmsub���*��� D2 sub�/��������� Dn sub���von A erfüllt wird. DieseFormelist jedochgenaudie EntsprechungdesResolventen.

    4.3.3 Auswertungsstrategie

    Eigentlichist ja jetzt allesklar. Um für eineAnfragezu beantworten,ob sie ausdemProgrammfolgt,müssenwir nur passendeRegeln und Faktenmit ihr resolvieren.Damit dies immer geht,müssenwirwomöglichimmerwiederVariablenumbenennungenvornehmen(diesgeschiehtin denRegeln,wir habenschongesehen,dassdieskeinenEinflussaufdasProgrammhat).Mit demErgebnis(einerneuenAnfrage)fährtmandanngenausofort. Dasist dertop-down-Strategie im Abschnitt1.21ganzähnlich.

    Wennwir allerdingseinenAlgorithmusschreibenwollen,derunsdieseAufgabeabnimmt(einensoge-nannterProlog–Interpreter),so stossenwir schnelldarauf,dassesimmer nochAuswahlmöglichkeitenzwischenmehrerenAlternativen gebenkannund dassmanmit dieserStrategie in Sackgassenlaufenkann.Wir werdengleichsehen,wie Prologmit diesenProblemenumgeht.

    Betrachtenwir dasProgramm:

    add(a,X,X).add(f(X),Y,f(Z)):- add (X ,Y, Z).

    und die Anfrage ?-add(X,Y,f(f(a))) (”Welchenaẗurlichen Zahlenx und y addierensich zu 2?“ )

    Schonim erstenSchritt kannmandie Anfragemit beidenProgramm–Klauselnresolvieren:NachderResolutionmit add(a,X1,X1) (ersteKlauselnachUmbenennungder Variablen)erḧalt mansofort dieleere Klausel ?-. und die Ergebnis–Substitution[X/a][Y/f(f(a))] , also x � 2 und y � 0. Wennmanjedochmit add(f(X1),Y1,f(Z1 )): -ad d( X1, Y1, Z1) resolviert,so erḧalt mandie neueAnfrage?-add(X1,Y1,f(a)) mit Substitution[X/f(X1)][Y/Y1][Z 1/f (a) ] . FürdieResolutiondieserAnfragegibt eswiederzweiMöglichkeitenundsoweiter. DervollständigeBaumallerMöglichkeitensiehtdannsoaus(manprüfenach,dassalleLösungenfür x � y � 2 dabeisind):

    ?-add(X,Y,f(f(a))).

    ?-. ?-add(X1,Y1,f(a)).

    ?-. ?-add(X2,Y2,a).

    ?-.

    add(a,X1,X1).sub=[X/a][Y/X1][X1/f(f(a)]

    add(f(X1),Y1,f(Z1)):-add(X1,Y1,Z1).sub=[X/f(X1)][Y/Y1][Z1/f(a)]

    add(a,X2,X2).sub=[X1/a][Y1/f(a)][X2/f(a)]

    add(f(X2),Y2,f(Z2)):-add(X2,Y2,Z2).sub=[X1/f(X2)][Y1/Y2][Z2/a]

    add(a,X3,X3).sub=[X2/a][Y2/a][X3/a]

    105

  • Man nenntdiesenBaumaller möglichenResolutionenauchdenAuswertungsbaumdesProgrammsundderAnfrage.Die Auswertungsstrategie siehtnunsoaus,dassimmermit der erstenmöglichenRegel re-solviertwird. PrologwürdealsoX=a undY=f(f(a)) ausgeben(ganzlinker Ast im Auswertungsbaum).Andersgesagt,im Auswertungsbaumwird in jedemSchrittzumamweitestenlinks stehendenKindkno-tenübergegangen.

    Wasaber, wennmandurchAnwendendieserStrategie zu einerAnfragegelangt,die nicht mit”Ja“ zu

    beantwortenist. BeispielsweisekönntemandasProgramm

    vater(artur,beat).vater(artur,christo ph) .vater(christoph,die ter ).opa(X,Y):-vater(X,Z ),v ate r(Z ,Y ).

    nach?-opa(artur,dieter ) befragen.DerAuswertungsbaumsähedannsoaus:

    ?-opa(artur,dieter).

    ?-vater(artur,Y),vater(Y,dieter).

    ?-vater(beat,dieter). ?-vater(christoph,dieter).

    ?-.

    opa(X,Y):-vater(X,Z),vater(Z,Y).sub=[X/artur][Y/dieter]

    vater(artur,beat).sub=[Z/beat]

    vater(artur,christoph).sub=[Z/christoph]

    vater(christoph,dieter).

    PSfragreplacements MUm die Anfragezu beantworten,würdePrologdie opa–Regel anwenden,und dannvor der Aufgabestehen,einenSohnfür artur zufinden,dergleichzeitigVatervon dieter ist. NachderobengenanntenStrategiewird dererstepassendeFaktvater(vater,beat) ausgewählt,dasheisst,beat geraten.DieserWeg entpupptsichaberalsSackgasse,dabeat nicht nachweislichderVatervon dieter ist. Prologtutdanndaseinzige,wasandieserStelleSinnmacht:EsgehteinenSchrittzurück,wo esfalschgeratenhatundversuchtesmit dernächstenanwendbarenRegel. DieserRück–Schrittwird Backtracking genannt.Genaugesagtbedeutetes:WennProlog zueinerAnfrage entwederkeineRegeln undkeineFaktenzumUnifizierenfindetoderalle gefundenenResolventenmit

    ”nicht ableitbar“ zurückgegebenwerden,gibt es

    auch für dieseAnfrage”nicht ableitbar“ zurück. DerganzeAuswertungsalgorithmussiehtsoaus:

    Algorithmus 4.3.7

    Input: Prolog–ProgrammF � K1 K2 ����� Kn, wobeiKi � Bi :- Ci � 1, ����� , Ci � ni . Regeln undFakten,undZielklauselG � ?- A1, ����� , Ak.

    Output: wenndie Zielklauselableitbarist, die Substitutionsubund”Ja“ , sonst

    ”Nein“ .

    Algorithmus:Hauptpr ogramm

    SetzeglobaleVariableerfolg : � falsch.Setzesub: � leereSubstitution.Führedie Prozedurauswerte� G � sub� aus.

    106

  • if erfolg thenSchreibe

    ”Ja“ .

    elseSchreibe

    ”Nein“ .

    EndeHauptpr ogramm.

    Prozedur auswerte(ZielklauselG � ?- D1, ����� , Dm. , Substitutionsub)if G ist die leereAnfrage(d.h.m � 0 undG � ?-. ) then

    Schreibesub.Setzeerfolg : � wahr.

    elseSetzei : � 0.while i N n and not erfolgdo

    Setzei : � i � 1.if O D1 � Bi P ist unifizierbarmit allgemeinstemUnifikator sub�

    (wobeiVariablenin Ki evtl. umbenanntwurden)then

    Führeauswerte(”?- Ci � 1sub� , ����� , Ci � ni sub� , D2sub� , ����� , Dmsub� . “ , subsub� ) aus.

    EndeProzedurauswerte.

    Um denAlgorithmusin aller Tiefe zu erklären,wendenwir unswiederdemBeispielzu (esempfiehltsich, denFlussdesAlgorithmus im Auswertungsbaumobenzu verfolgen):Zu Beginn ist die globaleVariableerfolg auf falsch gesetzt.Die Substitutionsub, in deralle anfallendenErsetzungengesammeltwerden,ist noch leer. Nun wird die Prozedurauswertemit G � ?-opa(artur,diete r) und dieserleerenSubstitutionaufgerufen.DieseZielklauselG ist nicht leer, alsowird in denelse–Teil gesprungen.Die ersteStrukturin der Zielklauselist zugleichauchdie einzige,alsoD1 � opa(artur,dieter) . Inder while–Schleifeist zun̈achstfür i � 1, alsoB1 � vater(artur,beat) . Dies ist naẗurlich nicht mitD1 unifizierbar, alsogehtesgleich weiter mit B2 � vater(artur,christ oph ) . Auch dieseStrukturist nicht mit D1 unifizierbar, also weiter zu B3 und, weil auchnicht unifizierbar, zu B4. Hier werdenwir endlichfündig,derallgemeinsteUnifikator lautetsub� � [X/artur][Y/dieter ] , unddie Prozedurauswertewird nunnocheinmalaufgerufen.Da die Regel K4 � opa(X,Y):-vater(X,Z ), vat er( Z,Y )nur zwei StrukturenC4 � 1 � vater(X,Z) undC4 � 2 � vater(Z,Y) und die AnfrageausserD1 garkeineStrukturenentḧalt, ist die neueZielklausel(derResolvent)gerade

    ?- C4 � 1[X/artur][Y/dieter ] , C4 � 2[X/artur][Y/dieter ] � ?-vater(artur,Z),v ate r(Z ,d iet er) �All diesbringt unsim AuswertungsbaumeineEtagetiefer. Wir habengesehen,dassnacheinanderalleKlauseln(RegelnundFakten)desProlog–Programmsdurchlaufenwerdenundversuchtwird, denerstenRegelkopf oderFakt zu finden,dermit dererstenStrukturderaktuellenZielklauselunifizierbarist. Wirwollenunsnunverdeutlichen,wie esweitergeht.Wiederist dieZielklausel

    G � ?-vater(artur,Z),va te r(Z ,di ete r)nicht leer, sieist abergleichmit demerstenFaktdesProgrammsK1 � vater(artur,beat) unifizierbar.Der allgemeinsteUnifikator ist [Z/beat] . Der Resolvent lautet vater(beat,dieter) , die Prozedurauswertewird erneutaufgerufen.Diesmalist aberwederdieZielklauselleernochgibt eseinenFaktodereineRegel,mit dersieresolvierbarist. Also wird die ProzedurauswerteunverrichteterDingeverlassenund wir sind wieder in der while–Schleifeder ProzedurauswerteeineEtagehöher. Der nächsteFaktK2 � vater(artur,christo ph) ist mit derZielklauselresolvierbar(allg. Unifikator [Z/christoph] ),

    107

  • derResolventlautet?-vater(christoph, die te r) . Die Prozedurauswertewird mit dieserZielklauselundderSubstitutionsub � [X/artur][Y/dieter ][Z /ch ris to ph] aufgerufen.Resolviertwird erstmitdemdrittenFakt vater(christoph,di ete r) .

    Der neueResolvent ist die leereKlausel?-. Dieswird auchim erneutenAufruf auswerteerkannt.DieSubstitutionwird ausgegeben.(Prologschreibtnur die Substitutionen,die schonin derurspr̈unglichenZielklauselvorkamen,in unseremFall wird alsonichtsausgegeben.Esist aberprinzipiell möglich,dieSubstitutionenaller Variablenauszuschreiben.)Nun wird die globaleVariableauf wahr gesetztunddie Prozedurverlassen.Wieder sind wir in der while–Schleifeeine Etagehöher, doch not erfolg �falsch, alsowird sieverlassenundnocheineEtagehöhergesprungen.Dasgehtsoweiter, manhangeltsich denAuswertungsbaumbis zum Hauptprogrammhoch.Letztendlichwird erfolg getestetund

    ”Ja“

    ausgegeben.

    Wir wollen noch einmal die ArbeitsweisedesAlgorithmus zusammenfassen:Der Auswertungsbaumwird nacheinerleerenKlauseldurchsucht,dabeiwird immerdie erstepassendeProgrammklauselzumresolvierengesuchtundmit demResolventenweitergemacht.WennaneinerStellekeineProgrammklau-sel zum resolvierengefundenwerdenkann,dannwird zur aufrufendenProzedurauswertegesprungenunddortdernächstepassendeResolventgesucht.WennaneinerStelledie leereAnfragegefundenwird,gibt Prologdie aktuelleSubstitutionausundhangeltsichdenBaumbis ganzandie Wurzel,dasHaupt-programm,hochundgibt

    ”Ja“ aus.WenndiesniederFall ist, aberderBaumtrotzdemganzdurchlaufen

    wurde,dannist erfolgnachwie vor falsch, alsogibt Prolog”Nein“ aus,die Anfrageist nicht ableitbar.

    Um sichdie AuswertungeinerAnfragekurz zu verdeutlichen,kannmanauchlediglich die Aufrufe derProzedurauswerteincl. deraktuellenZielklauselundderaktuellenSubstitutionnotieren.Die Tiefe derEinrückungbeschreibtdabeidieTiefedesAuswertungsbaums.

    auswerte(?-opa(artur,diet er) , [] )auswerte(?-vater(artur,Z), vat er (Z, die ter ) , [X/artur][Y/dieter] )

    auswerte(?-vater(beat,diet er) , [X/artur][Y/dieter ][Z /be at ] )auswerte(?-vater(christoph ,di ete r) , [X/artur][Y/dieter] [Z /ch ris top h] )

    auswerte(?-. , [X/artur][Y/dieter] [Z/ chr is top h] )

    108

  • 4.4 Programmieren in reinemProlog

    Die beste(und nachMeinungder Autoreneinzig richtige und gründliche)Art und Weise,Prologzulernen,ist es,vieleBeispielezu rechnen.In diesemKapitel wollenwir eineersteAnleitungdazugeben,wie manProlog–Programmeverfasst.

    Dabeiwird auchein neuesDenken überPrologeineRolle spielen:einedochwiedereherprozeduraleSichtweise.Ab einembestimmtenPunktbeginnt man,die Arbeitsweiseder Auswertungsstrategie vonPrologsosehrauszunutzen,dassjedeAbweichungvon dieserStrategie zu einemunsinnigenErgebnisführenwürde.Hat manbeispielsweiseeineRegel A:- B1, ����� , Bn gegeben,so kannmandiesauchals”Um (Prozedur)A erfolgreichabzuarbeiten,müssenwir erstB1 ��������� Bn in genaudieserReihenfolgeab-

    arbeiten“ . KommtmandannaneinerStellezur Anfrage?- A, D2, ����� , Dm, soheisstdas”ArbeitezuerstA ab,dannD2 ��������� Dm in dieserReihenfolge“ . Die zu unifizierendenVariablenkönnendannwie Ein-gabezu einerProzedurwirken. Im Unterschiedzu wirklich prozeduralenProgrammiersprachenhabenaberdieseVariablenkeinenTyp. Siekönnenauch,einmalunifiziert,nichtnachtr̈aglichgëandertwerden.DieseSichtweisesoll GegenstanddernächstendreiAbschnittesein.

    4.4.1 Rekursion mit Verwandtschaftsbeziehungen

    Eingangswurdeschonerwähnt,dassdasKonzeptder RekursioneineeminenteRolle bei der Prolog–Programmierungspielt.Wir wollen hier einigekleineBeispielemit Verwandtschaftsbeziehungen brin-gen.

    Es sei eine Mengevon Vaterschaftsbeziehungen ähnlich wie im Eingangsbeispielin diesemKapitelgegeben.Ein VorfahrX einesMenschenY seieinMensch,derdirektdurchwiederholteVaterbeziehungenmit Y verwandtist.

    Um diesrekursiv zu beschreiben,ben̈otigenwir einenRekursionsanfangund einenRekursionsschritt.Der Rekursionsanfang ist ein Basisfall, wo die Lösungder Anfragesehreinfach ist. Der Rekursions-schritt sollte von einerAnfrageauf eineneueAnfrageführen,die näheram Rekursionsanfang (wenndie Anfrageableitbarist) oderderNichtunifizierbarkeit (wennnicht ableitbar)ist. Im Vorfahrenbeispielkannmansagen,dass,X klarerweisederVorfahrvon Y ist, wennX derVatervon Y ist. In Prologwürdemanalsovorfahr(X,Y):-vate r(X ,Y) schreiben.

    DieserRekursionsanfangfängtnurvorfahr –Beziehungenauf,wo dieVaterschaftskettezwischenX undY geradeeinslangist. DerRekursionsschrittsoll dieseKetteum einsverkürzen.Betrachtedie Regel:

    vorfahr(X,Y):-vater( X, Z), vor fah r( Z,Y ).

    Der Lesersollte jetzt schonerkennen,wassie bedeutet:”X ist ein Vorfahr von Y, wenneseinenMen-

    schenZ gibt, dessenVaterX ist undderselberein Vorfahr von Y ist.“ Dies ist offensichtlichwahr. WiedieseBedingungdieKettevonVaterschaftsbeziehungen verkürzenkann,soll amBeispieldesfolgendenProgrammsgezeigtwerden:

    vater(a,b).vater(b,c).vater(b,d).vater(d,e).vorfahr(X,Y):-vater (X, Y).vorfahr(X,Y):-vater (X, Z), vo rfa hr( Z,Y ).

    109

  • Die Anfragesoll ?-vorfahr(a,e). lauten.Die Auswertungsstrategie ruft die Prozedurauswertemitden folgendenAnfragenauf. Die Darstellungals Baum soll verdeutlichen,von welchemAufruf derProzedurauswertedieseerneutaufgerufenwird. Der Baumist alsogleichsamder Auswertungsbaum,abgeschnittenanderStelle,wo die leereAnfragegefundenwird.

    ?-vorfahr(a,e).

    ?-vater(a,Z1),vorfahr(Z1,e).

    ?-vorfahr(b,e).

    ?-vater(b,Z2),vorfahr(Z2,e).

    ?-vorfahr(c,e).

    ?-vater(c,e).

    ?-vater(c,Z3),vorfahr(Z3,e).

    ?-vorfahr(d,e).

    ?-vater(d,e).

    ?-.

    ?-vater(a,e).

    ?-vater(b,e).

    PSfragreplacements

    MMM

    M

    M

    Esist aberauchwichtig, dassein Pr̈adikatnicht”Ja“ antwortet,wenneseigentlich

    ”Nein“ sagensollte.

    Für unserenFall könntenwir nach?-vorfahr(c,e) fragen.Man erḧalt folgendenAuswertungsbaum:

    ?-vorfahr(c,e).

    ?-vater(c,Z1),vorfahr(Z1,e).

    ?-vater(c,e).PSfragreplacementsM

    MMWir wollen nun zeigen,dassessehrdaraufankommt, in welcherReihenfolgewir die Hypothesenei-ner Regel schreiben.Wennwir die letzteZeile durch vorfahr(X,Y):-vor fah r(Z ,Y) ,v ate r(X ,Z) .ersetzen,soergibt sichbei derAnfrage?-vorfahr(c,e) folgenderAuswertungsbaum:

    ?-vorfahr(c,e).

    ?-vorfahr(Z1,e),vater(c,Z1).

    ?-vater(c,e).

    ?-vater(Z1,c),vater(c,Z1).

    ?-vater(c,b).

    ?-vater(c,e).

    ?-vorfahr(Z2,e),vater(Z1,Z2),vater(c,Z1).

    ?-vorfahr(Z3,e),vater(Z2,Z3),vater(Z1,Z2),vater(c,Z1).

    PSfragreplacements

    M MM

    M

    Es ist schonnachwenigenSchrittenersichtlich,dassderAuswertungsbaumunendlichgrosswird, undderAuswertungsalgorithmusin eineunendlicheRekursionläuft. Und allesnur wegenfalscherReihen-folge.

    110

  • Eskommtauchvor, dassdieReihenfolgederKlauselnim ProgrammeineRollespielt(naẗurlich nurvonKlauselnmit gleichemführendenAtom im Kopf). Ein Beispielist dasfolgendeProgramm:

    verheiratet(gabi,k lau s).verheiratet(X,Y):- ver hei ra tet (Y, X).

    Die Regel in derzweitenZeilesoll bewirken,dassdieAnfrage?-verheiratet(klaus, gabi) trotzdemzu

    ”Ja“ evaluiert(Verheiratetseinist einebeiderseitigeAngelegenheit).Unddasklapptauchsehrgut:

    ?-verheiratet(klaus,gabi).

    ?-.

    ?-verheiratet(gabi,klaus).

    Beim zweitenAufruf von auswertewird ?-verheiratet(gabi ,kl aus) mit dem Fakt in der erstenZeile resolviert.Übrig bleibtdie leereAnfrage.VertauschtmanjedochdieersteunddiezweiteZeiledesProgramms,soergibt sichfolgenderAuswertungsbaum:

    ?-verheiratet(klaus,gabi).

    ?-verheiratet(gabi,klaus).

    ?-verheiratet(gabi,klaus).

    ?-verheiratet(klaus,gabi).

    Eswird in jedemAufruf die Anfragemit derRegel resolviert,wasdie gleicheAnfragemit vertauschtenArgumentenzur Folgehat.Diesbringtunswiederin eineendloseRekursion.

    Eswird langsamklar, dassnaivesÜbersetzeneinerprädikatenlogischenRegel in Prolog–KlauselnnichtimmerzumZiel führt.MansolltesichbeimProgrammierenin PrologstetsvonderLauffähigkeit in allenSituationen̈uberzeugen.Dafür solltenfür jedeRegel stetseinige(auchunwahrscheinlicherscheinende)Anfragenim Kopf (oderamComputer)durchgetestetwerden.

    4.4.2 Arithmetik

    Wir hattenschondieAddition in naẗurlichenZahlenmit Hilfe derfolgendenbeidenKlauselnmodelliert:

    add(a,X,X).add(f(X),Y,f(Z)): -ad d(X ,Y, Z) .

    DiesebeidenKlauselnverdeutlichensehrscḧon dasPrinzipderRekursion:die ersteist derRekursions-anfang,ein einfacherBasisfall (0 � x � x), unddie zweiteist derRekursionsschritt,dereinenicht schondemRekursionsanfangerliegendeAnfrageeinfachermachensoll. Beispiel:x � 2 � 3.

    ?-add(f(f(a)),f(f(f(a))),X).

    ?-add(a,f(f(f(a))),Z2).

    ?-.

    ?-add(f(a),f(f(f(a))),Z1). [X/f(Z1)]

    [X/f(Z1)][Z1/f(Z2)]

    [X/f(Z1)][Z1/f(Z2)][Z2/f(f(f(a)))]

    111

  • HinterdenaktuellenAnfragenhabenwir immerdie für die VariableX wesentlichenSubstitutionenfest-gehalten.Esergibt sichX � f(f(f(f(f(a))))) , wasderrichtigenAntwort 5 entspricht.DochdiesebeidenKlauselnkönnenauchsubtrahieren:?-add(X,f(f(a)),f(f (f (f( a)) ))) .

    ?-add(X,f(f(a)),f(f(f(f(a))))).

    ?-add(X2,f(f(a)),f(f(a))).

    ?-.

    ?-add(X1,f(f(a)),f(f(f(a)))). [X/f(X1)]

    [X/f(X1)][X1/f(X2)]

    [X/f(Z1)][Z1/f(Z2)][Z2/a]

    Auchhierwird zun̈achstzweimalderRekursionsschrittunddannderRekursionsanfangzumresolvierenverwendet.Wennwir in einemProlog–Programmein Pr̈adikatsubtract benutzenwollen, so könnenwir esunsdemnachdurch

    subtract(X,Y,Z):- add (Y, Z,X ).

    definieren.Bei einemAufruf der Klausel?-subtract(f(f(f(f(a )) )), f(f (a) ), X) wird sich Ähli-chesereignenwie zuvor (nachpr̈ufen!).

    NachAddition und Subtraktionist naẗurlich die Multiplikation als nächstesan der Reihe.Wir hattenim ZugederModellierungdernaẗurlichenZahlenin derPr̈adikatenlogikschongesehen,welchebeidenRegeln gen̈ugen,um die Multiplikation vollständig festzulegen: 0 Q x � 0 und � x � 1� y � xy � y. Dieerstereist wiederderleichteRekursionsanfang:mult(a,X,a). Für diezweitemüssenwir unseinweniganstrengen,da wir kein Gleichpr̈adikat haben.NichtsdestowenigermüssengleicheVariablenin einerKlauselauchnach SubstitutionendengleichenWert haben.Wir werdensehen,dassdie folgendeRegeldasGewünschteleistet:

    mult(f(X),Y,Z):-mul t(X ,Y, W),ad d(W,Y, Z) .

    (Um � x � 1� y zu berechnen,errechnezun̈achstw � xy, dasErgebnisist dannw � y. Wiederist dasEr-rechnenvon WeinfacheralsdasErrechnenvon Z, da ja f(X) um einskleiner ist alsX. JedesAnwendendesRekursionsschritteswird unsdemRekursionsanfangeinenSchritt näherbringen.)Hier werdendieAuswertungsb̈aumeschonbei kleinenAnfragenunübersichtlich.Man solltedaherzur Probenicht wilddrauflosrechnen,sondernvielmehrversuchen,zu verstehen,wie sich dieseRegeln in denverschiede-nenvorstellbarenFällen verhalten:auf die Anfrage?-mult(f(f(f(a))) ,f( f(a )) ,X) wird zun̈achstderRekursionsschrittdesmult –Pr̈adikatsverwendet.Diesergibt wiedereineAnfragemit mult alser-stenTeil. Allerdings ist dessenerstesArgumentnur noch f(f(a)) . In dieserArt und Weisewird derRekursionsschrittnochzweimalangewendet,bis die Anfragesoaussieht:

    ?-mult(a,f(f(a)), W3),ad d( W3,f(f (a) ), W2),ad d(W2, f(f (a) ),W 1) ,ad d(W1,f (f (a) ),X ).

    Nunwird derRekursionsanfangdesmult –Pr̈adikatsverwendet,esbleibendiedreiadd–Pr̈adikateübrig.Dochwir habenschongesehen,dassdiesesehrgut zumAddierentaugen.Da mehrereAnfragenimmervon vorne abgearbeitetwerden,eine nachder anderen,kommt nacheinanderW3 � a, W2 � f(f(a)) ,W1 � f(f(f(f(a)))) undX � f(f(f(f(f(f(a)))) )) (d.h.6) heraus.Wichtig für die Programmierungmit Zahlensindnaẗurlich Vergleiche.Wir wollen ein kleiner –Pr̈adi-kat definieren.Wiederhat derRekursionsanfang etwasmit der Null und der Rekursionsschrittmit derNachfolgerfunktionzu tun:

    kleiner(a,f(X)).kleiner(f(X),f(Y) ):- kle in er( X,Y ).

    112

  • DerLesersolltefür sichselbstübersetzen,wasdieseKlauselnbedeuten.Wir wollenunsanschauen,wasPrologaufdieAnfrage?-kleiner(f(f(a)), f(f (f( a)) )) . hin tut:

    ?-kleiner(f(f(a)),f(f(f(a)))).

    ?-kleiner(f(a),f(f(a))).

    ?-.

    ?-kleiner(a),f(a)).

    Sehrgut:”Yes“ . WaspassiertjedochbeiderAnfrage?-kleiner(f(f(f(f(a ))) ),f (f (a) )) ?

    ?-kleiner(f(f(f(f(a)))),f(f(a))).

    ?-kleiner(f(f(f(a))),f(a)).

    ?-kleiner(f(f(a)),a).

    DerAuswertungsbaumist vollständig,unddochwurdekeineleereAnfragegefunden,derAuswertungs-algorithmusmussdaher

    ”Nein“ ausgeben.Diesist naẗurlich auchrichtig, daebennicht 4 N 2.

    Basierendauf diesenBasispr̈adikatenkannmanweiterePr̈adikatedefinieren.LetztesBeispielan die-serStelle sollte dasPr̈adikatexp(N,M,X) stehen,welchesgenaudannwahr wird, wenn nm � x. DerRekursionsschrittsolltedenExponentenkleinermachen:nmR 1 � nm Q n, also

    exp(N,f(M),X):-exp(N ,M,Y) ,mu lt( Y, N,X ).

    Der Rekursionsanfangist naẗurlich n0 � 1. Dochstimmtdiesin jedemFall?Wasist, wennn � 0. Dannist für m S 1 geradenm � 0m � 0, diePotenz00 ist nichteinmaldefiniert.DerAusweg ausdieserMisereist, denRekursionsanfangnur für n T 0 zudefinieren:

    exp(f(N),a,f(a)).

    d.h. � n � 1� 0 � 1 für alle n. Für n � 0 habenwir dannnochdenFakt:exp(a,f(M),a).

    Der Lesersollte an dieserStelle versuchen,weiterePr̈adikatezu definieren,die auf add , mult undkleiner basieren.DenkbarwärenzumBeispieldieFakulẗat fakultaet(N,X) (x � n!) oderdasModulo–Pr̈adikatmod(N,M,R) (r ist derRestbei ganzzahligerDivision von n durchm) oderdie n–teFibonacci–Zahl fib(N,X) (sie ist von Natur ausschonrekursiv definiert: f0 � f1 � 1, fnR 2 � fnR 1 � fn für allen).

    4.4.3 Listen

    Listensindin PrologeinessentiellesWerkzeug.WeitereDatenstrukturenwie Zeichenketten,BäumeundStackswerdenalle durch Listen modelliert.Es gibt zwei Konstruktionselemente: die leereListe nil(Konstante)und denListenkonstruktorcons (zweistelligeFunktion).DieserListenkonstruktorhat alserstenEintragdasersteListenelement(dersogenanntehead) undalszweitenEintragdengesamtenRestder Liste (der sogenanntetail). Es ist essentiellzu beachten,dassessich bei nil und cons nicht umPr̈adikatehandelt.Vielmehrwerdendiesein Pr̈adikate(wie append – hintenanḧangen,reverse – Listeumkehren,usw.) eingesetzt.

    113

  • Ein Beispiel:Die Liste,die ausdenElementen1, 2 und3 besteht,wird in Prologals

    cons(f(a),cons(f(f (a )), con s(f (f (f( a)) ),n il )))

    kodiert.Wir wollenunsdiesesKonstruktvoninnennachaussenzerpfl̈ucken.Ganzinnenstehtcons(f(f(f(a))),ni l) .Dies ist laut Vereinbarungdie Liste, die als erstesElementdie 3 und als Restder Liste die leereLi-stehat. Demnachist diesdie Liste mit einemeinzigen Element, nämlich 3. Nun wird auchklar, dasscons(f(f(a)),cons(f (f( f(a ))) ,n il) ) die Liste mit 2 als erstemElementist, derenRestlistenurausdemElement3 besteht.Wir schreibendiesals [2,3] . Wennwir vor dieseListe nochdie 1 hängen,sokommtdieListe [1,2,3] heraus.

    Warumso umsẗandlich?Prologhat eineeingebauteVorliebefür Rekursionen.Die Listendefinitionistnun auchschonpotentiell rekursiv. Ein Pr̈adikat list , welcheswahr wird, wenn dasArgumenteineListe ist, könntenämlichwie folgt definiertwerden:

    list(nil).list(cons(X,Xs)):-li st (Xs ).

    Die leereListe ist eineListeundcons(X,Xs) ist eineListe,wennXs schoneineListe ist. Herrlichrekur-siv. DerAbleitungsbaumderAnfrage?-list(cons(f(a),c ons (f( f( a)) ,ni l)) ) spiegeltwieder, wiezun̈achstzweimalderRekursionsschrittunddannderRekursionsanfangangewendetwerden,umaufdieAntwort

    ”Ja“ zu kommen:

    ?-list(cons(f(a),cons(f(f(a))). list(cons(X1,Xs1)):-list(Xs1).

    ?-list(cons(f(f(a)),nil). list(cons(X2,Xs2)):-list(Xs2).

    ?-list(nil). list(nil).

    [X1/f(a)][Xs1/cons(f(f(a)),nil)]

    [X2/f(f(a))][Xs2/nil]

    ?-.

    EineVerkettungvon Listenwird durchdasappend –Pr̈adikaterreicht:

    append(nil,X,X).append(cons(X,Xs), Ys, co ns( Z,Z s)) :- append(Xs ,Y s,Z s).

    ”EineListe,die aneineleereListe angeḧangtwird, bleibt gleich.“ und

    ”WennXs undYs zusammenZs

    ergeben,soergibt dieVerkettungvoncons(X,Xs) undYs geradecons(X,Zs) “ . AuchhierspieltwiederdieRekursivität dieentscheidendenRolle.Um zweiListenzuverketten,wird zun̈achstdasersteElementdererstenListeabgenommenundrekursiv dieRestlistenverkettet.An dieErgebnislistewird dannvornedasabgenommeneElementwiederangeḧangt.DerRekursionsanfangtritt dannein,wenndieersteListeleerist. Esfolgt ein Beispielauswertungsbaum zur VerkettungderListen [a,b] und [b,c] :

    ?-append(cons(a,cons(b,nil)),cons(b,cons(c,nil)),X).

    ?-append(nil,cons(b,cons(c,nil)),Z2).

    ?-.

    ?-append(cons(b,nil),cons(b,cons(c,nil)),Z1). [X/cons(a,Z1)]

    [Z1/cons(b,Z2)]

    [Z2/cons(b,cons(c,nil))]

    114

  • DerWertvonX ist nachderAusführungallerSubstitutionencons(a,cons(b,cons( b,c ons(c ,ni l)) )) �[a,b,b,c] .

    DochdiesesPr̈adikatkannnochmehr. Wir könnenfragen,ob eineListe derBeginn eineranderenListeist:

    ?-append(cons(a,cons(b,nil)),X,cons(a,cons(b,cons(c,nil)))).

    ?-append(nil,X,cons(c,nil)).

    ?-.

    ?-append(cons(b,nil),X,cons(b,cons(c,nil))).

    [X/cons(c,nil)]

    oderauch,ob eineListedasEndeeineranderenListe ist:

    ?-append(X,cons(c,nil),cons(a,cons(b,cons(c,nil)))).

    ?-append(X2,cons(c,nil),cons(c,nil)).

    ?-.

    ?-append(X1,cons(c,nil),cons(b,cons(c,nil))). [X/cons(a,X1)]

    [X1/cons(b,X2)]

    [X2/nil]

    DarummachtesauchSinn,die Pr̈adikatepr äfix undsuffix wie folgt zu definieren:

    pr äfix(L1,L2):-appe nd( L1,X, L2) .suffix(L1,L2):-appe nd( X, L1, L2) .

    4.5 PrologCrashkurs

    Dasvon unsbeschriebenereineProlog(pure prolog) ist theoretischeinevoll entwickelteProgrammier-sprache,jedochfür praktischeZwecke zu unhandlichundlangsam.Zum Beispielben̈otigt die AdditionzweierZahlenx undy proportionalzu x viele Programmschritte.Dies ist inakzeptabel,daeseigentlichviel schnellerginge.Wir werdenvorstellen,wie eineechteProlog–Implementierungdie Effizienzstei-gerungerreicht.Ausserdemwerdenwir sogenannteSeiteneffekte vorstellen.Dies sind Pr̈adikate,die,wennsie resolviertwerdensollen,Eingabenvon derTastaturoderdemFilesystembzw. AusgabenaufdenBildschirmundauf dasFilesystemvornehmen.Wir werdendenCut kennenlernenundmit ihm einnot –Pr̈adikatdefinieren.AusserdemwerdenunssogenanntemetalogischePr̈adikateinteressieren.

    4.5.1 Prologam Computer

    WennmanPrologaufruft, zum BeispielSWI–Prologmit Hilfe desKommandospl , so bekommt maneinenPrompt,nämlich das?- , und Prolog wartet auf eine Anfrage. Anfangsist noch kein Prolog–Programmgeladen,wir denQuellcodevorherin irgendeinemFile (z.B. beispiel.pl ) gespeichertha-ben.Man kompiliert diesesFile so:

    ?-consult(beispiel) .

    (Das ?- mussnicht mehr eingegebenwerden,der Punkt ist aberessentiell.)Angenommen,im Filebeispiel.pl stehendie folgendenRegeln:

    add(a,X,X).add(f(X),Y,f(Z)):- add (X ,Y, Z).

    115

  • Wennwir die Anfrage?-add(f(f(a)),f(f(f (a) )) ,X) stellen,dashabenwir schongesehen,kommtdie Antwort X=f(f(f(f(f(a))))) . Wir quittierendie Antwort mit dem Drücken der EntertasteundPrologsagt

    ”Yes“ .

    Auf die Anfrage?-add(X,Y,f(f(a))) antwortetPrologmit X = a, Y = f(f(a)) . Aber damit ist derAuswertungsbaumgarnicht ganzabgesucht,sondernnur bis zumerstenAuffindender leerenKlausel.Esgibt nochzwei weitereWege(sieheAbschnitt4.3.3).Um diesezu finden,drücken wir dasSemiko-lon. Prologantwortetmit X = f(a) , Y = f(a) . Wasist passiert?Da derAuswertungsbaumnochnichtvollständigabgesuchtwar, stopptedie InferenzmaschinedenAuswertungsalgorithmusbeimAuffindenderleerenKlausel,abernachEingabedesSemikolonswurdedieglobaleVariableerfolgwiederauf falsegesetzt.Damit ging die Sucheim Auswertungsbaumweiterundwir kamenzur zweitenLösung.Noch-maligesDrücken desSemikolonsführt zur dritten Lösung.Nun ist der Auswertungsbaumvollständigabgesucht.NachnochmaligemDrückendesSemikolonsmussPrologmit

    ”No“ antworten:Nein,esgibt

    keineweiterenLösungen.Auf dieseArt ist esunsmöglich, dengesamtenAuswertungsbaumabzusu-chen,selbst,wennwir schoneineleereKlauselgefundenhaben.Selbstversẗandlichstehtesjedesmal,wennPrologauf eineQuittierungwartet,frei, Enterzu drücken und die Abarbeitungder Anfragezubeenden.

    4.5.2 Der Unifikationsoperator =

    Die Syntaxvon Prologwird erweitert:WennA undB Termesind,sosoll auchA=B eineStruktursein.DieseStrukturbedeutet,dassA undB unifizierbarsind.Wenndie Inferenzmaschineauf dieseStrukturalsZielklauselstösst,sowird genaudie Unifikation ausgef̈uhrt. Man kannsichdiesenOperatorwie einPr̈adikatunif vorstellen,welcheseinfachals

    unif(X,X).

    definiertist.

    4.5.3 Arithmetik

    Bisherwarendie Argumentevon Faktenund Regelnnur Variablenund Strukturen.Doch auchZahlensindmöglich.SyntaktischgeltensiealsAtome.Wir werdenjedochgleichsehen,wiemanmit ihnenrech-net.Dafür gibt esdie arithmetischenOperatoren:X+Y, X-Y , -X , X*Y, X/Y , X mod Y, abs(X) , sqrt(X) ,sin(X) , cos(X) etc. All dieseAusdr̈ucke geltenjetzt auchals Strukturen.Man mussaberbeachten,dassdieseAusdr̈uckenichtsofortevaluiertwerden,sondernalsAusdr̈uckestehenbleiben.Diesbedeutetbeispielsweise,dassdieAnfrage?-X=3+4 die Antwort X=3+4 undnichtetwa X=7 ergibt. Zur Evaluationgibt esdenis –Operator:Die Anfrage?-X is 3+4*2 ergibt geradeX=11. Erstwennin einerKlauselderis –Operatorerreichtwird, werdendie arithmetischenOperationenausgef̈uhrt. Dies ist von Bedeutung,wennmanzumBeispieleinPr̈adikatzur BerechnungderFakulẗat n! � 1 Q 2 Q�Q�Q n definierenwill:

    fak(0,1).fak(N,X):-N’ is N-1, fak(N’,X’), X is X’*N.

    Schauenwir unsdenAuswertungsbaumzur Anfrage?-fak(2,X) an:

    116

  • ?-fak(2,X).

    ?-fak(1,X1), X is X1*2.

    ?-N2 is 1-1, fak(N2,X2), X1 is X2*1, X is X1*2.

    ?-N1 is 2-1, fak(N1,X1), X is X1*2.

    [N1/1]

    [N2/0]

    [X2/0]

    ?-fak(0,X2), X1 is X2*1, X is X1*2.

    ?-X1 is 1*1, X is X1*2.

    ?-X is 1*2.

    ?-.

    [X1/1]

    [X/2]

    An diesemBeispielsiehtmansehrscḧon, dassdie arithmetischenOperatorenzun̈achstnicht, sondernerstbeim is –Operator, ausgerechnetwerden.Man darf zum Beispiel auchnicht denFehlermachen,stattderobigenRegeldieRegel fak(N,X):-fak(N-1, X’ ),X is X’*N. zuverwenden.DasN-1 würdenichtevaluiertwerdenunddie Auswertungin eineEndlosrekursionlaufen:

    ?-fak(2,X).

    ?-fak(2-1-1,X1), X is X1*2.

    ?-fak(2-1-1-1,X1), X is X1*2.

    ?-fak(2-1,X1), X is X1*2.

    ?-fak(2-1-1-1-1,X1), X is X1*2.

    AucharithmetischeVergleichewie X>Y, X=Y, X=

  • desadd–Pr̈adikatesfür wirkliche Zahlen:

    add(X,Y,Z):-nonvar (X) ,no nva r( Y), Z is X+Y.add(X,Y,Z):-nonvar (X) ,no nva r( Z), Y is Z-X.add(X,Y,Z):-nonvar (Y) ,no nva r( Z), X is Z-Y.

    Nunkönnenwir add wiederzumBerechnenvon?-add(f(a),f(f(a) ),Z ) (ersteRegel)oderfür ?-add(X,f(a),f(f(f( f( a)) )))(dritteRegel)verwenden:

    ?-add(X,1,4).

    ?-nonvar(X),nonvar(4),1 is 4-X.

    ?-nonvar(1),nonvar(4),X is 4-1.

    ?-nonvar(X),nonvar(1),4 is X+1.

    ?-nonvar(4),X is 4-1.

    ?-X is 4-1.

    ?-. [X/3]

    PSfragreplacements

    MM

    WeiteremetalogischePr̈adikatesind atom(X) und compound(X) , welcheswahr werden,wenn X einAtom bzw. ein zusammengesetzterTerm ist. DasPr̈adikat functor(Term,F,N) gibt denNamendesführendenAtoms und die Stelligkeit. Die Anfrage ?-functor(add(a,X,X ),F ,N ) würde mit F=add ,N=3,

    ”Yes“ antworten.Schliesslichgibt dasPr̈adikatarg(N,Term,Arg) dasnte ArgumentdesTerms

    Term, also?-arg(2,add(f(a),X, f(X )), Ar g) ergibt Arg=X .

    4.5.7 Cut und Negation

    Der Cut ! ist ein Pr̈adikat,welchesgewisseÄstedesAuswertungsbaums”abschneidet“ . Er ist äusserst

    für dasVerhindernvon unn̈utzenSuchpfadenim Auswertungsbaum.Dabeikanner sogarvor Endlosre-kursionenscḧutzen.Ausserdemwird erzur Implementationeinesnot –Operatorsben̈utzt.

    Wird im ZugedesAuswertungsalgorithmusmit einerRegel der Form C � A:- B1, ����� , Bk � !, Bk R 1 �������resolviert,sover̈andertsichanderAuswertungnichts,solangenichtderCuterreichtwird. Wennerabererreichtwird, sagenwir in deraktuellenAnfrage?-!, C1, ����� , Cl , sowirkt er wie ein Pr̈adikat,welchesimmer wahr ist. Wenn allerdingsdie neueAnfrage ?- C1, ����� , Cl erfolglos zurückkommt, so passiertetwasNeues:Es wird in einemSprungzu der Anfragezurückgesprungen,die mit C resolvierthatte.SämtlicheMöglichkeiten,andereRegelnoderFaktenfür A � B1 ��������� Bk zufinden,werdenmissachtet.Diesbedeutetmit anderenWorten,dasssämtlicheÄstedesAuswertungsbaumes,die andereAlternativen füreinederStrukturenA � B1 �������1� Bk enthaltenhätten,abgeschnittenwurden.Wir wolleneinBeispielgeben.DochdazunocheineVorbemerkungzumebenfalls eingebautenPr̈adikatfail . Diesesist immer falsch(eskommtnie in einemFakt odereinemRegelkopf vor). BetrachtenwirdasfolgendeProgramm1:

    lebewesen(rose).lebewesen(hund).blume(rose).tier(X):-blume(X),! ,f ail .tier(X):-lebewesen( X) .

    Auf die Anfrage?-tier(hund) passiertnichtsBesonderes.1aus:KleineBüning/Schmittgen:Prolog,B.G.TeubnerStuttgart,1986.

    118

  • ?-tier(hund).

    ?-lebewesen(hund).

    ?-blume(hund),!,fail.

    ?-.

    DerCutwird nichterreicht,dablume(hund) mit keinemFaktoderRegelkopf unifizierbarist. Also wirddieAlternativregel tier(X):-lebewesen( X) angewendetundführt zumErfolg: Ein Hundist ein Tier.

    Bei derAnfrage?-tier(rose) ist die Situationjedochschonganzanders:

    ?-tier(rose).

    ?-!,fail.

    ?-blume(rose),!,fail.

    ?-fail.

    Die Anfragewird mit dererstentier –Regel resolviert,dieseihrerseitsmit blume(rose) . Nun kommtderCut andie Reihe.Da er wie ein immerwahresPr̈adikatwirkt, bleibt nachderResolutionnur nochfail übrig, waskeinenErfolg bringt. Nun würdeeigentlichdasBacktrackingkommen,im Auswer-tungsbaumwürdenwir und einenSchritt nachdemanderennachobenhangeln.Doch dieswird durchdenCutverhindert:ermacht,dasswir unswederfür blume(rose) nochfür tier(rose) andereRegelnoderFaktensuchendürfen.DeshalbspringtPrologsofortausderoberstenProzedurauswerteherausundmeldet

    ”No“ .

    DasProgrammbedeutetalso,”Ein Tier ist ein Lebewesen,welcheskeineBlume ist“ . Dies gleicht der

    ImplementationeinerNegation,wie sie in reinemProlognicht möglich ist. Ein richtiger Operatornotist auchTeil desLieferumfangsvon Prolog:

    not(X):-call(X),!, fa il.not(X).

    Die Klauselcall(X) funktioniertso,dass,wennX mit einerStrukturunifiziert ist, dieseversuchtwirdzu evaluieren.Wenndiesgelingt,so ist auchcall(X) erfolgreichundumgekehrt.Die Funktionsweisevon not ist dannganzim GeistdesletztenProgramms.

    119

  • 4.6 Praxisbeispiel:Registermaschine

    Um zu zeigen,dassmanmit Prologrelativ einfachund übersichtlichprogrammierenkann,seihier einBeispielprogrammgegeben.EsliesteinenDateinamenein,dereinRegistermaschinenquelltext im SinnevonKapitel3 entḧalt. DannwerdendieAnzahln derzusetzendenRegisterunddieRegisterR0 ��������� Rn W 1eingelesen.DasProgrammist noch,obschonlauffähig, in der Entwicklungsphaseund daherschlechtdokumentiert.

    Ein Beispielfür ein Registermaschinenprogramm ist dasfür die Fakulẗat:

    0:R3=R0+R11:R3=R3*R22:R2=R2-R13:IF R2=0 GOTO54:GOTO 15:STOP

    Ein Testlaufkönntedannsoaussehen(dasRegistermaschinenprogrammist im File beispiel .

    ?- consult(registermas chi ne) .registermaschine compiled, 0.01 sec, 14,076 bytes.

    Yes?- main.Geben Sie den Filenamen der Datei ein: beispiel0:R3=R0+R11:R3=R3*R22:R2=R2-R13:IF R2=0 GOTO54:GOTO 15:STOPWieviele Register: 3Gib das 1te Register ein: 0Gib das 2te Register ein: 1Gib das 3te Register ein: 4[0, 1, 4]line = 0 reg = [0, 1, 4] zuweis(plus, 3, 0, 1)line = 1 reg = [0, 1, 4, 1] zuweis(mal, 3, 3, 2)line = 2 reg = [0, 1, 4, 4] zuweis(minus, 2, 2, 1)line = 3 reg = [0, 1, 3, 4] ifZeroGoto(2, 5)line = 4 reg = [0, 1, 3, 4] goto(1)line = 1 reg = [0, 1, 3, 4] zuweis(mal, 3, 3, 2)line = 2 reg = [0, 1, 3, 12] zuweis(minus, 2, 2, 1)line = 3 reg = [0, 1, 2, 12] ifZeroGoto(2, 5)line = 4 reg = [0, 1, 2, 12] goto(1)line = 1 reg = [0, 1, 2, 12] zuweis(mal, 3, 3, 2)line = 2 reg = [0, 1, 2, 24] zuweis(minus, 2, 2, 1)line = 3 reg = [0, 1, 1, 24] ifZeroGoto(2, 5)line = 4 reg = [0, 1, 1, 24] goto(1)

    120

  • line = 1 reg = [0, 1, 1, 24] zuweis(mal, 3, 3, 2)line = 2 reg = [0, 1, 1, 24] zuweis(minus, 2, 2, 1)line = 3 reg = [0, 1, 0, 24] ifZeroGoto(2, 5)line = 5 reg = [0, 1, 0, 24] stopstopped[0, 1, 0, 24]

    Yes?-

    Esfolgt derQuellcodedesProgrammesregistermaschine.p l :

    %%%%%%%%%%%%%%%%%% Hauptprogramm %%%%%%%%%%%%%%%%%%%%%main :-

    write(’Geben Sie den Filenamen der Datei ein: ’),liesTastatur(F),name(File,F),see(File),liesFile(Code),seen,ausgabe(Code),parse(Code,Programm) ,write(’Wieviele Register: ’),liesZahl(RegZahl),liesRegister(RegZahl , Reg),write_ln(Reg),ausfuehren(0,Reg,Pro gr amm).

    liesTastatur([X|Xs] ):-get0(X),not X = 10, !,liesTastatur(Xs).

    liesTastatur([]).

    liesFile([X|Xs]) :-get0(X),not X = -1, !,liesFile(Xs).

    liesFile([]).

    ausgabe([X|Xs]) :-put(X),ausgabe(Xs).

    ausgabe([]).

    liesZahl(X) :-liesTastatur(S),name(X, S),integer(X).

    121

  • liesRegister(N, Reg) :-liesRegister(N, 1, Reg).

    liesRegister(N, M, [X|Reg]) :-N > 0,write(’Gib das ’),write(M),write(’te Register ein: ’),liesZahl(X),N1 is N - 1,M1 is M + 1,liesRegister(N1, M1, Reg).

    liesRegister(0, _, []).

    %%%%%%%%%%parsing %%%%%%%%%%%%%%%%

    ziffer([Z|S0], S0, N) :-Z >= 48,Z =< 57,N is Z - 48.

    zahl(S0, S1, SchonDa, Ergebnis) :-ziffer(S0, S2, ErsteStelle),JetztDa is SchonDa * 10 + ErsteStelle,zahl(S2, S1, JetztDa, Ergebnis).

    zahl(S0, S0, Ergebnis, Ergebnis) :-not ziffer(S0, _, _).

    zahl(S0, S1, Ergebnis) :-zahl(S0, S1, 0, Ergebnis).

    r([82|S0], S0).doppelpkt([58|S0], S0).gleichEins([61,49|S 0], S0) .gleich([61|S0],S0).operator([43|S0], S0, plus).operator([42|S0], S0, mal).operator([45|S0], S0, minus).goto([71, 79, 84, 79, 32 | S0], S0).if([73, 70, 32 | S0], S0).gleichNull([61, 48, 32 | S0], S0).stop([83, 84, 79, 80 | S0], S0).zeilenEnde([10|S0], S0) .

    parse(Code, Programm) :-programm(Code, [], Programm).

    122

  • programm(S0, S2, [Befehl|Rest]) :-programmZeile(S0, S1, Befehl),programm(S1, S2, Rest).

    programm(S0, S0, []).

    programmZeile(S0, SX, Befehl) :-zahl(S0, S1, _),doppelpkt(S1, S2),befehl(S2, S3, Befehl),zeilenEnde(S3, SX).

    befehl(S0, SX, macheEins(I)) :-r(S0, S1),zahl(S1, S2, I),gleichEins(S2, SX).

    befehl(S0, SX, zuweis(Operator, I, J, K)) :-r(S0, S1),zahl(S1, S2, I),gleich(S2, S3),r(S3, S4),zahl(S4, S5, J),operator(S5, S6, Operator),r(S6, S7),zahl(S7, SX, K).

    befehl(S0, SX, goto(L)) :-goto(S0, S1),zahl(S1, SX, L).

    befehl(S0, SX, ifZeroGoto(I, L)) :-if(S0, S1),r(S1, S2),zahl(S2, S3, I),gleichNull(S3, S4),goto(S4, S5),zahl(S5, SX, L).

    befehl(S0, SX, stop) :-stop(S0, SX).

    beispielProgramm("0:R3=R0+R11:R3=R3*R22:R2=R2-R13:if R2=0 goto 54:goto 15:stop

    123

  • ").

    %%%%%%%%%%%%%%%%%%%%%%%%%% interpreter %%%%%%%%%%%%%%%

    nthInList([X|_],0,X ).nthInList([_|Xs],N, Z): -

    N > 0,M is N - 1,nthInList(Xs,M,Z).

    nthInList([],N,0):-N >= 0.

    putInList([],0,X,[X ]).putInList([],N,X,[0 |Xs ]): -

    N > 0,M is N - 1,putInList([],M,X,Xs) .

    putInList([_|Xs],0, Y,[ Y|X s]) .putInList([X|Xs],N, Y,[ X|Y s]) :-

    N > 0,M is N - 1,putInList(Xs,M,Y,Ys) .

    varMinus(X,Y,Z):-X >= Y,Z is X - Y.

    varMinus(X,Y,Z):-X < Y,Z is 0.

    operiere(plus, X, Y, Z) :-X is Y + Z.

    operiere(mal, X, Y, Z) :-X is Y * Z.

    operiere(minus, X, Y, Z) :-varMinus(Y, Z, X).

    ausfuehren(L, Reg, Programm) :-nthInList(Programm, L, Befehl),write(’line = ’), write(L), write(’\treg = ’), write(Reg),write(’\t’), write(Befehl), nl,ausfuehren(L, Befehl, Reg, Programm).

    ausfuehren(L, macheEins(I), Reg, Programm) :-putInList(Reg, I, 1, RegNeu),

    124

  • LNeu is L + 1,ausfuehren(LNeu, RegNeu, Programm).

    ausfuehren(L, zuweis(Operator, I, J, K), Reg, Programm) :-nthInList(Reg, J, RJ),nthInList(Reg, K, RK),operiere(Operator, RI, RJ, RK),putInList(Reg, I, RI, RegNeu),LNeu is L + 1,ausfuehren(LNeu, RegNeu, Programm).

    ausfuehren(_, goto(LNeu), Reg, Programm) :-ausfuehren(LNeu, Reg, Programm).

    ausfuehren(_, ifZeroGoto(I, LNeu), Reg, Programm) :-nthInList(Reg, I, RI),RI =:= 0,ausfuehren(LNeu, Reg, Programm).

    ausfuehren(L, ifZeroGoto(I, _), Reg, Programm) :-nthInList(Reg, I, RI),RI =\= 0,LNeu is L + 1,ausfuehren(LNeu, Reg, Programm).

    ausfuehren(_, stop, Reg, _) :-write(’stopped’),nl,write(Reg),nl.

    ausfuehren(L, 0, _, _) :-write(’syntax error in register programm’), nl,write(’at line ’), write(L), nl.

    beispiel(0,[4],[

    macheEins(1),zuweis(plus, 2, 1, 2),zuweis(mal, 2, 0, 2),zuweis(minus,0, 0, 1),ifZeroGoto(0, 6),goto(2),stop

    ]).

    125