• Keine Ergebnisse gefunden

Grössere Programme

N/A
N/A
Protected

Academic year: 2022

Aktie "Grössere Programme"

Copied!
27
0
0

Wird geladen.... (Jetzt Volltext ansehen)

Volltext

(1)

Grössere Programme

Nachträge

Weitere nützliche Prädikate

Programmiertechniken und Debugging Tokenizer Programm I

Nachträge

Weitere nützliche Prädikate

Programmiertechniken und Debugging Tokenizer Programm I

(2)

Nachtrag zum Backtracking

Werden im Backtracking bottom-up höhere choice-Punkte erreicht, so werden alle Belegungen die darunter liegen freigegeben. Das muss so sein, da sich durch Backtracking weiter oben über

Abhängigkeiten die Startbelegungen der weiter unten liegenden Ziele ändern können.

Werden im Backtracking bottom-up höhere choice-Punkte erreicht, so werden alle Belegungen die darunter liegen freigegeben. Das muss so sein, da sich durch Backtracking weiter oben über

Abhängigkeiten die Startbelegungen der weiter unten liegenden Ziele ändern können.

(3)

Nachtrag zum Backtracking

Beispielprogramm:

p(1).

p(2).

?- p(X), p(Y).

X=1,Y=1;

X=1,Y=2;

X=2,Y=1; %zuerst 1 da Belegung mit 2 wieder gelöscht wurde X=2,Y=2; %jetzt wieder Y bottom-up Backtracking erste Variante no %weiteres Backtracking nicht möglich

Beispielprogramm:

p(1).

p(2).

?- p(X), p(Y).

X=1,Y=1;

X=1,Y=2;

X=2,Y=1; %zuerst 1 da Belegung mit 2 wieder gelöscht wurde X=2,Y=2; %jetzt wieder Y bottom-up Backtracking erste Variante no %weiteres Backtracking nicht möglich

(4)

Beispielprogramm zu =..

=.. Term umwandeln zu Funktor, Argumenten in einer Liste

Stellen uns vor, dass wir ein Programm haben, das geometrische Figuren manipuliert. Funktor gibt den Typ der Figur an, Argumente spezifizieren die Größe.

Figuren

square(Side)

square(Side1,Side2,Side3) circle(Radius)

Mögliche Operation enlarge(Figure,Factor,Figure1)

=.. Term umwandeln zu Funktor, Argumenten in einer Liste

Stellen uns vor, dass wir ein Programm haben, das geometrische Figuren manipuliert. Funktor gibt den Typ der Figur an, Argumente spezifizieren die Größe.

Figuren

square(Side)

square(Side1,Side2,Side3) circle(Radius)

Mögliche Operation enlarge(Figure,Factor,Figure1)

(5)

Beispielprogramm zu =..

enlarge(square(A),F,square(A1)) :- A1 is F*A.

enlarge(circle(R),F,circle(R1)) :- R1 is F*R.

Verallgemeinerter Lösungsversuch für die Einparameterfiguren:

enlarge(Type(Parameter),F,Type(Parameter1)) :- Parameter1 is F*Parameter.

Funktioniert nicht, da Funktor in Prolog Atom sein muss.

Variable werden nicht als Funktor akzeptiert enlarge(square(A),F,square(A1)) :-

A1 is F*A.

enlarge(circle(R),F,circle(R1)) :- R1 is F*R.

Verallgemeinerter Lösungsversuch für die Einparameterfiguren:

enlarge(Type(Parameter),F,Type(Parameter1)) :- Parameter1 is F*Parameter.

Funktioniert nicht, da Funktor in Prolog Atom sein muss.

Variable werden nicht als Funktor akzeptiert

(6)

Beispielprogramm zu =..

Lösung: =.. Benutzen enlarge(Fig, F, Fig1) :-

Fig =.. [Type|Parameters],

multiplylist(Parameters,F,Parameters1), Fig1 =.. [Type|Parameters1].

%Hilfsprädikat

multiplylist([ ],_,[ ])

multiplylist([X|Rest],F,[X1|Rest1]) :-

X1 is X*F, multiplylist(Rest,F,Rest1).

