• Keine Ergebnisse gefunden

Effizienz und Grammatiken

N/A
N/A
Protected

Academic year: 2022

Aktie "Effizienz und Grammatiken"

Copied!
31
0
0

Wird geladen.... (Jetzt Volltext ansehen)

Volltext

(1)

Effizienz und Grammatiken

Effizienz

Differenzlisten Grammatiken

Effizienz

Differenzlisten Grammatiken

(2)

Effizienz im Allgemeinen

Ausführungszeit, Speichererfordernis

Die traditionelle Computerarchitektur ist nicht besonders passend für Prologs Programmausführung: beweisen einer Zielliste

Für praktische Applikationen ist die mangelnde Effizienz von Prolog dann bedeutsam,

(1) wenn die Grundlaufzeit des Programms hoch ist und das Programm öfter aufgerufen werden muss.

(2) wenn die Anwendung online ist und der Benutzer auf Terminierung warten muss

Vorteile von Prolog bezüglich Programmentwicklungszeiten:

symbolische, nicht-numerische Programmierung, strukturierte Datenobjekte und Relationen auf diesen.

→ aber heute auch viele Bibliotheken z.B. in Java Ausführungszeit, Speichererfordernis

Die traditionelle Computerarchitektur ist nicht besonders passend für Prologs Programmausführung: beweisen einer Zielliste

Für praktische Applikationen ist die mangelnde Effizienz von Prolog dann bedeutsam,

(1) wenn die Grundlaufzeit des Programms hoch ist und das Programm öfter aufgerufen werden muss.

(2) wenn die Anwendung online ist und der Benutzer auf Terminierung warten muss

Vorteile von Prolog bezüglich Programmentwicklungszeiten:

symbolische, nicht-numerische Programmierung, strukturierte Datenobjekte und Relationen auf diesen.

→ aber heute auch viele Bibliotheken z.B. in Java

(3)

Effizienz im Allgemeinen

Ausführungszeit: im Allgemeinen ist ein compiliertes Programm schneller als ein interpretiertes. Deshalb falls vorhanden für

zeitkritische Anwendungen compilierte Programme verwenden.

Daneben:

- Ordnung der Klauseln

- Prozedurale Steuerung durch den Cut Schließlich:

Oft kann der Algorithmus selbst entscheidend verbessert werden.

- Verbesserung der Sucheffizienz, indem unnötiges Backtracking vermieden wird, aussichtslose Alternativen so schnell wie möglich beenden

- Passendere Datenstrukturen verwenden um die Objekte des Programms zu repräsentieren, so dass Operationen möglichst effizient implementiert werden können.

- Caching mit assert

Ausführungszeit: im Allgemeinen ist ein compiliertes Programm schneller als ein interpretiertes. Deshalb falls vorhanden für

zeitkritische Anwendungen compilierte Programme verwenden.

Daneben:

- Ordnung der Klauseln

- Prozedurale Steuerung durch den Cut Schließlich:

Oft kann der Algorithmus selbst entscheidend verbessert werden.

- Verbesserung der Sucheffizienz, indem unnötiges Backtracking vermieden wird, aussichtslose Alternativen so schnell wie möglich beenden

- Passendere Datenstrukturen verwenden um die Objekte des Programms zu repräsentieren, so dass Operationen möglichst effizient implementiert werden können.

- Caching mit assert

(4)

Effizienz durch Anordnung

Beispiel 1: Verbesserung der Effizienz des 8-Damen Programms In der ersten Lösung wurden die Y-Koordinaten für jede Dame

festgelegt indem Integer zwischen eins und acht ausgewählt werden.

member(Y,[1,2,3,4,5,6,7,8]).

Also wird zunächst 1, dann 2 usw. ausprobiert.

Nachdem die Damen in aufeinanderfolgenden Spalten auf dem Brett angeordnet werden, muss gelten, dass zwei aufeinanderfolgende

Damen in vertikaler Richtung mindestens zwei Quadrate entfernt angeordnet werden müssen.

