Listen und Akkumulatoren Weitere Beispiele zur Listenmanipulation Akkumulatoren zur Effizienzsteigerung Nicht-deterministischer Automat Quicksort mit Prolog.

Slides:



Advertisements
Ähnliche Präsentationen
Programmieren in Logik
Advertisements

Entscheidungsunterstützungssysteme -
Programmierung 1 - Repetitorium WS 2002/2003 Programmierung 1 - Repetitorium Andreas Augustin und Marc Wagner Homepage:
Programmierung 1 - Repetitorium
Sortieren I - Bubblesort -
Das LCA – Problem in Suffixbäumen
Zusammenfassung der Vorwoche
Lineare Suche Divide-and-Conquer-Suche Kombinationssuche
Suche in Texten (Stringsuche )
Listen [mia, vincent, jules, yolanda] [mia, robber(honey_bunny), X, 2, mia] [] [mia, [vincent, jules], [butch, girlfriend(butch)]] [[], dead(zed), [2,
Friedhelm Meyer auf der Heide 1 HEINZ NIXDORF INSTITUT Universität Paderborn Algorithmen und Komplexität Notationen A = ist eine endliche, nichtleere menge,
Kapitel 4 Syntaktische Analyse: LR Parsing.
Listen & Beweisstrategie
Rekursive Listenverarbeitung
Sortierverfahren Richard Göbel.
Motivation Richard Göbel.
Dynamischer Speicher. In einer Funktion wird z.B. mit der Deklaration int i; Speicher auf dem sogenannten Stack reserviert. Wenn die Funktion verlassen.
Vorlesung Informatik 2 Algorithmen und Datenstrukturen (18 - Bäume: Durchlaufreihenfolgen, Analyse nat. Bäume) Prof. Th. Ottmann.
Informatik II, SS 2008 Algorithmen und Datenstrukturen Vorlesung 2 Prof. Dr. Thomas Ottmann Algorithmen & Datenstrukturen, Institut für Informatik Fakultät.
Informatik II, SS 2008 Algorithmen und Datenstrukturen Vorlesung 16 Prof. Dr. Thomas Ottmann Algorithmen & Datenstrukturen, Institut für Informatik Fakultät.
Vorlesung Informatik 3 Einführung in die Theoretische Informatik (17 –Turingmaschinen) Prof. Dr. Th. Ottmann.
Verschachtelte Listen, Differenzlisten, Graphen
Fakten, Regeln und Anfragen
EINI-I Einführung in die Informatik für Naturwissenschaftler und Ingenieure I Kapitel 7 Claudio Moraga, Gisbert Dittrich FBI Unido
EINI-I Einführung in die Informatik für Naturwissenschaftler und Ingenieure I Vorlesung 2 SWS WS 99/00 Gisbert Dittrich FBI Unido
6 Folgen (Teil II - Datenstrukturen und Algorithmen)
Klausur „Diskrete Mathematik II“
Günter Kniesel Advanced Prolog. 2 Bisher: Grundlagen Klauseln –Regeln –Fakten Terme –Die einzige Datenstruktur in Prolog –Listen als Sonderfall mit eigener.
Programmierung 1 - Repetitorium WS 2002/2003 Programmierung 1 - Repetitorium Andreas Augustin und Marc Wagner Homepage:
Programmierung 1 - Repetitorium WS 2002/2003 Programmierung 1 - Repetitorium Andreas Augustin und Marc Wagner Homepage:
Rekursion Richard Göbel.
Kurt Mehlhorn Konstantinos Panagiotou
Rekursion mit Listen: Quicksort
Computational Thinking Suchen und Sortieren [Ordnung muss sein…]
Einführung in die Informatik für Naturwissenschaftler und Ingenieure (alias Einführung in die Programmierung) (Vorlesung) Prof. Dr. Günter Rudolph Fachbereich.
Sortieralgorithmen Sortieren von Arrays.
Effiziente Algorithmen
Effiziente Algorithmen
Einführung in die Informatik für Naturwissenschaftler und Ingenieure (alias Einführung in die Programmierung) (Vorlesung) Prof. Dr. Günter Rudolph Fakultät.
Institut für Wirtschaftsinformatik – Software Engineering, JKU Linz 1 Algorithmen und Datenstrukturen SS 2005 Mag.Th. Hilpold u. Dr. A.Stritzinger Institut.
2.4 Rekursion Klassifikation und Beispiele
Grundlagen der Informatik - Prof. Slany 1 Grundlagen der Informatik Prof. Wolfgang SLANY.
Einfach und doppelt verkettete Listen in JAVA by Jens Weibler
Algorithmen und Datenstrukturen Übungsmodul 8
Institut für Wirtschaftsinformatik – Software Engineering, JKU Linz 1 Thomas Hilpold: Algorithmen und Datenstrukturen SS 2005 Mag.Th. Hilpold u. Dr. A.Stritzinger.
SWE1 / Übung 10 ( ) Rekursion Binärbäume.
Einführung in die Informatik für Naturwissenschaftler und Ingenieure (alias Einführung in die Programmierung) (Vorlesung) Prof. Dr. Günter Rudolph Fachbereich.
1 Albert-Ludwigs-Universität Freiburg Rechnernetze und Telematik Prof. Dr. Christian Schindelhauer Informatik III Christian Schindelhauer Wintersemester.
SFZ FN Sj. 13/14 Python 3 Rekursion Inf K1/2 Sj 13/14
Wintersemester 2005 / Vorlesung
Inhalt Einordnung und Funktion der lexikalische Analyse Grundlagen
Mag. Thomas Hilpold, Universität Linz, Institut für Wirtschaftsinformatik – Software Engineering 1 Algorithmen und Datenstrukturen 1 SS 2002 Mag.Thomas.
Java-Kurs Übung Besprechung der Hausaufgabe
M a r c – o l i v e r p a h l Informatik II – Kapitel 12 „Sortier-Algorithmen“ Zusammenfassung des Kapitel 12 Küchlin, Weber, Einführung in die Informatik,
Funktionen. Aufgabe : Eingabe zweier Zahlen ---> Minimum bestimmen Dann nochmals Eingabe zweier Zahlen ---> Minimum bestimmen.
Sortierverfahren Mit VB 2010 express edition JBS Tr, info Q1.
 Am Ende der letzten Stunde hatten wir über die Grenzen unserer Automaten-Modell gesprochen. Dr. Lars Ettelt2  Tipp: Parkhaus.  Einfahrt erst wenn.
Pointer, Arrays und verkettete Listen. Mehrdimensionale Arrays  Pointer auf ein Array von Pointern  int32 **matrix = new int32*[3];  matrix: Zeiger.
Tutorium Software-Engineering SS14 Florian Manghofer.
Dr. Wolfram Amme, Automatische Speicherverwaltung, Informatik II, FSU Jena, SS Automatische Speicherverwaltung.
Cut und Ablaufsteuerung Das Cut Goal mit Beispielen Negation als Failure Probleme mit Cut und Negation Das Cut Goal mit Beispielen Negation als Failure.
Datenstrukturen DCG Grammatiken Tutorial II Leiss Skript Grammatiken S.65 - S.77 Operationen auf Datenstrukturen Bäume Nachtrag Sehr kurz Operationen auf.
Rekursion und Listen Wiederholung: Bratko Kapitel 1 und 2, was haben wir gelernt Prinzip der Rekursion Listen, Listen, Listen Etwas komplexere Beispielprogramme.
Klausur „Diskrete Mathematik II“
Gliederung 0. Motivation und Einordnung 1. Endliche Automaten
Prolog-Kurs SomSem 2017 Daniel Beßler/Hagen Langer
Laufzeitverhalten beim Sortieren
1. Die rekursive Datenstruktur Liste 1.3 Rekursive Funktionen
1. Die rekursive Datenstruktur Liste 1.5 Das Entwurfsmuster Kompositum
REKURSION + ITERATION.
 Präsentation transkript:

Listen und Akkumulatoren Weitere Beispiele zur Listenmanipulation Akkumulatoren zur Effizienzsteigerung Nicht-deterministischer Automat Quicksort mit Prolog Weitere Beispiele zur Listenmanipulation Akkumulatoren zur Effizienzsteigerung Nicht-deterministischer Automat Quicksort mit Prolog

Ein Element an eine Liste anhängen, ein Element löschen add(X,L[X|L]). Das neue Element ist einfach der neue Kopf. del(X,L,L1) (1) ist X der Kopf, einfacher Fall del(X,[X|Tail],Tail) (2) ist X in Tail wird es dort gelöscht del(X,[Y|Tail],[Y|TailL1]):- del(X,Tail, TailL1). del ergibt fail, wenn das zu löschende Element nicht in der Liste ist über backtracking können alle anderen Elemente X aus der Liste gelöscht werden (immer nur eins, nicht alle). del kann auch dazu benutzt werden ein Element an einer beliebigen Stelle in die Liste einzufügen. ?- del(a,L,[1,2,3]) durch backtracking wird 'a' nach hinten durchgereicht. insert(X,List, BiggerList) :- del(X,BiggerList, List). add(X,L[X|L]). Das neue Element ist einfach der neue Kopf. del(X,L,L1) (1) ist X der Kopf, einfacher Fall del(X,[X|Tail],Tail) (2) ist X in Tail wird es dort gelöscht del(X,[Y|Tail],[Y|TailL1]):- del(X,Tail, TailL1). del ergibt fail, wenn das zu löschende Element nicht in der Liste ist über backtracking können alle anderen Elemente X aus der Liste gelöscht werden (immer nur eins, nicht alle). del kann auch dazu benutzt werden ein Element an einer beliebigen Stelle in die Liste einzufügen. ?- del(a,L,[1,2,3]) durch backtracking wird 'a' nach hinten durchgereicht. insert(X,List, BiggerList) :- del(X,BiggerList, List).

Ein Element löschen loesche(X,[X|L],L). loesche(X,[Y|L],[Y|L1]):- loesche(X,L,L1). [trace] ?- loesche(1,[1,2,1,3],L). Call: (7) loesche(1, [1, 2, 1, 3], _G9797) ? creep Exit: (7) loesche(1, [1, 2, 1, 3], [2, 1, 3]) ? creep L = [2, 1, 3] ; Redo: (7) loesche(1, [1, 2, 1, 3], _G9797) ? creep Call: (8) loesche(1, [2, 1, 3], _G9876) ? creep Call: (9) loesche(1, [1, 3], _G9879) ? creep Exit: (9) loesche(1, [1, 3], [3]) ? creep Exit: (8) loesche(1, [2, 1, 3], [2, 3]) ? creep Exit: (7) loesche(1, [1, 2, 1, 3], [1, 2, 3]) ? creep L = [1, 2, 3] ; Durch Backtracking werden konsekutiv die 1en gelöscht loesche(X,[X|L],L). loesche(X,[Y|L],[Y|L1]):- loesche(X,L,L1). [trace] ?- loesche(1,[1,2,1,3],L). Call: (7) loesche(1, [1, 2, 1, 3], _G9797) ? creep Exit: (7) loesche(1, [1, 2, 1, 3], [2, 1, 3]) ? creep L = [2, 1, 3] ; Redo: (7) loesche(1, [1, 2, 1, 3], _G9797) ? creep Call: (8) loesche(1, [2, 1, 3], _G9876) ? creep Call: (9) loesche(1, [1, 3], _G9879) ? creep Exit: (9) loesche(1, [1, 3], [3]) ? creep Exit: (8) loesche(1, [2, 1, 3], [2, 3]) ? creep Exit: (7) loesche(1, [1, 2, 1, 3], [1, 2, 3]) ? creep L = [1, 2, 3] ; Durch Backtracking werden konsekutiv die 1en gelöscht

Sublist S ist eine Subliste von L wenn (1) L in zwei Listen L1 und L2 zerlegt werden kann (2) L2 in S und eine Liste L3 zerlegt werden kann. sublist(S,L):- append(L1,L2,L), append(S,L3,L2). ?- sublist([c,d,e],[a,b,c,d,e,f]) ?- sublist([c,e][a,b,c,d,e,f]) generiere "alle" Sublisten: ?- sublist(S,[a,b,c]). ausprobieren: übergeneriert z.B. [ ] zweimal, warum? S ist eine Subliste von L wenn (1) L in zwei Listen L1 und L2 zerlegt werden kann (2) L2 in S und eine Liste L3 zerlegt werden kann. sublist(S,L):- append(L1,L2,L), append(S,L3,L2). ?- sublist([c,d,e],[a,b,c,d,e,f]) ?- sublist([c,e][a,b,c,d,e,f]) generiere "alle" Sublisten: ?- sublist(S,[a,b,c]). ausprobieren: übergeneriert z.B. [ ] zweimal, warum?

Permutationen Zweistelliges Prädikat, ein Argument ist die Ausgangsliste, das andere die permutierte Variante. (1) wenn die erste Liste leer ist, muss die zweite auch leer sein (2) wenn die erste Liste nicht leer ist, so hat sie die Form [X|L] und eine Permutation kann wie folgt erstellt werden: erstelle erst eine permutation L1 von L (rekursiver Aufruf) und füge dann X an jeder Stelle von L1 ein um jeweils eine andere Permutation zu erhalten. Zweistelliges Prädikat, ein Argument ist die Ausgangsliste, das andere die permutierte Variante. (1) wenn die erste Liste leer ist, muss die zweite auch leer sein (2) wenn die erste Liste nicht leer ist, so hat sie die Form [X|L] und eine Permutation kann wie folgt erstellt werden: erstelle erst eine permutation L1 von L (rekursiver Aufruf) und füge dann X an jeder Stelle von L1 ein um jeweils eine andere Permutation zu erhalten. L L1 X permutiere L zu L1 füge X in L1 ein

Permutationen pemutation([ ],[ ]). pemutation([X|L],P):- permutation(L,L1), insert(X,L1,P). oder alternativ: lösche ein Element X von der ersten Liste, permutiere den Rest zu P und füge X am Beginn von P ein. pemutation2([ ],[ ]). pemutation2(L,[X|P]):- del(X,L,L1), permutation2(L1,P). ?- permutation([red,blue,green],P). P=[red,blue,green] P=[red,green,blue] P=[blue,red,green]... pemutation([ ],[ ]). pemutation([X|L],P):- permutation(L,L1), insert(X,L1,P). oder alternativ: lösche ein Element X von der ersten Liste, permutiere den Rest zu P und füge X am Beginn von P ein. pemutation2([ ],[ ]). pemutation2(L,[X|P]):- del(X,L,L1), permutation2(L1,P). ?- permutation([red,blue,green],P). P=[red,blue,green] P=[red,green,blue] P=[blue,red,green]...

Akkumulatoren Die bisherigen Beispiele zur rekursiven Programmierung konnten keine Zwischenergebnisse mitführen. Der Wert eines rekursiven Aufrufs war unabhängig vom Kontext. Beispiel umkehren einer Liste = Reihenfolge der Elemente umdrehen. [1,2,3,4] → [4,3,2,1] Mit append: reverse([ ],[ ]). reverse([X|L],R) :- reverse(L,RL), append(RL,[X ],R). %X rutscht von vorne nach hinten Die bisherigen Beispiele zur rekursiven Programmierung konnten keine Zwischenergebnisse mitführen. Der Wert eines rekursiven Aufrufs war unabhängig vom Kontext. Beispiel umkehren einer Liste = Reihenfolge der Elemente umdrehen. [1,2,3,4] → [4,3,2,1] Mit append: reverse([ ],[ ]). reverse([X|L],R) :- reverse(L,RL), append(RL,[X ],R). %X rutscht von vorne nach hinten

Akkumulatoren [1,2,3,4] → [4,3,2,1] Mit append: reverse([ ],[ ]). reverse([X|L],R) :- reverse(L,RL), append(RL,[X ],R). Wie lange wird reverse rekursiv aufgerufen? Bis die Eingangsliste beim letzten Element angekommen ist: L ist leer und X ist 4! Dann matcht reverse([ ],[ ]). Es ergibt sich RL ist [ ]. append wird zum ersten mal aufgerufen: [ ] wird an X angehängt. [1,2,3,4] → [4,3,2,1] Mit append: reverse([ ],[ ]). reverse([X|L],R) :- reverse(L,RL), append(RL,[X ],R). Wie lange wird reverse rekursiv aufgerufen? Bis die Eingangsliste beim letzten Element angekommen ist: L ist leer und X ist 4! Dann matcht reverse([ ],[ ]). Es ergibt sich RL ist [ ]. append wird zum ersten mal aufgerufen: [ ] wird an X angehängt.

Akkumulatoren [1,2,3,4] → [4,3,2,1] Mit append: reverse([ ],[ ]). reverse([X|L],R) :- reverse(L,RL), append(RL,[X ],R). die Ausgabeliste des ersten append Aufrufs ist [x]. Vorletzer rekursiver Aufruf(Aufstieg). reverse([3|4],R) reverse(L=[4], RL = [4]) und damit wird append mit append([4],[3],R) aufgerufen und R wird: [4,3]. und so weiter und sofort. Aufgabe: machen Sie sich den ganzen Aufstieg klar, bis die Liste umgedreht ist. [1,2,3,4] → [4,3,2,1] Mit append: reverse([ ],[ ]). reverse([X|L],R) :- reverse(L,RL), append(RL,[X ],R). die Ausgabeliste des ersten append Aufrufs ist [x]. Vorletzer rekursiver Aufruf(Aufstieg). reverse([3|4],R) reverse(L=[4], RL = [4]) und damit wird append mit append([4],[3],R) aufgerufen und R wird: [4,3]. und so weiter und sofort. Aufgabe: machen Sie sich den ganzen Aufstieg klar, bis die Liste umgedreht ist.

Akkumulatoren [1,2,3,4] → [4,3,2,1] Mit append: reverse([ ],[ ]). reverse([X|L],R) :- reverse(L,RL), append(RL,[X ],R). was ist der Nachteil dieser Vorgehensweise: append ist linear wird aber für jedes Element der Liste wieder aufgerufen: insgesamt wird der Aufwand für reverse quadratisch (Details im Leiss-Skript Seite 20/21). Implementation mit Akkumulator: ● Staple die Elemente der Eingabeliste auf eine Liste von ● Zwischenergebnissen(=Akkumulator) ● Beginne mit dem leeren Stapel ● Gib den Stapel aus, wenn die Eingabeliste leer ist [1,2,3,4] → [4,3,2,1] Mit append: reverse([ ],[ ]). reverse([X|L],R) :- reverse(L,RL), append(RL,[X ],R). was ist der Nachteil dieser Vorgehensweise: append ist linear wird aber für jedes Element der Liste wieder aufgerufen: insgesamt wird der Aufwand für reverse quadratisch (Details im Leiss-Skript Seite 20/21). Implementation mit Akkumulator: ● Staple die Elemente der Eingabeliste auf eine Liste von ● Zwischenergebnissen(=Akkumulator) ● Beginne mit dem leeren Stapel ● Gib den Stapel aus, wenn die Eingabeliste leer ist

Reverse mit Akkumulator reverse(L,R) :- reverse_acc(L,[ ],R). reverse_acc([X|L],Acc,R):- reverse_acc(L,[X|Acc],R). reverse_acc([],Acc,Acc). Die Eingabeliste [1,2,3,4] wird der Reihe nach geköpft und auf den Akkumulator geschrieben. Wenn die Liste leer ist wird der Akkumulator auf die Ausgabeliste geschoben und diese nach oben durchgereicht bis schliesslich das zweistellige Aufrufprädikat reverse erreicht wird. Der Algorithmus ist linear in der Größe der Eingabe. Aufgabe: machen Sie sich klar warum reverse(L,R) :- reverse_acc(L,[ ],R). reverse_acc([X|L],Acc,R):- reverse_acc(L,[X|Acc],R). reverse_acc([],Acc,Acc). Die Eingabeliste [1,2,3,4] wird der Reihe nach geköpft und auf den Akkumulator geschrieben. Wenn die Liste leer ist wird der Akkumulator auf die Ausgabeliste geschoben und diese nach oben durchgereicht bis schliesslich das zweistellige Aufrufprädikat reverse erreicht wird. Der Algorithmus ist linear in der Größe der Eingabe. Aufgabe: machen Sie sich klar warum

Anzahl der Elemente einer Liste Lösung ohne Akkumulator: len([ ],0). len([H|T],N) :- len(T,N1), N is N1 +1. Aufgabe: denken Sie darüber nach, wie das Programm für die Liste [1,2,3,4] abläuft. Das rekursive Prädikat köpft die Liste und ruft mit der Restliste rekursiv auf. Die Rekursion stoppt, wenn T = [ ] und somit N1 = 0. Damit wird N für den letzten rekursiven Aufruf 1. Bedeutet das, dass schon die leere Liste Länge 1 hat? Lösung ohne Akkumulator: len([ ],0). len([H|T],N) :- len(T,N1), N is N1 +1. Aufgabe: denken Sie darüber nach, wie das Programm für die Liste [1,2,3,4] abläuft. Das rekursive Prädikat köpft die Liste und ruft mit der Restliste rekursiv auf. Die Rekursion stoppt, wenn T = [ ] und somit N1 = 0. Damit wird N für den letzten rekursiven Aufruf 1. Bedeutet das, dass schon die leere Liste Länge 1 hat?

Anzahl der Elemente einer Liste Lösung mit Akkumulator: len2(L,N,) :- lenacc(L,0,N). lenacc([],Acc,Acc). lenacc([H|T],Acc,N) :- Acc1 is Acc +1, lenacc(T,Acc1,N). Klarmachen: der neue Aufruf hat jeweils um 1 erhöhtem Akkumulator und um 1 verkürzte Liste. In prozeduralen Programmiersprachen arbeitet man mit Iteration und einer Variablen, die Skopus über die gesamte Iteration hat. In Prolog wird eine Hilfsvariable mit einem Startwert mitgeführt die jeweils an den nächsten rekursiven Aufruf übergeben wird. Bei Ende der Rekursion steht das Ergebnis unmittelbar in der Hilfsvariablen. Lösung mit Akkumulator: len2(L,N,) :- lenacc(L,0,N). lenacc([],Acc,Acc). lenacc([H|T],Acc,N) :- Acc1 is Acc +1, lenacc(T,Acc1,N). Klarmachen: der neue Aufruf hat jeweils um 1 erhöhtem Akkumulator und um 1 verkürzte Liste. In prozeduralen Programmiersprachen arbeitet man mit Iteration und einer Variablen, die Skopus über die gesamte Iteration hat. In Prolog wird eine Hilfsvariable mit einem Startwert mitgeführt die jeweils an den nächsten rekursiven Aufruf übergeben wird. Bei Ende der Rekursion steht das Ergebnis unmittelbar in der Hilfsvariablen.

Nicht-deterministischer Automat vgl. Bratko S.94ff Eine abstrakte Maschine, die Input einliest, etwa einen String von Symbolen und die ● Entscheidet einen String abzulehnen oder zu akzeptieren ● Eine Reihe von Zuständen hat und immer in einem Zustand ist ● Von einem Zustand in den andern gehen kann ● Deren interne Struktur als Transitionsgraph repräsentiert werden kann Eine abstrakte Maschine, die Input einliest, etwa einen String von Symbolen und die ● Entscheidet einen String abzulehnen oder zu akzeptieren ● Eine Reihe von Zuständen hat und immer in einem Zustand ist ● Von einem Zustand in den andern gehen kann ● Deren interne Struktur als Transitionsgraph repräsentiert werden kann

Nicht-deterministischer Automat vgl. Bratko S.94ff S3S3 S2S2 S4S4 a b a b null S1

Nicht-deterministischer Automat vgl. Bratko S.94ff Der Automat akzeptiert einen String wenn: (1) er startet in irgendeinem Initialzustand (2) er endet in einem Finalzustand (3) die Übergangslabels auf dem Pfad korrespondieren mit dem gesamten Inputstring Automatenrepräsentation in Prolog: (a) unäre Relation final(S3) (b) 3-stellige Übergangsrelation trans(S1,X,S2) (c) binäre Übergangsrelation silent(S1,S2) Der Automat akzeptiert einen String wenn: (1) er startet in irgendeinem Initialzustand (2) er endet in einem Finalzustand (3) die Übergangslabels auf dem Pfad korrespondieren mit dem gesamten Inputstring Automatenrepräsentation in Prolog: (a) unäre Relation final(S3) (b) 3-stellige Übergangsrelation trans(S1,X,S2) (c) binäre Übergangsrelation silent(S1,S2)

Nicht-deterministischer Automat vgl. Bratko S.94ff Beispiel aus dem Übergangsgraphen final(s3). trans(s1,a,s1). trans(s1,a,s2). trans(s1,b,s1). trans(s2,b,s3). trans(s3,b,s4). silent(s2,s4). silent(s3,s1). Inputstrings werden als Prologlisten etwa [a,a,b] übergeben Beispiel aus dem Übergangsgraphen final(s3). trans(s1,a,s1). trans(s1,a,s2). trans(s1,b,s1). trans(s2,b,s3). trans(s3,b,s4). silent(s2,s4). silent(s3,s1). Inputstrings werden als Prologlisten etwa [a,a,b] übergeben

Nicht-deterministischer Automat vgl. Bratko S.94ff accept Prädikat für Zustand State (1) leerer String wird akzeptiert, wenn für den Zustand State des Automaten final zutrifft (2) ein nicht-leerer String wird akzeptiert, wenn nach dem Lesen des ersten Symbols ein Zustand State1 erreicht wird, von dem aus der Reststring akzeptiert wird (3) ein nicht-leerer String wird akzeptiert, wenn durch einen silent move (Spontanübergang) ein State1 erreicht wird, von dem aus der String akzeptiert wird accept Prädikat für Zustand State (1) leerer String wird akzeptiert, wenn für den Zustand State des Automaten final zutrifft (2) ein nicht-leerer String wird akzeptiert, wenn nach dem Lesen des ersten Symbols ein Zustand State1 erreicht wird, von dem aus der Reststring akzeptiert wird (3) ein nicht-leerer String wird akzeptiert, wenn durch einen silent move (Spontanübergang) ein State1 erreicht wird, von dem aus der String akzeptiert wird

Nicht-deterministischer Automat vgl. Bratko S.94ff accept(State,[ ]) :- final(State). accept(State[X|Reststring]) :- trans(State,X,State1), accept(State1,Reststring). accept(State,String) :- silent(State,State1), accept(State1,String). accept(State,[ ]) :- final(State). accept(State[X|Reststring]) :- trans(State,X,State1), accept(State1,Reststring). accept(State,String) :- silent(State,State1), accept(State1,String). X first rest null string

Nicht-deterministischer Automat vgl. Bratko S. 94ff Anwendungen Entscheide eine Eingabe ?- accept(S1,[a,a,a,b]) yes. Gib alle akzeptierten Strings der Länge 3 von s1 als Startzustand aus – Teilsprache des Automaten. ?- accept(s1,[X1,X2,X3]). X1=a X2=a X3 =b; X1=b X2=a X3 =b; no. ?- String=[_,_,_], accept(s1,String). Ausgabe? Anwendungen Entscheide eine Eingabe ?- accept(S1,[a,a,a,b]) yes. Gib alle akzeptierten Strings der Länge 3 von s1 als Startzustand aus – Teilsprache des Automaten. ?- accept(s1,[X1,X2,X3]). X1=a X2=a X3 =b; X1=b X2=a X3 =b; no. ?- String=[_,_,_], accept(s1,String). Ausgabe?

Quicksort Klassischer sehr effizienter Sortieralgorithmus nach dem Prinzip „teile und herrsche“. (vgl. Skript Hans Leiss, S. 22) Sortiere eine Liste L von Zahlen nach ihrer Größe zu L' (i) Wähle ein Element aus X (ii) Zerlege L in eine Liste Bigger, in der alle Elemente Y>= X und eine Liste Smaller, in der alle Elemente Y < X (iii) Sortiere die Listen Bigger und Smaller nach dem gleichen Prinzip (Rekursion) (iv) Bilde L' durch append(Bigger', [X|Smaller'],L') Klassischer sehr effizienter Sortieralgorithmus nach dem Prinzip „teile und herrsche“. (vgl. Skript Hans Leiss, S. 22) Sortiere eine Liste L von Zahlen nach ihrer Größe zu L' (i) Wähle ein Element aus X (ii) Zerlege L in eine Liste Bigger, in der alle Elemente Y>= X und eine Liste Smaller, in der alle Elemente Y < X (iii) Sortiere die Listen Bigger und Smaller nach dem gleichen Prinzip (Rekursion) (iv) Bilde L' durch append(Bigger', [X|Smaller'],L')

Quicksort quicksort([ ],[ ]). quicksort([ X|Xs],Ys):- partition(X,Xs,Big,Small), quicksort(Big,Bs), quicksort(Small,Ss), append(Bs,[X|Ss],Ys). quicksort([ ],[ ]). quicksort([ X|Xs],Ys):- partition(X,Xs,Big,Small), quicksort(Big,Bs), quicksort(Small,Ss), append(Bs,[X|Ss],Ys).

Quicksort partition(_,[ ],[ ],[ ]). partition(X,[Z|Zs], ZsBig, [Z|ZsSmall]) :- Z<X, partition(X,Zs, ZsBig, ZsSmall). partition(X,[Z|Zs], [Z|ZsBig], ZsSmall) :- Z>=X, partition(X,Zs, ZsBig, ZsSmall). Beispielaufruf: quicksort wird mit [2,4,3,1] gestartet: 1. Aufruf partition(2,[4,3,1],Big,Small). Da 4 >= 2 matcht 3. partition Regel 2. (rekursiver) Aufruf: partition(2,[3,1],ZsBig,ZsSmall) Liste Big wird zusammengebaut wenn Rekursion zurückkehrt und Tail ZsBig belegt. Da 3>= 2 matcht wieder die 3. Regel 3. (rekursiver) Aufruf: partition(2,[1],ZsBig,ZsSmall) Da 1 < 2 matcht 2. Regel. 4. (rekursver) Aufruf: partition(2,[],ZB,ZS). Da Verarbeitungsliste leer ist matcht die 1. Regel. Zusammenbau erfolgt und Big wird mit [4,3] Small mit [1] an Quicksort zurückgegeben. partition(_,[ ],[ ],[ ]). partition(X,[Z|Zs], ZsBig, [Z|ZsSmall]) :- Z<X, partition(X,Zs, ZsBig, ZsSmall). partition(X,[Z|Zs], [Z|ZsBig], ZsSmall) :- Z>=X, partition(X,Zs, ZsBig, ZsSmall). Beispielaufruf: quicksort wird mit [2,4,3,1] gestartet: 1. Aufruf partition(2,[4,3,1],Big,Small). Da 4 >= 2 matcht 3. partition Regel 2. (rekursiver) Aufruf: partition(2,[3,1],ZsBig,ZsSmall) Liste Big wird zusammengebaut wenn Rekursion zurückkehrt und Tail ZsBig belegt. Da 3>= 2 matcht wieder die 3. Regel 3. (rekursiver) Aufruf: partition(2,[1],ZsBig,ZsSmall) Da 1 < 2 matcht 2. Regel. 4. (rekursver) Aufruf: partition(2,[],ZB,ZS). Da Verarbeitungsliste leer ist matcht die 1. Regel. Zusammenbau erfolgt und Big wird mit [4,3] Small mit [1] an Quicksort zurückgegeben.

Quicksort mit Akkumulator Spare append Aufrufe: akkumuliere alle schon gesehenen Eingabeelemente auf dem Akkumulator quicksort(Xs,Ys):- quicksort_acc(Xs,[ ],Ys). quicksort_acc([ X|Xs],Acc,Ys):- partition(X,Xs,Big,Small), quicksort_acc(Big,Acc,Zs), quicksort_acc(Small,[X|Zs],Ys). %Implementierung partition bleibt gleich Spare append Aufrufe: akkumuliere alle schon gesehenen Eingabeelemente auf dem Akkumulator quicksort(Xs,Ys):- quicksort_acc(Xs,[ ],Ys). quicksort_acc([ X|Xs],Acc,Ys):- partition(X,Xs,Big,Small), quicksort_acc(Big,Acc,Zs), quicksort_acc(Small,[X|Zs],Ys). %Implementierung partition bleibt gleich

Hausaufgabe (1) In den Skripten Hadersbeck und Leiss den Stand der Vorlesung verifizieren (Tipp: Hadersbeckskript, S.35) (2) In Bratko Kapitel 4 lesen, versuchen Sie alle 4 dargestellten Probleme und deren Lösung in Prolog zu verstehen. (3) Implementieren Sie die Programme für den Automaten und Quicksort und probieren Sie sie aus. (1) In den Skripten Hadersbeck und Leiss den Stand der Vorlesung verifizieren (Tipp: Hadersbeckskript, S.35) (2) In Bratko Kapitel 4 lesen, versuchen Sie alle 4 dargestellten Probleme und deren Lösung in Prolog zu verstehen. (3) Implementieren Sie die Programme für den Automaten und Quicksort und probieren Sie sie aus.