erledigt auch square etc.

Lösung: =.. Benutzen enlarge(Fig, F, Fig1) :-

Fig =.. [Type|Parameters],

multiplylist(Parameters,F,Parameters1), Fig1 =.. [Type|Parameters1].

%Hilfsprädikat

multiplylist([ ],_,[ ])

multiplylist([X|Rest],F,[X1|Rest1]) :-

X1 is X*F, multiplylist(Rest,F,Rest1).

erledigt auch square etc.

(7)

Datenbankmanipulation

Prologprogramm kann als relationale Datenbank betrachtet werden.

Die Relationenmenge ist z.T. explizit: Fakten, z.T. implizit, Regeln.

Einige built-in Prädikate erlauben es, die Datenbank während der Programmausführung zu verändern (update).

Klauseln hinzufügen: assert, asserta, assertz.

Klauseln löschen: retract.

Prologprogramm kann als relationale Datenbank betrachtet werden.

Die Relationenmenge ist z.T. explizit: Fakten, z.T. implizit, Regeln.

Einige built-in Prädikate erlauben es, die Datenbank während der Programmausführung zu verändern (update).

Klauseln hinzufügen: assert, asserta, assertz.

Klauseln löschen: retract.

(8)

Datenbankmanipulation

assert (C): immer true, Seiteneffekt, C ist in der Datenbank verfügbar.

retract (C): immer true, Seiteneffekt, C ist in der Datenbank nicht mehr verfügbar.

nice :- sunshine, not raining. %Regeln funny :- sunshine, raining.

disgusting :- fog, raining.

rainy. %Fakten fog.

assert (C): immer true, Seiteneffekt, C ist in der Datenbank verfügbar.

retract (C): immer true, Seiteneffekt, C ist in der Datenbank nicht mehr verfügbar.

nice :- sunshine, not raining. %Regeln funny :- sunshine, raining.

disgusting :- fog, raining.

rainy. %Fakten fog.

(9)

Datenbankmanipulation

nice :- sunshine, not raining. %Regeln funny :- sunshine, raining.

disgusting :- fog, raining.

rainy. %Fakten fog.

?- nice. no

?- disgusting. yes

?- retract(fog).

?- disgusting. no

?- assert(sunshine).

?- funny. yes

?-retract(raining).

?-nice.yes

nice :- sunshine, not raining. %Regeln funny :- sunshine, raining.

disgusting :- fog, raining.

rainy. %Fakten fog.

?- nice. no

?- disgusting. yes

?- retract(fog).

?- disgusting. no

?- assert(sunshine).

?- funny. yes

?-retract(raining).

?-nice.yes

(10)

Datenbankmanipulation

Klauseln jeder Form können mit assert hinzugefügt und mit retract gelöscht werden. In manchen Prolog Implementation müssen soltch Klauseln dynamic deklariert sein.

?- asserta(C). fügt C am Anfang der Datenbank ein

?- assertz(C). fügt C am Ende der Datenbank ein

Als Anwendungsfall: schon berechnete Ergebnisse als Fakten in die Datenbank schreiben.

maketable :- L=[0,1,2,3,4,5,6,7,8,9]

member (X,L),member(Y,L), Z is X*Y,