member(Y,[1,5,2,6,3,7,4,8]) verbessert die erste Lösung um Faktor 3-4

Beispiel 1: Verbesserung der Effizienz des 8-Damen Programms In der ersten Lösung wurden die Y-Koordinaten für jede Dame

festgelegt indem Integer zwischen eins und acht ausgewählt werden.

member(Y,[1,2,3,4,5,6,7,8]).

Also wird zunächst 1, dann 2 usw. ausprobiert.

Nachdem die Damen in aufeinanderfolgenden Spalten auf dem Brett angeordnet werden, muss gelten, dass zwei aufeinanderfolgende

Damen in vertikaler Richtung mindestens zwei Quadrate entfernt angeordnet werden müssen.

member(Y,[1,5,2,6,3,7,4,8]) verbessert die erste Lösung um Faktor 3-4

(5)

Effizienz durch Anordnung

Beispiel2: Map coloring Problem: markiere jedes Land einer

gegebenen Karte aus vier Farben, so dass keine benachbarten Länder in derselben Farbe markiert sind.

ngb(Land,Nachbarn).

ngb(albanien,[griechenland,mazedonien,serbien]

ngb(andora,[frankreich,spanien]).

Lösung: Liste von Paaren Land/Farbe [albanien/C1,andorra/C2,...]

Definiere ein Prädikat für colors(Länder_Farben_Liste)

Beispiel2: Map coloring Problem: markiere jedes Land einer

gegebenen Karte aus vier Farben, so dass keine benachbarten Länder in derselben Farbe markiert sind.

ngb(Land,Nachbarn).

ngb(albanien,[griechenland,mazedonien,serbien]

ngb(andora,[frankreich,spanien]).

Lösung: Liste von Paaren Land/Farbe [albanien/C1,andorra/C2,...]

Definiere ein Prädikat für colors(Länder_Farben_Liste)

(6)

Effizienz durch Anordnung

colors([]).

colors([Country/Color|Rest]):-

colors(Rest), member(Color,[gelb,blau,rot,grün]), not(member(Country1/Color,Rest), neighbor(Country,Country1)).

neighbor(Country,Country1):-

ngb(Country,Neighbours),

member(Country1,Neighbors).

colors([]).

colors([Country/Color|Rest]):-

colors(Rest), member(Color,[gelb,blau,rot,grün]), not(member(Country1/Color,Rest), neighbor(Country,Country1)).

neighbor(Country,Country1):-

ngb(Country,Neighbours),

member(Country1,Neighbors).

(7)

Effizienz durch Anordnung

Aufruf über Hilfsprädikat:

country(C) :- ngb(C,_).

?- setoff(Country/Color, country(Country),CountryColorList), colors(ContryColorList).

setoff kontruiert eine Liste für z.B. Europa nach den ngb-Fakten in der Datenbank mit Variablen für die Farben. colors-Ziel soll dann die Farben belegen.

Aufruf über Hilfsprädikat:

country(C) :- ngb(C,_).

?- setoff(Country/Color, country(Country),CountryColorList), colors(ContryColorList).

setoff kontruiert eine Liste für z.B. Europa nach den ngb-Fakten in der Datenbank mit Variablen für die Farben. colors-Ziel soll dann die Farben belegen.

(8)

Effizienz durch Anordnung

Ineffizienzproblem:

Staaten und die Country/Color-Liste sind alphabetisch arrangiert.

Kein Zusammenhang mit der geographischen Lage.

Zuweisungsprozess der Farben startet am Ende der Liste (Warum?).

Zuweisungsprozess ist unabhängig von der ngb-Relation (Warum?).

Die Farben werden also beginnend von einem Punkt auf der Karte weiter bei einem anderen usw zugewiesen.

Mehr oder weniger zufällig. Es kann sehr leicht passieren, dass für ein Land, das viele Nachbarn hat, alle 4 Farben schon verbraucht sind! Dann ist aufwändiges Backtracking notwendig.

Ineffizienzproblem:

Staaten und die Country/Color-Liste sind alphabetisch arrangiert.

Kein Zusammenhang mit der geographischen Lage.

Zuweisungsprozess der Farben startet am Ende der Liste (Warum?).

Zuweisungsprozess ist unabhängig von der ngb-Relation (Warum?).

Die Farben werden also beginnend von einem Punkt auf der Karte weiter bei einem anderen usw zugewiesen.

Mehr oder weniger zufällig. Es kann sehr leicht passieren, dass für ein Land, das viele Nachbarn hat, alle 4 Farben schon verbraucht sind! Dann ist aufwändiges Backtracking notwendig.

(9)

Effizienz durch Anordnung

Klar ist: die Effizienz hängt von der Ordnung ab, in der Ländern die Farbe zugewiesen wird. Intuitiv ist schon eine einfache Strategie besser als Random:

Starte mit einem Land mit vielen Nachbarn, dann dessen Nachbarn und der Nachbarn Nachbarn...

Klar ist: die Effizienz hängt von der Ordnung ab, in der Ländern die Farbe zugewiesen wird. Intuitiv ist schon eine einfache Strategie besser als Random:

Starte mit einem Land mit vielen Nachbarn, dann dessen Nachbarn und der Nachbarn Nachbarn...

(10)

Effizienz durch Anordnung

makelist Prädikat

ausgehend von einem Land, z.B. Deutschland, wird eine Liste mit allen Ländern erstellt, die Closed heisst. Jedes Land wird zunächst in eine andere Liste geschrieben, die Open heisst. Aus Open kommt das Land zu Closed, wenn seine Nachbarn aus nbg(Land, Nachbarn), auf Open geschrieben worden sind.

makelist Prädikat

ausgehend von einem Land, z.B. Deutschland, wird eine Liste mit allen Ländern erstellt, die Closed heisst. Jedes Land wird zunächst in eine andere Liste geschrieben, die Open heisst. Aus Open kommt das Land zu Closed, wenn seine Nachbarn aus nbg(Land, Nachbarn), auf Open geschrieben worden sind.

(11)

Effizienz durch Anordnung

makelist Prädikat

makelist(List) :- collect([germany],[],List).

collect([],Closed,Closed). %keine Kandidaten für Closed %rausschreiben auf List

collect([X|Open],Closed,List) :-

member(X,Closed), !, collect(Open,Closed,List).

%X schon gesammelt collect([X|Open],Closed,List) :-

ngb(X,Ngbs),

append(Ngbs,Open,Open1),

collect(Open1,[X|Closed],List).

makelist Prädikat

makelist(List) :- collect([germany],[],List).

collect([],Closed,Closed). %keine Kandidaten für Closed %rausschreiben auf List

collect([X|Open],Closed,List) :-

member(X,Closed), !, collect(Open,Closed,List).

%X schon gesammelt collect([X|Open],Closed,List) :-

ngb(X,Ngbs),

append(Ngbs,Open,Open1),

collect(Open1,[X|Closed],List).

(12)

Differenzlisten

Verbesserung der Effizienz der Listenkonkatenation mithilfe von Differenzlisten

Programm zur Konkatenation von Listen bislang war:

append([],L,L).

append([X|L1],L2,[X|L3]):- append(L1,L2,L3).

Ineffizient, wenn die erste Liste lang ist.

Verbesserung der Effizienz der Listenkonkatenation mithilfe von Differenzlisten

Programm zur Konkatenation von Listen bislang war:

append([],L,L).

append([X|L1],L2,[X|L3]):- append(L1,L2,L3).

Ineffizient, wenn die erste Liste lang ist.

(13)

Differenzlisten

Beispiel: ?- append([a,b,c], [d,e],L).

Zielsequenz

append([a,b,c], [d,e],L)

append([b,c], [d,e],L') mit L = [a|L']

append([c], [d,e],L'') mit L' = [b|L'']

append([], [d,e],L''') mit L'' = [c|L''']

true mit L''' = [d,e]

Das append prädikat arbeitet die gesamte erste Liste ab, bis endlich die Leere Liste erreicht ist, dann beginnt der rekursive

Zusammenbau.

Beispiel: ?- append([a,b,c], [d,e],L).

Zielsequenz

append([a,b,c], [d,e],L)

append([b,c], [d,e],L') mit L = [a|L']

append([c], [d,e],L'') mit L' = [b|L'']

append([], [d,e],L''') mit L'' = [c|L''']

true mit L''' = [d,e]

Das append prädikat arbeitet die gesamte erste Liste ab, bis endlich die Leere Liste erreicht ist, dann beginnt der rekursive

Zusammenbau.

(14)

Differenzlisten

Beispielimplementierung von append mit Akkumulator Beispiel: ?- append_acc([a,b,c], [d,e],L).

Zielsequenz

append_acc([],L,L).

append_acc([X|Rest],Acc,L):- append_acc(Rest,[X|Acc],L).

L=[c,b,a,d,e].

Schon effizienter aber die erste Liste wird in umgekehrter Reihenfolge angehängt.

Beispielimplementierung von append mit Akkumulator Beispiel: ?- append_acc([a,b,c], [d,e],L).

Zielsequenz

append_acc([],L,L).

append_acc([X|Rest],Acc,L):- append_acc(Rest,[X|Acc],L).

L=[c,b,a,d,e].

Schon effizienter aber die erste Liste wird in umgekehrter Reihenfolge angehängt.

(15)

Differenzlisten

Was wir uns wünschen würden:

Skip das Scannen der ersten Liste und hänge die zweite Liste an, ohne die gesammte erste Liste abzuarbeiten.

Wir müssen wissen, wo das Ende einer Liste ist → wir brauchen eine andere Repräsentation von Listen.

Die Lösung wird als Differenzlisten bezeichnet.

Eine Differenzliste wird als Listenpaar repräsentiert.

L = [a,b,c] kann mit L1=[a,b,c,d,e] und L2= [d,e] als L1-L2 repräsentiert werden.

Achtung: nur wenn L2 ein Suffix von L1 ist!!!

Was wir uns wünschen würden:

Skip das Scannen der ersten Liste und hänge die zweite Liste an, ohne die gesammte erste Liste abzuarbeiten.

Wir müssen wissen, wo das Ende einer Liste ist → wir brauchen eine andere Repräsentation von Listen.

Die Lösung wird als Differenzlisten bezeichnet.

Eine Differenzliste wird als Listenpaar repräsentiert.

L = [a,b,c] kann mit L1=[a,b,c,d,e] und L2= [d,e] als L1-L2 repräsentiert werden.

Achtung: nur wenn L2 ein Suffix von L1 ist!!!

(16)

Differenzlisten

Dieselbe Liste kann von verschiedenen Differenzpaaren repräsentiert werden.

[a,b,c] - [ ]

[a,b,c,d,e] - [d,e]

[a,b,c,d,e|T] - [d,e|T]

[a,b,c|T] – T

wobei T eine beliebige Liste ist.

Die leere Liste wird durch irgendein Paar der Form L-L als Differenzliste repräsentiert.

Dieselbe Liste kann von verschiedenen Differenzpaaren repräsentiert werden.

[a,b,c] - [ ]

[a,b,c,d,e] - [d,e]

[a,b,c,d,e|T] - [d,e|T]

[a,b,c|T] – T

wobei T eine beliebige Liste ist.

Die leere Liste wird durch irgendein Paar der Form L-L als Differenzliste repräsentiert.

(17)

Differenzlisten

Nachdem nun die zweite Liste im Paar das Ende der Liste

repräsentiert, ist das Ende direkt zugänglich. Dies kann für eine effiziente Implementation der Konkatenation ausgenutzt werden.

append_diff(As-Bs,Bs-Cs,As-Cs).

Anwendung: konkateniere [a,b,c] und [d,e].

Also [a,b,c|Bs] – Bs, [d,e|Cs] – Cs über den Aufruf

?- append_diff([a,b,c|Bs] – Bs,[d,e|Cs] – Cs,L - []) Cs = [ ]

Bs = [d,e|[]]

und damit L = [a,b,c,d,e|[]]

wichtig daran ist der Zusammenbau von As in L durch Unifikation indem Bs instantiert ist. Es wird Cs mit [] aufgerufen kann man

das Ergebnis weiter verarbeiten.

Nachdem nun die zweite Liste im Paar das Ende der Liste

repräsentiert, ist das Ende direkt zugänglich. Dies kann für eine effiziente Implementation der Konkatenation ausgenutzt werden.

append_diff(As-Bs,Bs-Cs,As-Cs).

Anwendung: konkateniere [a,b,c] und [d,e].

Also [a,b,c|Bs] – Bs, [d,e|Cs] – Cs über den Aufruf

?- append_diff([a,b,c|Bs] – Bs,[d,e|Cs] – Cs,L - []) Cs = [ ]

Bs = [d,e|[]]

und damit L = [a,b,c,d,e|[]]

wichtig daran ist der Zusammenbau von As in L durch Unifikation indem Bs instantiert ist. Es wird Cs mit [] aufgerufen kann man

das Ergebnis weiter verarbeiten.

(18)

Kontextfreie Grammatiken in Prolog

Kontextfreie Grammatik Pseudocode s → np vp

np → det n vp → v np | v det → der | das

n → Programmierer | Programm v → steht | schrieb

Kontextfreie Grammatik Pseudocode s → np vp

np → det n vp → v np | v det → der | das

n → Programmierer | Programm v → steht | schrieb

(19)

Übersetzung in Prolog

S(S) :- append(NP,VP,S), np(NP),

vp(VP).

wir zerteilen den Eingabesatz S eine Liste von Prolog-Atomen in zwei Teillisten und prüfen ob diese die Eigenschaft np und vp haben

S(S) :- append(NP,VP,S), np(NP),

vp(VP).

wir zerteilen den Eingabesatz S eine Liste von Prolog-Atomen in zwei Teillisten und prüfen ob diese die Eigenschaft np und vp haben

(20)

Übersetzung in Prolog

np(NP) :- append(D,N,NP), det(D),n(N).

vp(VP) :- append(V,NP,VP), v(V),np(NP).

vp(VP) :- v(VP).

det([der]).

det([das]).

n(['Programmierer']).

n(['Programm']).

v([steht]).

v([schrieb]).

np(NP) :- append(D,N,NP), det(D),n(N).

vp(VP) :- append(V,NP,VP), v(V),np(NP).

vp(VP) :- v(VP).

det([der]).

det([das]).

n(['Programmierer']).

n(['Programm']).

v([steht]).

v([schrieb]).

(21)

Übersetzung in Prolog

Aufruf des Programms:

[trace] ?- np([das,'Programm']).

Call: (6) np([das, 'Programm']) ? creep

Call: (7) append(_G1595, _G1596, [das, 'Programm']) ? creep Exit: (7) append([], [das, 'Programm'], [das, 'Programm']) ? creep Call: (7) det([]) ? creep

Fail: (7) det([]) ? creep

Exit: (7) append([das], ['Programm'], [das, 'Programm']) ? creep Call: (7) det([das]) ? creep

Exit: (7) det([das]) ? creep

Call: (7) n(['Programm']) ? creep Exit: (7) n(['Programm']) ? creep

Exit: (6) np([das, 'Programm']) ? creep true .

Problem zu viele append Aufrufe.

Aufruf des Programms:

[trace] ?- np([das,'Programm']).

Call: (6) np([das, 'Programm']) ? creep

Call: (7) append(_G1595, _G1596, [das, 'Programm']) ? creep Exit: (7) append([], [das, 'Programm'], [das, 'Programm']) ? creep Call: (7) det([]) ? creep

Fail: (7) det([]) ? creep

Exit: (7) append([das], ['Programm'], [das, 'Programm']) ? creep Call: (7) det([das]) ? creep

Exit: (7) det([das]) ? creep

Call: (7) n(['Programm']) ? creep Exit: (7) n(['Programm']) ? creep

Exit: (6) np([das, 'Programm']) ? creep true .

Problem zu viele append Aufrufe.

(22)

Übersetzung in Prolog

Lösung: Differenzlisten. Wir parsen den Satz entlang von links nach rechts. Wir können also sagen, Eingabe ist eine Liste von Atomen, von denen mit der ersten Regel np ein Teil NP abgearbeitet wird und dann bleibt noch ein Teil VP übrig. Wird mit vp der Teil VP

abgearbeitet, so bleibt nichts mehr übrig. Zugleich gilt: S = NP+VP wir erinnern uns an die Differenzlistenimplementierung.

appendl(As-Bs,Bs-Cs,As-Cs).

Damit wird NP: S – VP VP: VP - [ ]

Aufruf: S- [ ]

Lösung: Differenzlisten. Wir parsen den Satz entlang von links nach rechts. Wir können also sagen, Eingabe ist eine Liste von Atomen, von denen mit der ersten Regel np ein Teil NP abgearbeitet wird und dann bleibt noch ein Teil VP übrig. Wird mit vp der Teil VP

abgearbeitet, so bleibt nichts mehr übrig. Zugleich gilt: S = NP+VP wir erinnern uns an die Differenzlistenimplementierung.

appendl(As-Bs,Bs-Cs,As-Cs).

Damit wird NP: S – VP VP: VP - [ ]

Aufruf: S- [ ]

(23)

Übersetzung in Prolog

Neue Grammatikregeln:

s(S-[]) :-

appendl(S-VP,VP-[ ],S-[]), beginnt_mit_np(S-VP), beginnt_mit_vp(VP-[]).

Neue Grammatikregeln:

s(S-[]) :-

appendl(S-VP,VP-[ ],S-[]), beginnt_mit_np(S-VP), beginnt_mit_vp(VP-[]).

(24)

Übersetzung in Prolog

Vereinfacht ohne Append mit zwei Argumenten: Eingabeliste des Prädikats und Ausgaberestliste.

s(I,J) :- beginnt_mit_np(I,K),beginnt_mit_vp(K,J).

mit J = [ ] aufgerufen, dann wird der ganze Satz in der Liste

I=['Der','Programmierer',programmiert] abgearbeitet wenn J mit []

zurückkommt.

beginnt_mit_np(I,K) :- det(I,J), n(J,K).

beginnt_mit_vp(K,J) :- v(K,J).

Terminale:

det(I,J) :- I = [der|J].

det(I,J) :- I = ['Der'|J].

n(I,J) :- I = ['Programmierer'|J].

v(I,J) :- I = [programmiert|J].

Vereinfacht ohne Append mit zwei Argumenten: Eingabeliste des Prädikats und Ausgaberestliste.

s(I,J) :- beginnt_mit_np(I,K),beginnt_mit_vp(K,J).

mit J = [ ] aufgerufen, dann wird der ganze Satz in der Liste

I=['Der','Programmierer',programmiert] abgearbeitet wenn J mit []

zurückkommt.

beginnt_mit_np(I,K) :- det(I,J), n(J,K).

beginnt_mit_vp(K,J) :- v(K,J).

Terminale:

det(I,J) :- I = [der|J].

det(I,J) :- I = ['Der'|J].

n(I,J) :- I = ['Programmierer'|J].

v(I,J) :- I = [programmiert|J].

(25)

Übersetzung in Prolog

Startaufrufe und Abarbeitung Determinator

[trace] ?- s(['Der','Programmierer',programmiert],[]).

Call: (6) s(['Der', 'Programmierer', programmiert], []) ? creep

Call: (7) np(['Der', 'Programmierer', programmiert], _G138943) ? creep Call: (8) det(['Der', 'Programmierer', programmiert], _G138943) ? creep Call: (9) ['Der', 'Programmierer', programmiert]=[der|_G138939] ? creep Fail: (9) ['Der', 'Programmierer', programmiert]=[der|_G138939] ? creep Redo: (8) det(['Der', 'Programmierer', programmiert], _G138943) ? creep Call: (9) ['Der', 'Programmierer', programmiert]=['Der'|_G138939] ? creep

Exit: (9) ['Der', 'Programmierer', programmiert]=['Der', 'Programmierer', programmiert] ? creep

Exit: (8) det(['Der', 'Programmierer', programmiert], ['Programmierer', programmiert]) ? creep

Startaufrufe und Abarbeitung Determinator

[trace] ?- s(['Der','Programmierer',programmiert],[]).

Call: (6) s(['Der', 'Programmierer', programmiert], []) ? creep

Call: (7) np(['Der', 'Programmierer', programmiert], _G138943) ? creep Call: (8) det(['Der', 'Programmierer', programmiert], _G138943) ? creep Call: (9) ['Der', 'Programmierer', programmiert]=[der|_G138939] ? creep Fail: (9) ['Der', 'Programmierer', programmiert]=[der|_G138939] ? creep Redo: (8) det(['Der', 'Programmierer', programmiert], _G138943) ? creep Call: (9) ['Der', 'Programmierer', programmiert]=['Der'|_G138939] ? creep

Exit: (9) ['Der', 'Programmierer', programmiert]=['Der', 'Programmierer', programmiert] ? creep

Exit: (8) det(['Der', 'Programmierer', programmiert], ['Programmierer', programmiert]) ? creep

(26)

Übersetzung in Prolog

Abarbeitung Nomen schließen Nominalphrase np

[trace]

Call: (8) n(['Programmierer', programmiert], _G139255) ? creep

Call: (9) ['Programmierer', programmiert]=['Programmierer'|_G139251] ? creep Exit: (9) ['Programmierer', programmiert]=['Programmierer', programmiert] ? creep Exit: (8) n(['Programmierer', programmiert], [programmiert]) ? creep

Exit: (7) np(['Der', 'Programmierer', programmiert], [programmiert]) ? creep

Abarbeitung Nomen schließen Nominalphrase np

[trace]

Call: (8) n(['Programmierer', programmiert], _G139255) ? creep

Call: (9) ['Programmierer', programmiert]=['Programmierer'|_G139251] ? creep Exit: (9) ['Programmierer', programmiert]=['Programmierer', programmiert] ? creep Exit: (8) n(['Programmierer', programmiert], [programmiert]) ? creep

Exit: (7) np(['Der', 'Programmierer', programmiert], [programmiert]) ? creep

(27)

Übersetzung in Prolog

Abarbeitung verb/schließen Verbalphrase vp

[trace]

Call: (7) vp([programmiert], []) ? creep Call: (8) v([programmiert], []) ? creep

Call: (9) [programmiert]=[programmiert] ? creep Exit: (9) [programmiert]=[programmiert] ? creep Exit: (8) v([programmiert], []) ? creep

Exit: (7) vp([programmiert], []) ? creep

Exit: (6) s(['Der', 'Programmierer', programmiert], []) ? creep true

Abarbeitung verb/schließen Verbalphrase vp

[trace]

Call: (7) vp([programmiert], []) ? creep Call: (8) v([programmiert], []) ? creep

Call: (9) [programmiert]=[programmiert] ? creep Exit: (9) [programmiert]=[programmiert] ? creep Exit: (8) v([programmiert], []) ? creep

Exit: (7) vp([programmiert], []) ? creep

Exit: (6) s(['Der', 'Programmierer', programmiert], []) ? creep true

(28)

Übersetzung in Prolog

Tatsächlich erfolgt die Abarbeitung der Differenzlisten auf der Ebene der Terminale über den Restlistenoperator.

Alternative Schreibung der Terminale:

Eingabeliste mit dem Terminal in Atomform als Kopf Ausgabeliste ist der Rest.

det([der|J],J).

Dieser Rest ist dann wiederum Eingabeliste für das n Goal aus der np Regel

n([Programmierer|J],J).

Dieser Rest wird dann an die np als deren Ausgabeliste weitergegeben, der Rest vom Satz

np(I,J) :- det(I,K),n(K,J).

Tatsächlich erfolgt die Abarbeitung der Differenzlisten auf der Ebene der Terminale über den Restlistenoperator.

Alternative Schreibung der Terminale:

Eingabeliste mit dem Terminal in Atomform als Kopf Ausgabeliste ist der Rest.

det([der|J],J).

Dieser Rest ist dann wiederum Eingabeliste für das n Goal aus der np Regel

n([Programmierer|J],J).

Dieser Rest wird dann an die np als deren Ausgabeliste weitergegeben, der Rest vom Satz

np(I,J) :- det(I,K),n(K,J).

(29)

Übersetzung in Prolog

Format der Klauselgrammatiken in Prolog

In Prolog wird die Regelübersetzung von Grammatikklauseln in das notwendige Abarbeitungsformat durch das Prädikat

--> /2 erreicht.

Format der Klauselgrammatiken in Prolog

In Prolog wird die Regelübersetzung von Grammatikklauseln in das notwendige Abarbeitungsformat durch das Prädikat

--> /2 erreicht.

(30)

Übersetzung in Prolog

Unsere Beispielgrammatik als DCG:

s --> np,vp.

np --> det,n.

vp --> v, np.

vp --> v.

det --> [der].

det --> [das].

n --> ['Programmierer'].

n --> ['Programm'].

v --> [steht].

v --> [schrieb].

Diese Regeln werden dann intern in die Differenzlistenform übersetzt: np(I,J) :- det(I,K),n(K,J).

Unsere Beispielgrammatik als DCG:

s --> np,vp.

np --> det,n.

vp --> v, np.

vp --> v.

det --> [der].

det --> [das].

n --> ['Programmierer'].

n --> ['Programm'].

v --> [steht].

v --> [schrieb].

Diese Regeln werden dann intern in die Differenzlistenform übersetzt: np(I,J) :- det(I,K),n(K,J).

(31)

Hausaufgabe

Lesen Leiss-Skript zu Kapitel 6 DCG Lesen Bratko Kapitel 21

Lesen Leiss-Skript zu Kapitel 6 DCG Lesen Bratko Kapitel 21

Referenzen

ÄHNLICHE DOKUMENTE

folgen, (i) daß in deutschen Hauptsätzen finite Verben entweder die erste oder die zweite Position einnehmen (wo sie dann auch meist vor statt hinter dem Objekt stehen), nicht aber

Lothar Sebastian Krapp Simon Müller.

Da aber T 22 eine Appro- ximation noch h¨ oherer Ordnung ist (theoretisch 6 gegen¨ uber 4), k¨ onnen wir dies auch als Fehlersch¨ atzung f¨ ur T

Diplom – VP

Da aber T 22 eine Approximation noch h¨ ohere Ordnung ist (theoretisch 6 gegen¨ uber 4), k¨ onnen wir dies auch als Fehlersch¨ atzung f¨ ur T

Wie groß ist der Fehler (h¨ ochstens) nach der 1.. a) Berechne einen N¨ aherungswert f¨ ur f (0.15) mit dem Neville-Aitken-Schema unter Benutzung aller Tabellenwerte und gib

Die vorhandene L-R-Zerlegung bezieht sich auf das pivotisierte Gleichungssystem zu der Matrix A.. Aufgabe 2: Lineare Ausgleichsrechnung... 1.. x) auf ihren

Während also der Nutzungsgrad das Verhältnis der Energiemengen (angegeben in kWh) ist, wird der Wirkungsgrad über das Verhältnis der Leistungen (angegeben in kW) berechnet. 1 Der