assert(product(X,Y,Z) fail.

Klauseln jeder Form können mit assert hinzugefügt und mit retract gelöscht werden. In manchen Prolog Implementation müssen soltch Klauseln dynamic deklariert sein.

?- asserta(C). fügt C am Anfang der Datenbank ein

?- assertz(C). fügt C am Ende der Datenbank ein

Als Anwendungsfall: schon berechnete Ergebnisse als Fakten in die Datenbank schreiben.

maketable :- L=[0,1,2,3,4,5,6,7,8,9]

member (X,L),member(Y,L), Z is X*Y,

assert(product(X,Y,Z) fail.

(11)

Datenbankmanipulation

?- maketable. fail

Wie sieht jetzt die Datenbank aus? Schauen Sie das Programm im Tracer an, um zu sehen wie es arbeitet.

?- product(A,B,8).

A=1,B=8;A=2,B=4;A=4,B=2;A=8,B=1;fail

Vorsicht mit assert und retract, diese Prädikate führen leicht zu obskuren Programmen.

?- maketable. fail

Wie sieht jetzt die Datenbank aus? Schauen Sie das Programm im Tracer an, um zu sehen wie es arbeitet.

?- product(A,B,8).

A=1,B=8;A=2,B=4;A=4,B=2;A=8,B=1;fail

Vorsicht mit assert und retract, diese Prädikate führen leicht zu obskuren Programmen.

(12)

Multiple Lösungen erzwingen

bagof, setof, findall

bagof(X,P,L) Liste L, aller Objekte X, so dass P erfüllt ist.

age(tom,7).

age(pat,4).

age(lisa,7).

?- bagof(Child,age(Child,7),List).

L=[tom,lisa] yes

?- bagof(Child,Age^age(Child,Age),List).

L=[tom,pat,lisa] yes

^ Infix Operator der Age auf beliebig setzt

setof: Liste wird geordnet und ohne Duplikate ausgegeben Termordnung nach @< Prädikat

bagof, setof, findall

bagof(X,P,L) Liste L, aller Objekte X, so dass P erfüllt ist.

age(tom,7).

age(pat,4).

age(lisa,7).

?- bagof(Child,age(Child,7),List).

L=[tom,lisa] yes

?- bagof(Child,Age^age(Child,Age),List).

L=[tom,pat,lisa] yes

^ Infix Operator der Age auf beliebig setzt

setof: Liste wird geordnet und ohne Duplikate ausgegeben Termordnung nach @< Prädikat

(13)

Multiple Lösungen erzwingen

findall

wiederum wird eine Liste erstellt, die alle Objekte enthält, die P erfüllen. Der Unterschied zu bagof ist, dass alle X gesammelt werden, egal wie die Variablen in P belegt sind, die nicht mit X geteilt werden.

findall(Child,age(Child,Age),List).

List=[tom,pat,lisa] yes.

findall

wiederum wird eine Liste erstellt, die alle Objekte enthält, die P erfüllen. Der Unterschied zu bagof ist, dass alle X gesammelt werden, egal wie die Variablen in P belegt sind, die nicht mit X geteilt werden.

findall(Child,age(Child,Age),List).

List=[tom,pat,lisa] yes.

(14)

Programmierstil und Techniken

Generelle Prinzipien

Prolog Programme im Allgemeinen Guter Programmierstil

Debugging Effizienz

Generelle Prinzipien

Prolog Programme im Allgemeinen Guter Programmierstil

Debugging Effizienz

(15)

Programmierstil und Techniken

Korrektheit

Benutzerfreundlichkeit Effizienz

Lesbarkeit

Modifizierbarkeit, Wartbarkeit Robustheit

Dokumentation Korrektheit

Benutzerfreundlichkeit Effizienz

Lesbarkeit

Modifizierbarkeit, Wartbarkeit Robustheit

Dokumentation

(16)

Programmierstil und Techniken

Schrittweise Annäherung an das Problem: in jedem Schritt werden einzelne schon verifizierte Prozeduren und Datenstrukturen auf die Lösung des eigentlichen Problems zubewegt

Schritte sollten so klein sein, dass eine Anpassung gut durchführbar ist und man immer Klarheit hat warum das Programm vor der

Änderung noch funktioniert hat

Beispiel: implementiere das Damenproblem erst als Turmproblem Finde lösbare Subprobleme

Schrittweise Annäherung an das Problem: in jedem Schritt werden einzelne schon verifizierte Prozeduren und Datenstrukturen auf die Lösung des eigentlichen Problems zubewegt

Schritte sollten so klein sein, dass eine Anpassung gut durchführbar ist und man immer Klarheit hat warum das Programm vor der

Änderung noch funktioniert hat

Beispiel: implementiere das Damenproblem erst als Turmproblem Finde lösbare Subprobleme

(17)

Programmierstil und Techniken

Techniken in Prolog zum finden lösbarer Subprobleme Benutze Rekursion: (1) Triviale Fälle, Grenzfälle

(2) Generelle Fälle= Lösung wird aus Lösungen einfacherer Varianten des ursprünglichen

Problems gewonnen

Techniken in Prolog zum finden lösbarer Subprobleme Benutze Rekursion: (1) Triviale Fälle, Grenzfälle

(2) Generelle Fälle= Lösung wird aus Lösungen einfacherer Varianten des ursprünglichen

Problems gewonnen

(18)

Programmierstil und Techniken

Beispiel: List ist eine Eingabeliste, F eine Transformationsregel = binäre Relation, Newlist, die Liste aller transformierten Objekte (1) Grenzfall: List=[ ] → Newlist=[ ] egal wie F aussieht

(2) Genereller Fall

List = [ X|Tail ] → Newlist=[NewX|NewTail ]

Transformiere X unter F in NewX und dann den Rest maplist([ ][ ]).

maplist[X|Tail],F,[NewX|NewTail]) :- G =.. [F,X,NewX],

call(G), maplist(Tail,F,NewTail).

Builtin call(Goal): Argument ist das Goal das ausgeführt werden soll Quadrate ausrechnen:

square(X,Y) :- Y is X*X.

maplist ([2,6,5],square,Squares).

Beispiel: List ist eine Eingabeliste, F eine Transformationsregel = binäre Relation, Newlist, die Liste aller transformierten Objekte (1) Grenzfall: List=[ ] → Newlist=[ ] egal wie F aussieht

(2) Genereller Fall

List = [ X|Tail ] → Newlist=[NewX|NewTail ]

Transformiere X unter F in NewX und dann den Rest maplist([ ][ ]).

maplist[X|Tail],F,[NewX|NewTail]) :- G =.. [F,X,NewX],

call(G), maplist(Tail,F,NewTail).

Builtin call(Goal): Argument ist das Goal das ausgeführt werden soll Quadrate ausrechnen:

square(X,Y) :- Y is X*X.

maplist ([2,6,5],square,Squares).

(19)

Programmierstil und Techniken

warum lässt sich Rekursion so natürlich anwenden: Datenobjekte selbst besitzen oft rekursive Strukturen. Listen und Bäume sind solche Strukturen.

Liste: (1) leer

(2) Head und Tail welches selbst Liste ist Binärer Baum

(1) leer

(2) Root und zwei Subbäume, die wieder binäre Bäume sind warum lässt sich Rekursion so natürlich anwenden: Datenobjekte selbst besitzen oft rekursive Strukturen. Listen und Bäume sind solche Strukturen.

Liste: (1) leer

(2) Head und Tail welches selbst Liste ist Binärer Baum

(1) leer

(2) Root und zwei Subbäume, die wieder binäre Bäume sind

(20)

Programmierstil und Techniken

Stylistische Konventionen

kurze Klauseln, wenige Ziele im Regelkörper

kurze Prozeduren = Klauseln mit demselben Kopf

sprechende Namen: Bedeutung der Relationen und die Rolle von Datenobjekten sollte angezeigt werden

Layout: spacing, Leerzeilen, Einrückungen konsequent; Klauseln der selben Prozedur zusammen

Cut vorsichtig, nicht wenn vermeidbar, besser grüne als rote; rote nur für not und Alternativenauswahl

Programmmodifikation durch assert und retract gefährlich, da unterschiedliches Programmverhalten zu unterschiedlichen Zeitpunkten

Benutzen von ; kann Klauseln schwer verständlich machen.

Manchmal besser zwei Klauseln zu benutzen Stylistische Konventionen

kurze Klauseln, wenige Ziele im Regelkörper

kurze Prozeduren = Klauseln mit demselben Kopf

sprechende Namen: Bedeutung der Relationen und die Rolle von Datenobjekten sollte angezeigt werden

Layout: spacing, Leerzeilen, Einrückungen konsequent; Klauseln der selben Prozedur zusammen

Cut vorsichtig, nicht wenn vermeidbar, besser grüne als rote; rote nur für not und Alternativenauswahl

Programmmodifikation durch assert und retract gefährlich, da unterschiedliches Programmverhalten zu unterschiedlichen Zeitpunkten

Benutzen von ; kann Klauseln schwer verständlich machen.

Manchmal besser zwei Klauseln zu benutzen

(21)

Programmierstil und Techniken

Beispiel für komplizierenden Programmierstil, mergen zweier sortierter Listen, aufsteigende Sortierung

merge(List1,List2,List3) :- List1 = [ ],!,List3=List2;

List2=[ ],!,List3=List1;

List1 = [X|Rest1], List2 = [Y|Rest2], (X<Y,!,

Z=X, %Z wird Head von List3 merge(Rest1,List2,Rest3);

Z=Y, %Z wird Head von List3 merge(List1,Rest22,Rest3) ),

List3 = [Z|Rest3].

Beispiel für komplizierenden Programmierstil, mergen zweier sortierter Listen, aufsteigende Sortierung

merge(List1,List2,List3) :- List1 = [ ],!,List3=List2;

List2=[ ],!,List3=List1;

List1 = [X|Rest1], List2 = [Y|Rest2], (X<Y,!,

Z=X, %Z wird Head von List3 merge(Rest1,List2,Rest3);

Z=Y, %Z wird Head von List3 merge(List1,Rest22,Rest3) ),

List3 = [Z|Rest3].

(22)

Programmierstil und Techniken

Einfacheres Programm mit 3 Klauseln d.h. ohne or ; merge( [ ],List,List) :- !, .

merge(List, [ ],List) :- !, .

merge([X|Rest1],[Y|Rest2],[X|Rest3]) :-

X<Y,!,merge(Rest1,[Y|Rest2],Rest3]).

merge(List1],[Y|Rest2],[Y|Rest3]) :-

merge(List1,Rest2,Rest3)

Einfacheres Programm mit 3 Klauseln d.h. ohne or ; merge( [ ],List,List) :- !, .

merge(List, [ ],List) :- !, .

merge([X|Rest1],[Y|Rest2],[X|Rest3]) :-

X<Y,!,merge(Rest1,[Y|Rest2],Rest3]).

merge(List1],[Y|Rest2],[Y|Rest3]) :-

merge(List1,Rest2,Rest3)

(23)

Programmierstil und Techniken

Kommentare: nicht zu lang und nicht zu kurz Zweck, top level Prädikate, Hauptkonzepte merge(L1,L2,L3) merge/3

input mit + output mit - kennzeichnen merge(+L1,+L2,-L3)

Kommentare: nicht zu lang und nicht zu kurz Zweck, top level Prädikate, Hauptkonzepte merge(L1,L2,L3) merge/3

input mit + output mit - kennzeichnen merge(+L1,+L2,-L3)

(24)

Programmierstil und Techniken

Debugging

Wenn ein Prolog Programm nicht das erwartete Verhalten zeigt, ist das Hauptproblem, den Fehler zu finden. Leichter einen Fehler für ein Teilproblem zu finden als für das ganze Programm

Testen kleiner Programmeinheiten. Wenn diese funktionieren wie erwartet, Übergang zu größeren Modulen

(1) Da Prolog interaktiv ist, kann jeder Programmteil direkt mit Fragen getestet werden.

(2) Jede Prologimplementation stellt Debugging Hilfsprädikate bereit Debugging

Wenn ein Prolog Programm nicht das erwartete Verhalten zeigt, ist das Hauptproblem, den Fehler zu finden. Leichter einen Fehler für ein Teilproblem zu finden als für das ganze Programm

Testen kleiner Programmeinheiten. Wenn diese funktionieren wie erwartet, Übergang zu größeren Modulen

(1) Da Prolog interaktiv ist, kann jeder Programmteil direkt mit Fragen getestet werden.

(2) Jede Prologimplementation stellt Debugging Hilfsprädikate bereit

(25)

Programmierstil und Techniken

Basis des Tracing: Informationen, welche die Lösung eines Goals betreffen, werden während der Ausführung angezeigt.

trace, notrace

do Prädikatname + Argumente

exit Im Erfolgsfall Argumentwerte, sonst fail redo Prädikataufruf durch Backtracking

zwischen do und exit kann die Lösung aller Subgoals verfolgt werden

Detailiertes Tracing ist für größere Programme zu extzessiv. Trace für eine spezifizierte Teilmenge von Goals:

spy(Goal), nospy(Goal=

Mehrere Prädikate können gleichzeitig für spy offen sein.

Siehe SWI Seite für weitere Informationen zum debugging.

Basis des Tracing: Informationen, welche die Lösung eines Goals betreffen, werden während der Ausführung angezeigt.

trace, notrace

do Prädikatname + Argumente

exit Im Erfolgsfall Argumentwerte, sonst fail redo Prädikataufruf durch Backtracking

zwischen do und exit kann die Lösung aller Subgoals verfolgt werden

Detailiertes Tracing ist für größere Programme zu extzessiv. Trace für eine spezifizierte Teilmenge von Goals:

spy(Goal), nospy(Goal=

Mehrere Prädikate können gleichzeitig für spy offen sein.

Siehe SWI Seite für weitere Informationen zum debugging.

(26)

Tokenizer

Zeichenweise von einer Datei einlesen

Zerlege die Zeichenfolge in Token

Wandle die Token in Prolog-Atome um

Erkenne das Satzende und gib die Atomliste zurück.

Einstiegsprogramm siehe Kursseite, fertiger Tokenizer siehe Leiss-Skript

Zeichenweise von einer Datei einlesen

Zerlege die Zeichenfolge in Token

Wandle die Token in Prolog-Atome um

Erkenne das Satzende und gib die Atomliste zurück.

Einstiegsprogramm siehe Kursseite, fertiger Tokenizer siehe Leiss-Skript

(27)

Hausaufgabe

Verstehen Sie den gelieferten Tokenizer lite. Fügen Sie ein tokenize/4 ein, das führende Leerzeichen entfernt.

Machen Sie den Tokenizer robust gegen Dateiende

Nochmals versuchen den Tokenizer im Leiss Skript zu verstehen Programm abschreiben und zum Laufen bringen

Bratko Kapitel 8 lesen

Verstehen Sie den gelieferten Tokenizer lite. Fügen Sie ein tokenize/4 ein, das führende Leerzeichen entfernt.

Machen Sie den Tokenizer robust gegen Dateiende

Nochmals versuchen den Tokenizer im Leiss Skript zu verstehen Programm abschreiben und zum Laufen bringen

Bratko Kapitel 8 lesen

Referenzen

ÄHNLICHE DOKUMENTE

der entsprechende Personenkreis. Als Repräsentanten des Versicherungsnehmers oder der Mitversicherten gelten jeweils auch die für diese verantwortlich handelnden Montage-/-

Die Begründung der Entscheidung des BGH war erst kurz vor diesem Zeitpunkt (Anfang Juni 2021) veröffentlicht worden. Die Kreditinstitute haben ihre Kundinnen und Kunden vielfach

Die Ergebnisse der Regressionsanalyse ver- deutlichen vielmehr, dass der stärkste Einfluss auf die tatsächliche Nutzung von PPAK von Verpächtern und Dritten ausgeht: Die

a) Absicherung des Kreditwürdigkeitsurteils ... Vertriebsverträge – insbesondere der Vertragshändler- vertrag ... Miet- und Pachtverträge ... Directors &amp;

die Bezahlung eines be- stimmten Betrages in Abhängigkeit vom Umsatz oder Gewinn des ver- kauften Unternehmens vereinbart worden, bedeutet dies, dass der Käu- fer in der Führung

Eine Gefährdung des Vertragszwecks ist erst anzunehmen, wenn mit der Einschränkung der Leistung der Vertrag ausgehöhlt werden kann und damit in Bezug auf das zu versichernde

Zivilsenat des Hanseatischen Oberlandesgerichts in Bremen (OLG Bremen) hat durch Urteil vom 15.06.2017 (Az. 5 U 16/16) Klauseln in Allgemeinen Geschäftsbedingungen (AGB) eines

Wenn ein Fehlbetrag in einer Kasse festgestellt wird, dürfen Arbeitgeber diese Beträge nicht ein­.. fach vom Gehalt abziehen, selbst wenn in diesem Zeitraum nur eine Person an