Ja, guten Morgen, alle zusammen. Also ich glaube,
für dies Weihnachten setzt sich der Trend zu Geschenkehaufen hiebs und zu Binärbäumen durch.
Nochmal einsteigen in die Vorlesung. Ja,
das letzte Mal hätten wir angefangen, darüber zu sprechen,
wie wir mithilfe funktionaler Programmierung kombinatorische Probleme lösen können und gegen
Ende einen der Klassiker besprochen, das Acht-Damen-Problem.
Wenn man das einfach so Direkt naiv, rekursiv programmiert,
dann wird es ziemlich kompliziert, das Vorstellen ziemlich langweilen.
Ich habe ja auch gleich wieder gemerkt, die Weggerate war größer als sonst.
Wir können uns jetzt mal gucken, wie wir ähnlich ist mit einer opposition.
Wir können mal gucken, wie wir ein ähnliches,
ein bisschen systematischer machen. Das ist eigentlich auch das,
worauf ich hinaus wollte, nämlich,
was ist typisch für Back-Tracking-Probleme überhaupt und wie können wir
die ein für alle mal in den Griff kriegen,
ohne jedes Mal von vorne anzufangen,
wie bei den Achtdamen
Es geht eben immer sehr gut und recht einfach im Funktionalen Programmierstil,
wenn wir das Problem, über das wir irgendwie kombinatorisch
eine Lösung finden wollen, darstellen können in Baumform.
Indem wir jeden Probierschritt in einem Zustandsraum repräsentieren. Wir brauchen
diskrete Zustände, keine kontinuierlichen. Und von jedem Zustand aus
sollten wir wenig Möglichkeiten da sein, wie man weiter probiert.
Also wenn wir hier unser Schachbrett haben,
dann wäre ein Zustand unserer Suche, wo wir gerade probieren,
na klappt es denn mit Achtsamen, dass wir in jeder Zeile,
in jeder Spalte hier eine Dame stehen haben und gucken,
bedrohen sie sich.
Und wenn wir das beschreiben können, würde unser nächster Probierschritt drin bestehen,
eine der Damen zu verschieben. Und das würde dazu führen,
dass wir von dem Zustand, wo wir gerade sind,
verschiedene Möglichkeiten haben, würden man die Dame verschieben kann.
Und bei jedem dieser wieder verschiedene Möglichkeiten und so weiter.
Und wir stellen im Allgemeinen einfach fest, ob wir
eine Lösung gefunden haben, indem wir einen Test anwenden.
Bedrohen sie sich oder nicht? Ja, und egal,
was das Problem ist, es sollte einen solchen Test geben.
Es sollte eine Möglichkeit geben, bei irgendeinem Zustand,
was er ist,
automatisch die Folgezustände zu generieren
Wir brauchen einen Staatszustand. Und wir brauchen einen Test,
um zu sagen, einen der Folgezustände, die wir ausgesucht haben,
überhaupt zulässig ist im Rahmen der Regeln, die wir haben.
Und genau diese Tests, wie komme ich von einem Knoten im Baum zum nächsten?
Wie stelle ich fest, ob ich fertig bin?
Das kann man wunderbar in einen Rahmen reinstecken.
Funktionieren halt einen Rahmen gegeben als Funktionen höhere Ordnung.
Und viele kleine Funktionen als Parameter, die genau dieses systematische
Suchen machen. Also was wir alles brauchen an Zutaten,
ganz allgemein, egal welches Backtracking-Problem das ist
Eine Datenstruktur für den Suchraum. Menge von Zuständen,
in diesem Beispiel die Position der Damen oder wenn wir einen
Weg durch ein Labyrinth suchen, Koordinaten im Labyrinth oder sowas.
Dann der Ausgangszustand, von dem wir beginnen wollen,
das sollten zu, dass jeder Zustand sein.
Zum Beispiel, wir stehen am Anfang am Eingang des Labyrinths.
Dann brauchen wir einen Generator. Funktionen, die jeden,
die einen Zustand nehmen kann und dann eine Liste erzeugt von
den möglichen Zuständen, wo wir hin könnten,
also die Unterbäume,
die wir
hier kriegen könnten
Und dann brauchen wir einen Test auf Zulässigkeit. Predikat,
mit dem wir prüfen können, ist der Zustand,
der vom Generator erzeugt wurde, zulässig im Hinblick auf alle weiteren Kriterien,
die wir noch so haben.
Ja, dass man im Labyrinth nicht durch die Hecke marschiert und so.
Einfach mal abkürzt. Und testet auf Erfolg, noch ein weiteres Prädikat,
das den erreichten Zustand anguckt und sagt Hurra, fertig.
Ja, oder eben nicht. So,
und das machen wir jetzt als eine Funktion höherer Ordnung.
General Backtracking, allgemeines Backtracking-Schema. Und die kriegt eben
vier Parameter,
Eine Funktion, General States,
die bildeten Zustand auf eine Liste von möglichen Folgezuständen ab.
Die geschweifen klammern, die sagen, die kann auch leer
sein, wenn es einfach keinen Folgezustand gibt.
Ist Legal, die nimmt einen Zustand als Argument und liefert
uns einen Wahrheitswert zurück. Ja, nein. Ist es
der Endzustand? Ja, auch wieder Zustand als Eingabe.
Und ein Bulien wahrheitswert als Ausgabe. Ja,
und das schreiben wir jetzt einfach mal als Funktion höherer Ordnung,
die Lösung aller Backtracking-Probleme
Also das Kind sollen heißen, General Backtracking. Wir übergeben
den Ausgangszustand, von wo wir in diesem Baum lossuchen.
Eine Funktion, die uns Folgezustandstände liefert.
Diesen Test ist der Zustand zulässig oder sind wir fertig?
Ja. Hier steht noch Mekors and Infinite Loop in dieser einfachen Form.
Könnten wir ein Problem haben. Dazu gehe ich nochmal ganz kurz
zurück. Ich habe die Bäume hier immer so gezeichnet,
dass es echte Bäume sind. Manche der Probleme,
die wir haben, könnten so geartet sein,
dass wir von einem solchen Zustand wieder zum Ausgangszustand zurückkommen in
der Endlosschleife sind.
Man muss
nur an Labyrinth denken,
Im Komfortausbau unserer Funktion müssen wir noch einen Test auf Zyklen einbauen.
Deshalb hier diese kleine Warnung. Wir gehen erst mal davon aus,
dass wir einen Zustandsraum haben, der Zyklen frei ist.
Wir definieren hier drin als erstes eine lokale Funktion 3. Die soll versuchen,
Folgezustände zu finden und eine Lösung zu finden. Die kriegt also,
wir sind irgendwo in unserem Baum, wo wir gesucht haben,
übergeben einen Zustand und, naja, man kann hier,
wenn sich so ein Backtrecking verläuft und nichts findet,
ist es ganz nett, man bildet hier einfach mal Testaufgaben ein,
deshalb steht hier das Displaylist Trying drin.
So, und jetzt kommt hier die Abfrage. Also wenn die Funktion ist Legal,
die wir übergeben, haben, sagt, Leute,
das war kein Zustand, der hier in diesem Suchraum vorkommt,
dann geben wir als Resultat zurück quäl.
Dieser Versuch hat nichts gebracht und geben auch noch netterweise den
Zustand mit, mit außen, die wir gerade sind.
Wenn es der Endzustand ist, dann sagen wir, gefunden,
jetzt haben wir unsere Lösung und dann machen wir einen Cons
und machen hier einen Aufruf für Alle weiteren Lösungen, ja.
Von dem Zustand, wo wir jetzt sind, versuchen wir auch noch
alle weiteren Lösungen zu finden und machen das rekursiv mit Try.
Und in allen anderen Fällen war weder illegal,
noch war es die Lösung, also müssen wir jetzt echt arbeiten.
Und in dem Fall machen wir ein Mapping über alle Aufrufe
von drei, für die gesamte Liste der Folgezustände
Was immer da an Lösung gefunden wird,
hängen wir mit Appent zusammen, dass das,
was es erpennt, macht, im Pentmap macht.
Das nimmt ja eine Funktion, eine Liste als Argument.
Also für jede der möglichen Folgezustände wird drei hier jetzt versuchen,
eine Lösung zu finden.
Und die binden wir alle mit Appent zusammen. So,
das ist also die Rekursive Suche mit Backtracking in einer Form
geschrieben, dass sie alle Lösungen findet.
Bitte nur bei endlichen Suchräumen anwenden. Kannst du einen
besonderen Grund, dass du das da in ein Komma steht
Los, das Lied. Ah, ja, scharfe Augen am. Also,
wenn wir uns zurückerinnern, viele,
viele Folien zurück in dieser Vorlesung, habe ich gesagt,
dass man auf keinen Fall syntaktisch verwenden sollte,
so ohne weiteres sind Kombatar,
die haben eine spezielle Beleute Bedeutung im Recket und listen.
Und das ist genau hier der Fall. Ich dachte,
ich könnte hier drüber hinwegbügeln, wegen nicht. Also,
erklären wir diese Syntaxen mal. Was wir hier haben,
ist eine Liste und wer ganz besonders scharfe Augen hat,
wird sehen, dieses Quotierungszeichen ist nicht das Quotierungszeichen,
was wir immer hatten,
ist der Spiegelverkehrte.
Das ist das Backquote
So, und ein Backquot behält sich für alle Zwecke wie ein normales Quartieren von Listen,
aber mit Ausnahmen und eine der Ausnahmen ist,
wenn wir hier ein kleines Komma machen, ja, dann wird der Ausdruck,
der dahinter steht, nicht wörtlich genommen, sondern ausgewertet.
Also was hier passiert ist, mit diesem Backquot,
wir kriegen eine Liste, wo die Variables steht,
ausgewertet wird, das Resultat eingesetzt wird und das ist das Resultat.
Diese Notation werden wir in der übernächsten Stunde noch brauchen,
wenn wir uns ein bisschen mit Makroprogrammierung in Liz beschäftigen,
dass mich genau das, was wir hier ausgenutzt haben,
das, mit dem wir Direktcode erzeugen können,
indem wir konstante quotierte Teile zusammensetzen mit ausgewerteten Variablen.
Und normalerweise macht man das immer, wenn man das Ganze übersichtlich schreiben will.
Also wir haben insgesamt einen quotierten Ausdruck und hier und da muss was Ausgewertetes reingesetzt werden,
indem man das alles mit Cons und Appent in riesen Ostdrücken vergleistet und kein Mensch kann es mehr lesen,
nimmt man diese Syntax,
macht ein kleines, komm mal hin und sagt,
also das hier werte jetzt mal aus und setzt genau der eine in die Liste.
Also das ist Also schon mal dran gewöhnen. Wir werden in Zukunft,
müssen wir bei dem Quotierungszeichen genau hinschauen, welches es ist,
ob es das Backquote ist oder auch Anquote genannt oder das Quotierungszeichen,
was wir hatten.
Okay, ansonsten, sonst noch Fragen, wo wir gerade unterbrochen haben?
Nein. Also das generelle Schema, eine Funktion schrei,
die unsere eins, zwei, drei Funktionen,
die wir hier übergeben haben, der Reihe nach anwendet.
Erstens testen dürfen wir hier sein oder ist der Zustand nicht zulässig,
ein Aufruf von dem,
ist das Resultat da
Wenn das Resultat ist,
ist es mit Cons anhängen einfach auf alles, was wir kriegen,
wenn wir rekursiv die Folgezustände expandieren und die mit Map zusammen haben,
also ein Mapping von 3 über alle Folgezustände,
mit Dependent verbunden und im anderen Fall tatsächlich loslegen und weiter suchen,
ob da in den Unterbäumen noch irgendwas ist,
bis wir letztendlich was gefunden haben.
Ich habe hier mal ein ganz simples Beispiel,
wie wir das machen können,
also das ist ein Problem,
was man normalerweise nicht mit probieren und teilen und Ärger löst
Aufzählen aller Zahlen von eins bis zu einer anderen Zahl N.
Aber wir können uns hier dran einmal anschauen,
wie im Grenzfall dieses Schema ist,
dass es sozusagen ein Testfall dafür, ob es im Allgemeinen klappt.
Wir wollen prüfen, gegeben eine normal natürliche Zahl N.
Und wir wollen jetzt versuchen, ob wir,
ob Piano recht hat und wir durch Addieren von eins um
die Nachfolger zu generieren, wirklich die Zahl NZ erreichen können.
So. In dem Fall die Folgezustände von N,
wer die Menge mit dem Nachfolger N plus 1 Der Zulässigkeitstest,
wer ist das N, bei dem wir jetzt gerade sind,
überhaupt noch kleiner als NZ, unser Ziel?
Und der Erfolg, wer ist das N,
was wir erreicht haben, tatsächlich gleich NZ?
Ist das ein Nachfolger von N, ja? Würden wir
so parametrisieren? Wir haben einen Startzustand, einen Zielzustand,
wo wir hinwollen, und rufen General Backtracking mal auf.
Erstes Argument ist der Startzustand. Der Test auf das Erzeugen
der Folgezustände
Wir übergeben einen Zustand und müssen die Liste der Folgezustände erstellen.
Na gut, da müssen wir einfach auf den augenblicklichen Zustand
eins addieren und eine Liste daraus machen.
Für den Test ist es zulässig. Da Fragen waren,
ist der Zustand kleiner als der Endverstand oder gleich?
Und ist es der Endzustand? Da müssen wir testen,
ist der Zustand gleich dem Ziel. Und sowas machen wir bei Parametern,
die Funktionen, höherer Ordnung natürlich inzwischen mit Currying.
Wir fragen also, Ab die Funktion, wo wir als
ein Argument schon fest den Zielzustand dran binden, mitkarieren.
Ob die sagt, ja, es ist der Zustand.
Und wenn wir das jetzt mal aufrufen, also Count,
von eins bis drei, kriegen wir zurück, als Zwischenergebnisse,
drei fehlen, wo ein Versuch schiff ging und eine vier,
ja, und Protokoll, schreien, drei, in drei, in Teilen.
Also das sind eingeschaltete Protokoll, wenn man diesen Kommentar dann
nicht ausklammert. So, jetzt machen wir mal dafür,
Etwas eine elegante Reform, die Parameter zu übergeben.
Ich habe im Wesentlichen da ja noch Lamdas übergeben. Aber bei so einfachen Abfragen,
wie ist es gleich oder so, da können wir auch versuchen,
die Parameter samt uns sonders mit Funktionen höherer Ordnung hinzukriegen.
Also stilistisch reiner würde dieser Aufruf so aussehen, Liste der Folgezustände.
Wird man kein Lamda nehmen, sondern einfach hinschreiben, die Funktionskompositionskomposition,
Wände Ad1 auf das Argument an und dann Hülles einen in eine Liste.
Und dafür nehmen wir unsere Funktionen höherer Ordnung, Compos.
Ist der Zustand zulässig. Da können wir auch einfach,
wenn wir sicher sind, dass wir immer mit einer kleineren Zahl beginnen,
in dem Fall als Argument übergeben, always two,
weil wir letztendlich das gar nicht brauchen,
wenn wir nur zulässige Zustände erzeugen,
dann brauchen wir nichts zu testen.
Und in dem Fall würde man eine solche Funktion eben parametrisieren
mit einer konstanten Funktion, always two.
Und ist der Zustand. Richtig,
wir könnten auch mit Curry sich hier um Zahlen handelt,
können wir es treffen,
dere Gleichheitsprädikat nehmen
Numerische Gleichheit und Curry Air oder Curry gleich N ist feiner,
den Zustand abfragen. In dem Fall ist es egal,
ob wir Curry oder Curry Air nehmen, diese Funktion,
ist in dem Fall ja kommutativ.
Und ich habe sie mit Absicht so hingeschrieben, um ihnen
noch einen Hinweis auf eine kleine stilistische Frage zu geben.
Also wenn es Funktionen in zwei Ausprägungen gibt, Curry und Curry A.
Und sie wählen die speziellere, wo es nicht nötig wäre,
verwirren sie sämtliche Leser. Das macht man eigentlich nicht.
Da fragt sich jeder, warum? Um Himmels Willen
hat sie hier jetzt Curry A genommen.
Jedenfalls sollten sie sich das fragen. Und also das tut
man nicht. Er steht hier als abschreckendes Beispiel
Vielleicht auch mit auf die Folie schreiben sollen, aber okay.
Also wir können mit diesem Rahmen,
die wir als Kontrollrahmen schreiben, in der Regel,
sämtliche Funktionen, die gebraucht werden durch Aufrufen unserer Funktionen,
höherer Ordnung, kurz und knapp und leserlich erzeugen.
Okay. Gut,
für unsere Achtdam würden wir diesen Rahmen jetzt so verwenden,
das sollte beim letzten Mal ja klar sein,
dass wir einen Zustand als Liste von Koordinaten haben darstellen.
Die Funktion Position ist safe,
das letzte Mal eingeführt haben,
die nehmen wir für den
Zulässigkeitstesten, weil wir keine Dame dahinstellen dürfen, wo sie bedroht wird.
Und das Brett ist gefüllt, wenn wir alle Reihen gefüllt haben.
Und alle Damen sicher sind. Und dafür würden wir also
einfach prüfen müssen, ob die Länge vom Zustand,
den wir haben, gleich der Größe des Brettes ist.
Und das würde dann mit dem allgemeinen Backtracking-Schemen mal so aussehen,
dass wir eine Funktion höherer Ordnung erzeugen,
Liste der nächsten Position,
irgendein Lamba über den Zustand
Eine Funktion, Position ist safe. Eine Funktion als Endtest,
alle Reihen gefüllt. Und das übergeben wir hier einfach.
List of Next Positions, but General Backtracking. Wir beginnen mit
dem leeren Brett. Diese fertigen Programme sind alle für sie
in diesem SC3-Modell. SC3-Bit-Modul, was sie für sie programmiert hat,
da können sie es dann auch mal ausprobieren.
Gut. Und für das nochmal zur Erinnerung,
also Repräsentation des Suchraums, als Menge von Zuständen, Ausgangszustand angeben,
die Generatorfunktion, Test auf Zulässigkeit und Test auf Erfolg.
Das finden wir jetzt mal auf gänzlich andere Programme ein.
Zum Beispiel hier auf das Problem der drei Missionare.
Nee, vier. Und vielleicht kriegen wir die auch mit Musik.
Ja, also dieses Beispiel sind gegeben. Ein kleines Problem,
dass ich mal eine Quizsendung gesehen habe, Missionare auf der Flucht,
ja, stellen sich folgende Situationen vor,
ein bisschen unrealistisch zugegeben, aber man kann gut knobeln.
Ich habe drei Tage drüber geknobelt, bis mir einfiel,
ach Mensch, du kannst doch Prolog und probiere es mal.
Und habe es als Beispiel programmiert. Also Situation ist
die folgende. Wir haben eine gemischte Altersgruppe von Missionaren,
also zwei eher junge und sportliche,
die schnell einen Stramm marschieren können und dann noch welche,
die eigentlich schon längst pensioniert sein sollten und mehr so am Stock durch die Gegend tumpeln,
sehr viel langsamer sind.
Und diese missionieren in einem Land, wo es
wilde Tiere gibt. Und diese sind bei Nacht unterwegs,
haben sich ein bisschen verschätzt in der Zeit
Und hinter ihnen hören sie die Löwen jaulen und so weiter.
Und sie wollen also schnell nach Hause.
Die einzige Abkürzung führt über eine baufällige Brücke.
Es ist Nacht, der Mond scheint nicht her.
Ihr habt extra so eine schmale Munze gemacht.
Man sieht also nichts im Düstern. Und diese Hängebrücke,
von der wissen sie aber eins, erstens,
die ist so instabil undär als zwei, dürfen nicht gleichzeitig drauf.
Zweitens hat sie viele, viele Löcher, wo man durchfallen kann.
Man braucht also eine Taschenlampe, um rüber zu gehen.
Und sie müssen ganz besonders tolles Taschenlampenmodell haben.
Die Batterie zeigt ihnen auf die Minute genau an,
wie viel Zeit noch da ist für diese Taschenlampe
So, also sie wissen jetzt,
unsere Taschenlampe brennt noch exakt 60 Minuten und immer nur zwei dürfen
zusammen auf die Brücke und hinter ihnen jollen die wilden Tiere.
Dumme Situation, sie sind zu viert. Was wir auch noch wissen,
ist von früheren Experimenten müssen sie genau wissen,
wie lange jeder von ihnen braucht, um über die Brücke zu kommen.
Die haben also in der,
der eine braucht für den Weg über die Brücke,
hey jetzt, mach doch mal weiter.
Der eine braucht für den Weg über die Brücke fünf Minuten,
der andere zehn,
der nächste 15 und der übernächste
So, also. Also fünf Minuten, zehn Minuten,
bei 20 und 25 Minuten. So, Taschenlampe brennt nur noch
eine Stunde. Und wie kommen die da jetzt drüber?
Den wollt ihr eigentlich noch hören, genau.
Ja, Mann. Quicktime streckt heute wieder. Ja,
eine Frage. Können sie es schaffen? Also für diesen
Weg über die Brücke? Die Idee ist ja, vielleicht,
dass man Wenn die ersten beiden darüber rennen und die Taschenlampe mithaben,
stehen die anderen da und sind verloren.
Das heißt, man muss damit die Kollegen eine Chance haben,
muss es immer eingeben mit der Taschenlampe zurückrennt und ihnen jetzt die Taschenlampe bringt.
Wäre die erste Idee, wir schicken mal zuerst die ersten beiden hier rüber. Und der,
der fünf Minuten braucht, das soll die 5-4 zeigen,
der schnappt sich dann die Taschenlampe rennt zurück, holt den nächsten ab,
kommt mit dem zurück, rennt zurück und so weiter.
Scheint irgendwie so mit der Schnellste zu sein.
Das probieren wir jetzt mal aus. Die Uhr tickt
60 Minuten
Tschüss. Ja, noch zehn Minuten haben wir.
Fünf Minuten. Ja, also das war nix,
ne? Uns fehlen glatt fünf Minuten,
wenn wir den schnellsten immer hin und her schicken.
Ja, wie kann es denn überhaupt gehen? Wie gesagt,
ich kam da nicht so recht drauf und habe dann
das Ganze im Prolog programmiert und im Wesentlichen das gemacht,
was wir uns jetzt zum Recket anschauen
Und das Ganze als Zustandsraum vorgestellt, bei jedem Schritt macht es
nur Sinn, dass zwei nach rechts gehen und einer zurückkommt.
So. Also eine Übergangsfunktion, wenn die Taschenlampe links ist,
dann werden die Folge, wird der Folgezustand sein,
dass zwei nach rechts gehen.
Ja. Wenn die Taschenlampe rechts ist,
dann muss der Folgezustand sein, dass nur einer zurückrennt.
Alles andere wird mir sicherlich bestimmt verschwenderisch sein.
Und der Zulässigkeitstest, die Funktion sollte einfach testen,
ob die Restzeit noch positiv ist.
Und wir sind fertig, wenn wir getestet haben,
keiner steht mehr links
Und wir wollen noch wissen, wie es geklappt hat.
Das machen wir das ganze Jahr. Also führen wir noch
einen weiteren Parameter, ein Protokoll für die Zahl der Zustände.
So, also mein Missionarsmodul hier. Parameterliste der Geschwindigkeiten,
mit denen unser Team marschieren kann. Und die Zeit,
die die Batterien noch brennt,
dann habe ich noch eine kleine Funktion geschrieben,
Pretty Pretty Print Protocol,
die uns einfach die Liste ausgibt,
wie jetzt
die Züge waren
Eine Funktion, die die Zustände konstruiert und zwar aus den
folgenden Angabenliste der Geschwindigkeiten. Wie viele stehen links? Ja
. Wie viele stehen rechts? Wo ist die Taschenlampe?
Da wird ihr Left oder Ride stehen und die Zeit,
die wir noch haben. Zu Anfang ist es Max Tay.
So erzeugen wir einen Zustand mit Mac, Stitness,
übergeben wir als ersten Zustand hier an, unser General Backtracking-Schema.
Dann übergeben wir eine Funktion,
die die Züge links nach rechts generiert und den Zulässigkeitstest,
den basteln wir einfach wieder aus unserem Curry
Mit der Größe Gleichfunktion null für die Restzeit, die wir noch haben.
Kommt aus unserem Zustand. Und der Test auf zulässig oft Erfolg unserer Suche,
der besteht darin, dass wir fragen,
ob die Gruppe der Missionare, die Links steht,
hier in unserer Datenstruktur, Missionary States,
ob die leer ist, ja?
Also wenn wir jetzt testen wollen,
ob das leer ist, machen wir eine Funktionskomposition aus der
Funktion null und Left Group den Akzessor für unseren Missionarszustand
Und ansonsten geben wir am Ende Truth zurück. Das ist also
unser General-Backtracking-Aufruf. Und dieses Erzeugen der Züge, das guckt einfach,
wo ist die Tasche und Lampe, ist die Taschenlampe.
Links, dann rufen wir einen Generator auf,
der alle möglichen Bewegungen von links nach rechts erzeugt.
Und im anderen Fall alle möglichen Bewegungen nach links für den
gegebenen Zustand, wo wir gerade sind.
Ja, und sage und schreibe, es gibt zwei Lösungen.
Und die haben wir
hier protokolliert
Hm. Also, was tatsächlich ein Schlüssel in den Ofen war,
ist die Idee, immer den schnellsten hin und her sprinten zu lassen.
Erst ist es unfair, der muss sich mehr anstrengen als alle anderen.
Und zweitens verschwendet man Zeit. Man verschwindet nämlich Zeit,
weil die, die 20 Minuten und 25 Minuten brauchen,
bei dieser Methode nicht gleichzeitig rüberlaufen.
Die laufen hintereinander rüber. Und wenn man sie hintereinander laufen lässt,
dann summiert sich das hier alles auf und wir haben die Zeit überschritten.
Aber wenn wir die beiden langsamsten für sich alleine sorgen lassen,
ja, also entweder der Fünfer oder der Zehner
springt zurück und bringt ihnen die Taschenlampe und dann marschieren
die beiden
zusammen rüber
Am anderen Ende steht schon einer von den beiden schneller und entweder Zehner oder Fünfer
und der bringt dann die Taschenlampe zurück und holt seinen Kumpel ab.
Also die Idee, Missionar 5 und Zehn marschieren nach rechts.
Zehn bleibt da, startbereit, fünf marschiert zurück,
schickt die beiden langsam, die ein bisschen trainieren müssten nach rechts.
So, gib die Taschenlampe. An den Zehner,
der läuft zurück und dann laufen Dieb, holt der seinen Fünf-Minuten-Kumpel ab,
die brauchen zusammen nur zehn Minuten und sie haben es geschafft.
Und das ähnliche Spiel, die zweite Lösung,
der würde zuerst der Zehner zurücklaufen, im Wesentlichen dasselbe,
aber die brauchen auf diese Weise genau 60 Minuten.
Also das hat das Backtracking gefunden
Ja, also nach dem Schema kann man wirklich alles Mögliche lösen im Skript,
habe ich eine ganze Menge Beispiele,
was man damit so machen kann,
Lösungen fürs Vier-Farben-Problem suchen im Einzelfall und so weiter.
Wirkt aus dem Labyrinth oder Züge und Kultkopf,
das ist eine ganze Menge von diesen Beispielen auch programmiert.
Ich möchte jetzt für das Systematische probieren,
einfach noch eine andere Methode ansprechen,
weil in vielen Fällen geht das Probieren am einfachsten,
indem man sich vorstellt,
ich habe eine Parallelarchitektur und probiere sämtliche Lösungszweige gleichzeitig
Nebenläufig aus. Und dafür haben wir in Recket auch eine wunderschöne, wunderschönen Operator.
Den Amp-Apparator, engelhafter Operator. Und mit dem können wir
tatsächlich so programmieren und beim Entwurf denken, als würde alles nebenläufig ausgeführt.
Solange unser Rechner keine Nebenläufigkeit unterstützt, wird es trotzdem sequenziell gemacht werden.
Aber die Programme werden viel, viel einfacher.
Und das schauen wir uns jetzt mal an zwei Beispielen an,
wie das gehen könnte. Von McCarsy eingeführt, John McCarsy,
das war ja auch der Urvater von Liz,
der zuerst den Lamdakalkalkül in eine Programmiersprache gewandelt hat.
Und der hat für die Nebenläufigkeit diesen Apparator eingeführt,
der war dann die ganze Zeit in Vergessenheit geraten,
aber mit Skim wurde er wiederentdeckt und er ist auch in Zelos drin,
in dem Objektteil für irgendwie das Arbeitspferd,
der funktionalen Programmierung in der Lizwelt kommen listet.
Und wenn wir ihn benutzen wollen, müssen wir eine der weiteren Sprachen,
die in Recket sind, verwenden. Also bitte,
wenn Sie es ausprobieren wollen, Dann heißt es,
für die Versuche nicht langen Recket, sondern sie müssten,
die Sprache ist Windeln nehmen, nämlich die,
die schwindelhaft unser Recket in Kommendes verwandelt.
Okay, also was macht der Amp-Apparator? Wir schreiben einfach
ins Programmklammer auf M. Es ist ein Special-Form-Operator, Operator.
Die kriegt eine Liste von Argumenten und wählt zufällig eins der Argumente aus.
Oh gut, und das würden wir in eine Variable binden. Wenn wir später,
wenn wir sagen, ich möchte weitere Lösungen haben,
dann kann der ganze Programmcode-Blog, in dem wir zurzeit sind,
wieder ausgeführt werden, mit einer der anderen Bindungen für M, ja.
Wenn wir M einfach ohne Argumente aufruften,
dann heißt das Fehl und wir haben keine Lösung.
Und jedes Fehl führt dazu, dass alle vorherigen Amps sich verschwören.
Und eins von denen probiert, eine andere Lösung zu wählen.
Eine andere Alternative. Und auf diese Weise können wir systematisch probieren,
indem wir gar nicht selbst programmieren, in welcher Reihenfolge probiert wird,
sondern einfach sagen, hier sind alle meine Möglichkeiten.
Mit Cassi hat es Engelilic Operator genannt, weil er wirklich,
es ist ein Traum. Es garantiert,
dass wenn viele Möglichkeiten da sind und eine Lösung existiert,
dass der sie auch findet.
Also er wird so lange probieren, wenn die Lösung existiert,
bis man bei dieser Menge der endlichen Lösung tatsächlich auf die Lösung stößt.
Wenn er keine Lösung existiert, dann kriegen wir irgendwann
einen Fehlfluss Fehlermeldung und all den unangenehmen Konsequenzen.
Wie funktioniert es? Also erstmal im simpelsten Fall,
indem sie überhaupt noch nicht sehen, was es soll,
aber damit können sie es testen
Also, wenn wir das Ganze in der Sprache Rackett machen,
dann müssen wir es Windel wählen. Wenn wir es in
der Sprache swindeln machen, können wir uns ja sparen.
Aber in Rackett würden wir hier reinschreiben, Require,
Swindel, extra, da steckt der Amp-Apparater drin.
Und wir sagen hier jetzt im Interprit, der, hallo?
Ich möchte als Ergebnis irgendeine der Zahlen von 1 bis 4 haben.
Ja, und empfet zufällig einen auswählen und wir kriegen eins.
Und jetzt zu sagen, ach Mensch, eins gibt es nicht was Besseres.
Wir rufen Amp auf mit Klammer zu und das heißt,
Bitte sehr, suchen an einer neuen Lösung.
Es wird zurückgehen zu Amp-Aufrufen, die noch Alternativen hatten.
Und jetzt kriegen wir die zwei. Und das Spielchen können wir
so lange treiben, wie noch irgendwo in einem Amp-Ausdruck,
Ergebnisse sind. Und wir werden immer neue Ergebnisse kriegen.
Das muss das Ergebnis dieser Acke auf der Folie sein.
Hat sich das Ganze schön aufgehackt?
Na gut. Machen wir es nochmal. Ja,
also nach jedem Fehl wird eine neue Alternative gewählt,
Kontext neu ausgewertet
Und das macht vor allem dann Sinn,
wenn wir die Ergebnisse unserer Auswertung an Variablen binden.
Und diese Folie zeigt ihnen hoffentlich auch,
dass eine wichtige Eigenschaft beim Programmieren mit M verletzt ist,
die wir im Funktionalen Programmierstil brauchen.
Ich wollte das gerade sagen, wenn wir eine dick, ne?
Frage, ist das ein hochgradig Zustandsorientiert? Ja. Ja,
jetzt wissen muss, was man es vorher sozusagen schon mal hatte,
auch bei den späteren Mbox 500 Jahre künftig gegeben, die Liste der Zahlen.
Genau, also was wir hier sehen, ist,
dass wir mit dem Programmieren Nebenläufigkeit praktisch nicht umhin können.
Tatsächlich verklausuliert, verkappt eine Zustandsorientiertheit zu haben.
Wenn ich mir diesen Berechnungsfahrt hier anschaue,
ich habe eine Variable eingeführt und habe gesagt, na bitte,
ich möchte, dass meine Variable A irgendeinen dieser Werte hat.
Und ich mache jetzt einen Fehl. Dann kann nicht
alles, was vorher war, nochmal neu berechnen.
Und zwar seit dem Amp, das geändert wurde,
bis zu meinem Aufruf hierhin,
wo dasselbe durchgerechnet wird mit einer neuen Bindung von
Ja, wenn ich jetzt mich nach diesem Felien-Aha-Abfrage,
habe ich mit einmal die zweite Variante.
Nochmal, jetzt habe ich hier die dritte. Wir können trotzdem
ziemlich stilrein funktional programmieren. Wenn wir nicht auf Seiteneffekte vertrauen,
sondern all diese Bindungen immer in einem lokalen Bindungskontext machen,
der verworfen wird.
Also sowas würde man nur in einem Lett tun und nie mit globalen Variablen.
Und dann würden eben die lokalen Umgebungen, die eingeführt werden,
durch einen Lettblock der Amp enthält,
die würden verworfen
Und trotzdem bleibt das Programm im Wesentlichen funktional. So,
wie können wir jetzt damit systematisch programmieren, um kombinatorische Probleme zu lösen?
Typischerweise verwendet man das Amp in Kombination mit Special Forms,
die prüfen, ob bestimmte Bedingungen erfüllt sind.
Und das ist Amp Assert. Also hier habe ich gesagt,
welche Werte für A ich mir vorstellen könnte. Und jetzt sage ich,
aber Racket, bitte überprüfe für mich, ich möchte sicher sein,
dass ich nur einen Wert für A bekomme,
der größer als vier ist
Und dazu sage ich dann Amp, es hört und gebe eine Bedingung ein.
Und wenn ich das mache, dann habe ich mit einmal
Werte für A, die diese Bedingung tatsächlich erführteln.
Nämlich, Moment, die haben wir noch nicht, ne?
Er nimmt erstmal den nächsten Wert und beim Test,
der dann passiert, werden wir tatsächlich dann einen Wert von fünf bekommen.
Gut. Wir gucken das jetzt mal in einem etwas sinnvolleren Programmstück,
zum Beispiel,
wir wollen Alle Zahlenpaare haben aus zwei Zahlen A und B und A
und B sollen aus der Menge der natürlichen Zahlen kommen mit kleinen Einschränkungen.
Und wir wollen nur die haben, für die die Bedingung
erfüllt ist, dass die Summe dieser Zahlen sieben ist.
Kann man ja vielleicht irgendwann mal brauchen.
Und dieses Probieren könnten wir so machen, dass wir,
dass die Special Form Amp Collect nimmt.
M macht folgendes, es macht einen Es wertet alle Amp-Ausdrücke auf,
die danach kommend eingeführt werden. Und sammelt die Ergebnisse in
einer Liste für Werte, Zustandsbelegungen, für die diese Bedingung erfüllt war.
Also hier sagen wir mal, unsere Zahl A,
die sollte aus der Liste all dieser Zahlen kommen,
1, 2, 3, 4, 5, 6,
7. Und B sollte nur aus der Liste der Zahlen 2,
4, 6, 8 kommen.
Und wir haben jetzt unsere Einschränkung, wir wollen das A
plus B gleich 7 ist.
Also schreiben wir hier noch unser Amp Acertain als Test ab
plus B
Wenn das erfüllt ist, hier, dann sammeln wir die. Amp-Ergebnisse,
indem wir einfach einen Cons machen aus A und B.
Amp Collect sammelt jetzt eine Liste von allen Paaren A und B,
wo A aus dieser Liste kommt,
B aus dieser und die Bedingung auch erfüllt ist.
Und wir sehen hier das Ergebnis fürs Paar 1,6. Es ist erfüllt,
für 3,4 ist es erfüllt, für 5,2 ist es erfüllt.
Also hiermit können wir Viele Variablen einführen und dann nach allen Konstellationen suchen,
wo Bedingungen an all die Variable gemeinsam erfüllt sind und
Amp-Collect sammelt uns alle Lösungen in einer Lösung.
Das ist wirklich eine super einfache Art um Listen von Lösungen mit etwas komplizierteren Suchen zu schreiben.
Und das können wir jetzt mal ausprobieren am Beispiel Landkarte zu färben.
Sie kennen ja sicherlich Das Problem, was den Mathematiker lange,
lange Zeit aufgeregt hat, weil sie nicht beweisen könnten,
ob es erfüllt werden kann oder nicht, gegeben eine Landkarte,
ist es möglich, mit nur vier Farben,
die immer so einzufärben,
das benachbarte Länder nicht dieselbe Farbe haben.
Und man fand ziemlich schnell Lösungen für spezielle Flächen.
Zum Beispiel wusste man schon, als ich Studentin war,
dass es immer geht mit fünf Farben,
wenn dir Landkarte auf ein Tores gemalt wird.
Nur auf ein Touris war irgendwie nicht
der praktische Anwendungsfall,
der einen vorgeschwebt hat
Es ist dann tatsächlich mit Hilfe eines systematischen Probierprogramms gelungen zu beweisen,
dass es immer lösbar ist, nur hat es die Mathematiker nicht erfreut,
weil dieser Computerausdruck war so umständlich zu lesen,
dass man nicht dahinter kam,
was die zündende Idee ist, was heißen soll,
verstanden hat man das Problem immer noch nicht,
aber wenn man in seinem Computer glaubt, dann weiß man,
es ist lösbar allgemein.
Gut, wir suchen, wir wollen das jetzt nicht,
das Problem allgemein lösen,
sondern schlichtweg für eine konkrete Landkarte versuchen, sie einzufärben.
Und zwar nicht deterministisch, indem wir es mit M machen
Und ich mache es mal in einer vereinfachten Form. Wir beschränken uns,
damit das alles noch auf eine Folie passt, auf das Problem.
Lösungen mit drei Farben, eine Karte einzufärben und diese Karte sei diese.
Und was müssen wir probieren? Wir haben,
wenn wir das auf den Zustandsraum abbilden wollen,
haben wir zunächst mal einen Ausgangsknoten und als ersten Probierschritt die Möglichkeiten,
unser Land einziehe, einzufärben mit blau, mit grün,
mit rot oder pink eher.
Dann haben wir als Schritt zwei die Möglichkeit,
das Land 2 einzufärben, aber blau geht nicht,
deshalb ist es hier durchgestrichen, weil blau hat schon Land 1,
aber wir könnten hier noch grün und rot nehmen und als drittes
eben das Land 3 so einzufärben und so weiter und so weiter.
Wir sind schon, wir haben hier tatsächlich wieder den schönen Fall eines Back-Tracking-Problems, alles,
einen Baum von Möglichkeiten in jedem Schritt, eine endliche Auswahl.
Und jetzt machen wir mal die Variante, dass wir in jedem Schritt,
wo der Baum sich hier verzweigt, einen Amp machen.
Um fürs nächste Land die Farbe zu wählen.
Dazu als Hilfsfunktion Eine Funktion, die hier aus vier Farben
etwas auswählt. Und zwar mit M. Das heißt,
jeder Aufruf von Juice Color würde uns irgendeine Farbe liefern.
Und um dir Länder mit ihren Farben zu repräsentieren, führen wir anstruct ein.
Für die Länder Country, Name des Landes, die Farbe.
Und um jetzt die Karte zu repräsentieren, die direkten Nachbarn
des Landes. Also bei fünf wäre diese Liste 4,
2,
3 und
Okay, das steht in diesem Stract drin. Und jetzt
färben wir mal mit Amp einfach eine Karte von Europa ein.
Das Beispiel habe ich hier übrigens aus dem ebelsten Zasman abgeschrieben,
Structured Interpretation of Computer Programs,
der hat es in der 1985er-Ausgabe des Buches mal programmiert gehabt.
Also, wir wollen jetzt per Amp jedem Land eine Farbe geben.
Und dazu führen wir Bindungen an lokale Variable ein
Peevey Portugal, tschüss Kalle, evi espendia, tschüss Kalle und so weiter.
Und da kriegen wir dann für jedes dieser Länder eine Farbe.
Gut. Dann führen wir hier die Länder selbst ein.
Also hier werden sie erzeugt, Portugal,
also ein Struct, Country mit dem Namen Portugal,
der Farbe P. und die Nachbarländer in dem Fall nur Spanien.
Das ist Banya, Spanien hat als einzige Nachbarländer Frankreich und
Portugal und so weiter
Viel Fleiß arbeitest zu schreiben. Und dann können wir die Liste aller Länder aufstellen,
Countrys, List, Port Your Girls, Bane, Friends und so weiter. So,
wie Benedikt schon richtig bemerkt hatte, in dem Moment,
wo wir bei Amp angekommen sind,
wir kommen in einen Touch, zustandsorientiert hätten,
da sieht man auch, das sind in diesem Fall,
greifen wir zu Sprachelementen der funktionalen Programmierung,
die zwar immer noch funktional sind,
aber genommen werden,
wenn man imperative Sprachelemente hat
Wir machen jetzt einfach eine Schleife,
indem wir über die Liste aller Länder gehen und sagen,
für jedes Land, ja, Countries.
Führe diesen Ausdruck aus. Hier steht kein Map,
damit man nicht eine neue Liste der Länder abbildet.
Das for each, arbeitet jetzt echt nur mit dem Seiteneffekt,
dass das Amp ausgeführt wird und fertig. So,
und dann sagen wir, es muss ein Amp-Sert sein,
das sicherstellt, dass die Farbe des Landes nicht ein Element der Farbe der Nachbarländer ist,
der Liste der Farbe der Nachbarländers ist.
Und wenn wir das haben, dann sind wir fertig.
Dann haben wir nämlich so oft durch die vielen versteckten Amps die Farbe der Länder geändert,
wenn wir hier angekommen sind und alle Amp-Asserts hier gut gegangen sind,
dann haben wir eine gültige Färbung.
Also wir selbst haben hier nirgendwo probiert.
Wir haben überall einfach nur gesagt, hier sind die Möglichkeiten
, wähle eine davon
Und weil das alles mit Amp gewählt wird,
wird dieses Amp-Sert hier dafür sorgen, dass wir zurückgehend zu anderen Möglichkeiten von Amps.
Wenn wir feststellen, dass für irgendeine zwei Länder hier ein Konflikt besteht,
dann wird eins der bisherigen Möglichen geändert. Und das heißt,
wenn wir hier am Ende sind und mit Amp-Sert gesagt haben,
was sicher sein soll, Angelique Operator,
wir können darauf vertrauen, entweder haben wir gar keine Lösung,
aber wenn uns eine geboten wird, ist sie es,
die ist richtig.
Und deshalb brauchen wir jetzt einfach nur noch ein Display
zu machen
For it. Für jedes unserer Länder in der Liste Countrys
zeige an, nahmen wir des Landes und die Farbe.
Und ein Newline, damit das nicht alles Ländern da wegsteht.
Und jetzt haben wir unseren Europa angefärbt und kriegen dann hier
unsere schöne Liste Portugal, Rot, Spanien, Gelb,
Frankreich wieder rot und so weiter und nichts nirgendwo ein Konflikt.
Und wenn es weitere Lösungen gibt oder wir wissen wollen,
ob es weitere gibt, sagen wir einfach nochmal M,
dann beginnt das Spielchen von neun,
es wird nach weiteren Folgelösungen gesucht
Okay. Und einfach das Zurückgehen und die vorherigen Ems zu fragen,
dass nach Möglichkeiten kann man natürlich wunderbar nehmen,
um damit das allgemeine Backtracking-Schema auszudrücken. Das ist das,
was wir uns bei der Gelegenheit auch nochmal anschauen können.
Ja, gehen wir nochmal zu unserem Schema jetzt zurück,
was jetzt eigentlich verstanden sein sollte.
Wie probiere ich systematisch in so einem Suchraum von Möglichkeiten? Ja,
wir übergeben wieder den Ausgangszustand, Position, Generate States,
vertestet, ob es legal ist und ein Test, ob es die Endlösung ist.
Und dann Fragen war, zuerst mal, ob unser Ausgangszustand legal ist,
indem wir ein Amp Assert machen, ist Legal State.
Wenn das nicht ist, geben wir schon mal gleich auf.
In allen anderen Fällen, fragen wir,
es ist der Endzustand und dann geben wir die Lösung aus
und in allen anderen Fällen wieder mit Jens stets Folgezustände erzeugen und Um jetzt mit End zu testen,
ob wir eine Lösung gefunden haben, machen werden,
ein Amp assert, ob dieser Zustand eine Lösung ist.
Und dann sind wir fertig. Okay. Und mit dem Fall haben wir jetzt auch eine Möglichkeit,
eine ganz elegante Möglichkeit so zu programmieren, als wollten wir nur eine Lösung haben,
das Schöne bei diesen Endlösungen ist, die sind so programmiert,
dass sie potenziell alle Lösungen zeigen können,
man muss die anderen Lösungen bestellen und immer,
es fehlt erzwingen, dann kriegt man die Folgelösung.
Und das genau da gemacht worden, wenn wir,
wir haben den Rahmen so geschrieben, alle Möglichkeiten werden erzeugt,
potenziell, indem alle Folgezustände expandiert werden in einem großen Amp,
aber wir würden, wenn wir damit arbeiten,
dafür sorgen,
dass wir immer nur eine Lösung anschauen und wenn wir eine Folgelösung haben wollen,
einfach nochmal Amp in Klammern sagen und dann wird die nächste angezeigt.
So, wir haben jetzt noch ein bisschen Zeit und
ich kann jetzt den nächsten Lock der Vorlesung reingehen,
so nachdem wir so die Grundtechniken kennen.
Wie mache ich systematisches Programmieren im Funktionalen Programmierstil?
Wie verwende ich Funktionen höherer Ordnung? Jetzt schauen wir uns mal
ein paar etwas größere Pakete an. Und eines der Klassiker,
der gerade dazu einlädt, dass man es mal anders,
als es Josef Weizenbaum mit seinem Assembler-Programm gemacht hat,
mal funktional zu programmieren, das ist das,
weil der Klassiker Eliza,
weiß nicht,
hat einer von ihnen mal mit dem E-Max in
der Unix gearbeitet
Ey, wunderbar, ja. Dann können Sie sicherlich bestätigen,
der E-Mail kann unglaublich viel, aber er hat ziemlich,
ziemlich viele Möglichkeiten und Keyboard-Shot-Cuts, die man sich merken muss.
Und manchmal fängt man an, zu verzweifeln. Und für diese Fälle
, seit Anfang an der E-Mails gleich psychologische Betreuung eingebaut.
Eines der Meta-Kommandos, die man aufrufen muss, ist,
auf dem Ofen kann es das Programm Doktor.
Was eine Gesprächstherapie-Sitzung startet und was da gestartet wird,
ist das Programm Eliza. In der Ursprungsform abgeleitet von dem,
wie Weizenbaum das gemacht hat
Das Programm möchte ich mir einmal mit Ihnen näher anschauen,
weil da kann man eine ganze Menge netter Zutaten finden,
die eigentlich alle gebraucht werden,
wenn man sein Pro-Log selbst schreiben will.
Das wollen wir am Ende des Semesters ja machen.
Also wir haben zum einen einen regelbasierten Übersetzer,
wir machen die mal unsere erste Übung darin,
ein Programm mit Hilfe einer Regel, Datenbasis deklarativ zu schreiben.
Und wir können uns anschauen, wie wir mit Funktionen höherer Ordnung
weitere Werkzeuge bauen. Und dann lernen wir auch daran,
das Pattern-Matching, das ist eine einfache Form der Unifikation,
wie sie im Pro-Log verwendet wird.
Sehen,
wie weit wir kommen
Das Programm von Weizenbaum hat ja echt Furore gemacht.
Das war in den 70er-Jahren neu. Also was kann die
Leiser überhaupt? Eliza ist ein Programm, das vorgibt,
mit einem Menschen einen Dialog führen zu können.
Und man setzte sich also an seinen Rechner, sagt einen guten Tag,
geh leiser und das fragt mich nice zurück.
Und im Endeffekt war es so etwas wie der Versuch des Modells einer Gesprächstherapie.
Du warst halt Weizenbaum selbst dazu gesagt. It's said that
tricks plain is tricks plain away, this maxime is nowhere
so werelful filt as in the area of computer programming.
Especially in what's called juristic programming and artificial intelligence
Von Those Realms Machines are made to behave and wandres ways offensifician
to design to even the most experienced of server. Er sagte,
dass in seinem Buch die Macht der Computer und die Ohren macht der Vernunft,
weil er beobachtet hatte, dass tatsächlich Menschen,
die sich hingesetzt hatten, mit Eliza gesprochen hatten,
im ersten Moment geglaubt hätten, sie sprechen mit einem echten Menschen.
Ich kann es kaum glauben, weil die Beispiele,
die wir uns jetzt anschauen werden, die sind eher,
naja, aber trotzdem, wenn man verstanden hat,
wie das Programm funktioniert, ist es im Wesentlichen was Simples ist,
was jeder nach Semester programmieren, lernen,
auch hätte hinhacken können, ja.
Dann erlischt das Wunder. Mit wann supporticular programme ist anmaßt?
Wann sitzt in a working sikesplained, in a language sufficiently
plained to end use understanding, it's magic crumbles away.
It's stands revealed at a mear collection of seeds.
It's quite comprehensible. The open server assists jumpselves,
I could tave a ritten that.
This that's what he moves the program and question from the
shelf-market intelligent to digital revert software curios.
Fit to be discussed only
vis people less in lightened
The Object of this paper is to cause just such a
re-evaluation of the program about to be explained.
Few programs ever a needed it more. Ich habe
dieses Zitat aus dem Buch von Peter Norweg abgeschrieben,
also nicht aus dem Originaltext von Weizenworn, aber egal.
Ich hoffe, Norweg hat es richtig gemacht. Also,
Gesprächstherapie, erfolgende Idee, wir haben in der Gesprächstherapie ja den Ansatz,
dass man einfach Patienten dazu bringen will, zu erzählen,
zu erzählen und dabei unbeabsichtigt Dinge preiszugeben,
die sie sonst immer verborgen halten
Also einfach, indem man ihnen zuhört, sie ermuntern,
was zu erzählen, dass da irgendwann mal was kommt,
wo man anfangen kann zu bohren und nachzufragen.
Und ich meine, Personen mit ihren Problemen zu konfrontieren.
Also nicht wirklich sagen, sondern nur zum Sprechen zu ermuntern.
Und dabei aber verständnisvoll zuhören, dass man merkt,
wenn etwas Interessantes gesagt wird. Und das ist genau das,
was Eliza tut, in leiser, versucht,
die Personen vorm Tormündel dazu zu bringen, zu reden,
zu reden, zu reden.
Und wenn aus Versehen etwas gesagt wird,
wo man meint, da lohnt es sich,
da könnten Probleme sein,
da fragen wir mal nach
Und ein solches Programm zu schreiben, wie leiser es war,
da lernen wir also erstens Pattern-Matching.
Also wie wir in einer Antwort nach Mustern gucken,
die auch Probleme hindeuten, wo man nachfragen möchte.
Außerdem schauen wir uns einen modellanen Entwurf mit Funktionen höherer Ordnung
nochmal an und bauen uns selbst eigene weitere Werkzeuge,
um Rackett ein bisschen mächtiger zu machen.
Einen Originaldialog, wie ElisaIn geführt hat,
so wie Weizenbombe es in seinem Buch beschrieben hat
Männer all a like. Das also jetzt, die Patientin
gespricht. Ilaza fragt nach, in Bhat Way,
der All ways bugging as about something or another.
So, da war noch nichts bei,
also müssen wir Patientin dazu bringen, erzähle mehr.
Can you be more is specific? War my boyfriend made
me come here. Your boyfriend made you come here.
You says, I'm depressed much of the time.
I'm sorry to hear you are don't be pressed.
It's true, I'm unhappy. Do you think coming here
, will help you not to be unhappy.
Also was wir hier jetzt sehen können,
ist, dass das Eliza-Programm tut,
als hätte es die Aussage verstanden und tatsächlich Bezug nimmt auf das,
was vorher gesagt worden ist, ja.
Und genau da kommt das Pattern-Matching ins Spiel,
also das Modul Pattern-Matching, was wir jetzt gleich programmieren werden.
Das macht genau das. Aus dem vorherigen Sätzen etwas herauszunehmen,
um die nächste Frage zu generieren.
Ein nits am heart that match a certain.
What would it meant to you if you got some help?
Ja, selbe Spielchen. Man geht auf das bisher Gesagte ein.
Dann hört es, I could learn to get a long this my mother.
Und da, der Doktor in Eliza, Familie wird erwähnt.
Tal, me more about your family. Ja, kommt,
wird dann als Frage generiert. So. Okay, jetzt,
wir könnten zum Computer vorlesen lassen, aber das lassen wir mal.
So, der Dialog, der ist jetzt wirklich so,
dass er anscheinend erweckt, als ob Billizer am Patienten verstünde, ne?
I'm sorry, do you are depressed. Tonyou more about
your family. Aber wir haben in die Leise reingeschaut,
und stellt man fest, dass es wirklich reinschematisch,
bestimmte Muster in der Eingabe werden erkannt.
Und das wird die Rückfrage generiert, ja?
Wenn in der Eingabe zum Beispiel über Ähnlichkeit gesprochen wird,
like same, dann kommt in meisten Fällen eine Rückfrage
mit in what way
Und wenn da etwas steht, wie ein Lied,
irgendwas, what would it mean to you if you got?
Sex, ja. Und Leiser bringt nur Spaß,
wenn man selbst kooperativ ist und ordentlich Stoff liefert.
Weil die Regeln setzt, die generieren nur die Phrasen und Hüllen drumherum.
Also solange ein Patient mauerte Therapie resistent ist und nichts von sich gibt,
kommt immer nur go on, please continue very interesting.
Und die Semantik wird auch nur ziemlich spärlich erfasst
Also wenn wir sagen würden,
I need this like a hole and in the head,
dann könnt ihr die Rückfrage kommen,
what would it mean to you have you got it like
a hole and the head, ja?
Oder I want to what the what the way. Support,
you got to do to do. Okay. Ja. Kurze Zeit,
nachdem die Leiser veröffentlicht war, kam man auf die Idee,
jetzt mit einem anderen berühmten Programm Perry zu verbinden.
Perry, es ist ein Dialogsystem, was paranoides Verhalten simulieren soll.
Und die beiden passten echt gut zueinander. Ja,
und das ist jetzt aus dem ersten veröffentlichten Dialog von Eliza im Gespräch mit Perry.
Ich glaube, ich habe das Auch von Eliza sprechen lassen.
Heute, und verdienst der Ernsthaft. Leider liegen auch nichts,
der ein Mama lässt. Schönes Reifen lief. Nein,
ich bin just saying, that just not.
Das ist just made. Das ist just made.
Ich bin just saying, that just saying,
that saying, that saying, that saying.
Ich bin just saying. Ich bin just saying. Also
hier ist, was sie meinte, mit dem Schema.
Hier wird was von Zähmen gesagt. Zeiger geht an,
wir fragen mal nach Ähnlichkeit. Boah, das ist Systema
lernity suggest to Julia.
Jetzt gucken wir uns mal an, wie wir das programmieren können.
Ich war ja in Versuchung, das als nächste Übungsaufgabe zu stellen,
aber vielleicht gucken wir es uns hier mal fertig an.
Also, wir müssen Folgendes lösen.
Lese die Eingabe. Dann suchen wir nach passenden Mustern,
wie eben Same und so weiter, Family.
Dann müssen wir anhand dieses Musters, das,
was wir erkannt haben, in syntaktischen Bausteinen zusammenbauen zu einer Rückfrage.
Eben Eingabe zur Ausgabe transformieren, Oscar beschreiben und dann wieder
auf die Antwort warten. Okay, lesen und schreiben,
das macht Drecket für uns,
da haben wir Ritt und Reit.
Das sind einfache Sachen, voreingegeben
Für Sachen, der Postmuster, werden wir jetzt,
passende Muster, da suchen wir uns jetzt einen kleinen Algorithmus,
mit dem wir Pattern-Matching machen können.
Das ist nicht ganz trivial. Und dann schreiben wir eben
die Ausgabe. Okay, also wie kriegen wir Pattern-Matching hin?
Sei das Muster ein Need-Ex, ja? Dann wollen wir,
dass vielleicht sowas zurückkommt wie What Would It Mean to You,
if you got X, yeah.
Oh, fehlt eine falsche Farbe. I need a vacation,
what would, wenn das jetzt tatsächlich die Eingabe ist,
sollte rauskommen, what would it mean to you have you
got a vacation,
So, und dazu müssen wir eben Dinge wie,
I need a Vacation abgleichen mit Einite X und dabei auch feststellen,
dass das am besten passt,
wenn wir Cash und einen X gebunden wird, diejenigen,
die von ihnen im Moment relationales Programmieren hören werden,
das genau erkennen als das,
was Prolog für uns kostenlos macht mit der Unifikation.
Diese Bindung musste abgleichen und dies hier machen. Ja,
wir sind auf dem ersten Schritt dahin,
so etwas in Racket neu auch zu machen.
Also wir müssen es hier leider zum Fuß machen, Pech gehabt. Okay,
also Wir müssen also feststellen,
passt so ein Muster zu einer Eingabe und da,
wo wir Variablen haben, Variablen als solche erkennen,
kenntlich machen und sie dann binden an die Symbole und die Variablenbindung als Lösung zurückgeben.
Und natürlich ist Pattern-Matching etwas, was man sehr gut rekursiv machen kann.
Und zwar haben wir immer ein richtig schönes Beispiel für Baumrekursion.
Wenn sie sich gewundert haben, wo wir die je
brauchen werden, hier brauchen wir sie.
Wir haben als Eingabe das Muster, ein Nieter-Tex und die
Eingabe,
ein Nieter-Pacation
Dann fragen wir erst mal, ist das Pattern, ist das,
was wir als Muster übergeben haben, vielleicht schon eine Variable?
Merken wir uns einen Variablentest, müssen wir noch programmieren?
Wir müssen entscheiden können, ist es das X oder irgendetwas Richtiges?
Wenn es eine Variable ist,
dann geben wir einfach Tod zurück und sagen, ja,
Variable passt ja auf jede Eingabe, das passt.
Okay, da müssen wir später auch noch was tun.
Das Tool selbst ist nicht sehr hilfreich,
aber erst mal festhalten mit so Variable ist, passt es.
Aber wenn es kein Paar ist, also Liste oder ähnliches, ja?
Die Eingabe und der Input, sondern beides sind atomare Ausdrücke,
dann fragen wir einfach, sind sie gleich.
Wenn sie nicht gleich sind, passt es nicht, ja?
Aber wenn das jetzt Paare sind, die wir übergeben bekommen haben,
listen, dann machen wir ein Pattern-Matching für die ersten Elemente,
Carl Pettern nun Car Input, rekursiv,
und nun Pettern-Matching für den Rest.
Ja, und hier kommt die Baumredukussion ins Spiel,
sowohl die ersten Elemente müssen passen,
als auch der Rest muss passen.
Und deshalb das Ganze mit End verbunden.
Also simple Form des Pattern-Matching
So, aber wie wollen wir jetzt Variable kenntlich machen?
Pro Log machen wir das einfach, indem wir die Dinger groß schreiben.
Wir machen es hier, indem wir spezielle Symbolnamen einführen.
Wir sagen einfach, wenn es eine Variable ist,
lassen wir den Namen des Symbols mit einem Fragezeichen beginnen.
Und wie testen wir, ob der Name eines Symbols
mit Fragezeichen beginnt? Erstens sind wir fragen,
ob es
ein Symbol ist
Und dann machen wir Symbol Distring. Einfach das Symbol als
Zeichenkette expandieren und dann gucken wir uns das erste Zeichen,
eine Zeichenkette an. Stringraph an der Position Null. Und
dann können wir eben feststellen, ist das ein Fragezeichen?
Und dann sind wir fertig. Okay, also was passiert,
wenn wir hier unseren Pattern-Matcher aufrufen für ein Lied X und I Lied Money,
ist vielleicht vor Weihnachten irgendwie aktueller als Fication, dann,
ja, der erste Aufruf,
Pat Match würde hier die ersten Elemente vergleichen.
Pat Match II kommt tot zurück
Need X, mit Need Money, Need Need Tu passt.
Pat Match X mit Money. Hier sagt der Variablentest,
ja, es ist eine Variable, also passt es auch.
Und dann am Ende noch ein Pat Match,
Lehrerliste zur Lehrerliste, passt auch und wir kriegen Tools zurück.
Was noch fehlt, ist, wir wissen jetzt nicht die Variablenbindung für X.
Und das müssen wir es noch erweitern. Wenn wir dagegen
ein INID X mit I Real Me Need Money abgleichen,
dann geht es schief, weil hier die Stelligkeit nicht stimmt.
Also Pat dann Matching funktioniert nur,
wenn die Stelligkeit gleich ist
So, jetzt müssen wir das Pat Match so erweitern,
dass wir noch eine Liste der Variablenbindung zurückkriegen.
Und wenn wir die haben, nehmen wir die gebundenen Variablen,
um dann Antworten zu generieren mit Zepless. Ja? Wie sollten... Ja,
also wenn wir jetzt eine aus der Liste der möglichen Antworten,
die wir geben können, auch eine Schablone haben.
Müssen wir in dieser Schablone die Worte, die wir in Variablen gebunden haben,
in der Eingabe, einsetzen und dann so zurückgeben.
Also wenn die mögliche Antwort wäre auf ein Ei need,
what would it mean to you, if you got?
Und hier ist jetzt ein Ex-Trend. Dann müssen wir eben
von der Liste, die wir eben zurückgekriegt haben,
ein Pattern-Madding, wo steht X is Money oder Vacation,
dann dies ersetzen durch diese Bindung.
Und Subless ist die Funktion,
die nimmt eine Liste von Variablen Wertsparen, so eine Assoziationsliste,
sucht nach dem ersten List drin Element drin und ersetzt Alle Variable durch den Wert.
Also hier wurde dann tatsächlich mit dieser Möglichkeit, ersetze X durch Vacation,
in dieser Liste jedes Vorkommen von X ersetzt werden durch Vacation.
Also, ot would it mean to you, if you gottin, why?
Und dann würde das in dem X, das hier richtig
so ersetzt werden. Okay, jetzt wollen wir eben noch
diese Listen zurückkriegen, damit wir Subless verwenden können.
Und dazu erweitern wir Dass, dass wir am Ende einfach da,
wo wir bisher Tool zurückgegeben haben, diese Liste zurückgeben.
Ich habe die Folien jetzt übersprungen,
weil das müssen wir wirklich nicht im Detail diskutieren,
dass wir statt Truth zurückgeben mit dem Konstant auf eine Liste der Resultate hängen,
kann sich jeder selbst vorstellen, wie es gemacht wird.
Um aus dieser Liste der Bindung die Werte rauszukriegen,
führen wir noch eine Hilfsfunktion ein.
Get Bindings, die soll einfach in der Liste nachgucken,
an was ist welcher Wert gebunden.
Und das machen wir wirklich als Datenstruktur
Gibt die Bindung, holt das erste Element, holt das zweite Element mit Beinding,
Wall und Look-up-Bindings als Stützfunktion, damit unser Kot klarer wird.
Und zweite kleine Probleme kennen auch diejenigen,
die inzwischen schon mit Prolog und Unifikation gut arbeiten können,
wenn wir eine Variablenbindung haben, dann muss sie in allen Stellen,
an derselben Stelle in gleicher Weise ersetzt werden, sonst geht es schief.
Ja, also Chorreferenz heißt das vornehmen im Pro-Look. Und was wir also haben wollen,
ist, wenn wir Pattern mit Jing machen in X,
um X und um X herum, Dass das wirklich funktioniert,
wenn wir hier raus diesen Zungenbrecher in Ulm,
um Ulm und um Ulm herum machen,
aber eben nicht mit Ulm um Rom und um Ulm herum,
weil in diesem Fall würde X einmal in Ulm und einmal in Rom gebunden werden müssen,
das geht schief.
Also, wir müssen in Pattern-Matching,
nämlich als zusätzliche kleine Komplikationen noch einbauen,
dass die geprüft wird, wenn wir eine Variable binden,
ob diese Variablischen in einen anderen Wert gebunden wurde.
Und in dem Fall, wenn sie schon gebunden war,
dann würden wir einen Fail zurückgeben, weil so geht es nicht.
Also, Wir haben jetzt die Fälle zu unterscheiden,
Variable ist schon gebunden und die Bindung fast zur Eingabe prima.
Variable ist schon gebunden, Bindung passt nicht zur Eingabe fail.
Variable ist noch nicht gebunden, na dann müssen wir sie
eben binden und ab da muss es immer das sein.
Und dann rekursiv auf die Listen anwenden und jetzt zieht uns
der Pet Magic schon einen kleinen Tick komplizierter aus,
aber nicht wirklich schlimm, passt immer noch auf eine Folie.
Hätte dann Input, also das Muster, was wir vergleichen,
die Einladung, mit der wir es vergleichen.
Und hier jetzt unsere Liste mit Bindung, mit Paaren,
XS3, Y ist Rom und Z ist Ulm und
so weiter
Wenn wir in früheren Fällen schon festgestellt haben,
das ist schiefgegangen, dann können wir es jetzt nicht mehr reparieren.
Also wenn die Bindung den Fehlwert enthalten, Pech gehabt,
das geben wir auch viel zurück. Wenn es eine Variable ist,
dann rufen wir eine Hilfsfunktion mit Variable auf und die stellt eben sicher,
dass sie nur matcht abgeglichen wird,
wenn sie nicht schon gebunden ist.
Und ansonsten eben, wenn das Pattern gleich der Eingabe ist,
dann geben wir die Bindung zurück, weil wir fertig sind.
Wenn die ohnehin schon gleich sind,
Dann geben wir die bisherigen Bindungen zurück und fertig.
Man sieht also, dies hier ist eigentlich auch eine entrekursive Funktion.
Und im Endfall, da machen wir ein Peer,
Peter und Peer Input und machen hier die Rekursion.
Über die Kütter und den K. Okay, mit Schwerebelborn im
Einzelnen sich anzuschauen. Und was wir jetzt zurückkriegen,
wenn wir mit dem Pattern-Matching machen, INETX and INET AVacation,
ist eben Explocation.
Und hier hinten ist noch
der Default-Foul-Fell-Trutru drin
Ist die leere Antwort, wenn die Muster überhaupt keine Variable enthalten.
Aber wir sagen wollen, ja, es hätte geklappt,
die sind gleich. Dafür ist es Trutru drin. So,
und wir können es noch so ändern, dass,
wenn, sobald wir in der ersten echte Bindung haben,
dieses lustige Trutru am Ende wegnehmen.
Und weil dann brauchen wir es nicht mehr. So,
also unsere Tests klappen, wir können innen um XOM und
so weiter mit Ulm und Ulm herum metzen müssen.
Hier nur sagen, bisher haben wir keine Beinlinks,
das ist das Trutruh, was wir zu Anfang übergeben haben.
Da kommt Folz raus. Wir können mit diesem Pattern Matching
eine ganze Menge mehr machen, als einfach nur so Texte abgleichen.
Zum Beispiel Wenn wir Ausdrücke hier haben wie Explus 6
und machen ein Matching mit 1 plus 1,
dann können wir also auf diese Weise syntaktisch arathmetische Ausdrücke zerleben.
Brauchen wir später. Kriegen raus x gleich 1. Und wenn
wir x mal x hier abgleichen mit 3 mal 4,
3 mal 4,
da können wir tatsächlich dann dieses 3 mal 4 als gegsamte Unterliste finden und auch das hier rauskriegen.
So, und mit diesen Bindungen können wir jetzt ein Sublets
auf Patton Pattern Matching machen, das Resultat,
was zurückkommt, wird genommen als Assoziationsliste und wir kriegen es
damit eingesetzt
Okay. Pattern-Matching in der vollständigen Form ist ein Tick komplizierter
als bisher besprochen. Über den Teil werde ich jetzt einfach
hinweggehen und nicht im Detail erklären, aber er möchte,
kann sich anschauen, wie es gemacht wird,
falls ich je Pattern-Matcher brauchen für Segmentmuster.
Das Problem ist, wenn wir ein Pattern-Matching haben,
wo wir hier längere Phrasen drin haben, ja?
Zum Beispiel Mr. You Low and I Need DiVication.
Und wir wollen eben diese beiden Symbole zusammen,
Mr. You Low als Teilliste an ein Muster,
eine Variable binden
Und evacation als Teilliste dran binden, dann brauchen wir,
um das Nied herum, eine Syntax, die uns sagt,
also Hoppla, hier brauchen wir ganze Stücke aus der Liste.
Segmentpattern. Und die kennzeichnen wir hier einfach mal,
indem wir das nicht als einfache Symbol reinschreiben,
sondern als Liste, dass die mit Fragezeichensternen beginnt.
Ja, das sieht kompliziert aus, ist es nicht.
Es ist einfach nur zwei elementige Liste und das sagt uns,
dass es ein Segment ist und das sagt uns den Namen,
den wir dafür verwenden wollen.
Okay, und dann brauchen wir noch etwas in unserem Pattern-Match,
was Segmentpatterns erkennt.
So, und da springe ich jetzt mal einfach drüber hinaus
Ich möchte noch zeigen, warum Segment Pattern Matching schwierig ist.
Wenn wir ein Muster haben, wo ähnliche Sachen zweimal nacheinander vorkommen,
dann ist immer die Frage beim Segment Pattern Matching,
wo lasse ich das neue Segment beginnen?
Binde ich an das X, den ganzen Teil Wotty ist
und binde dieses es hier ran oder binde ich das,
dieses ist hier rein, wenn nicht dieses ist?
Wenn die das erste ist, ans Muster binde,
dann wird der Rest nicht aufgehen,
weil das irrlich
gebunden werden kann
Ich muss also tatsächlich, kriege tatsächlich nur eine Lösung, wenn ich das Zweite versuche.
Und deshalb hat der Segment-Pattern-Matcher noch eine Rekursionsschicht mehr,
in der probiert wird, wo man hier wirklich das aufbricht.
Weil man die unterschiedlichen Möglichkeiten alle separat testen muss.
Ja. Okay. Das, was wir jetzt wirklich noch brauchen,
und dazu werden wir die nächste Viertelstunde auch noch gut verwenden können,
ist uns zu überlegen,
wie wir dann die möglichen Fragen und Antworten repräsentieren.
Also Eliza wird unser erstes Beispiel für regelbasiertes Programmieren sein,
wo praktisch die ganze Mächtigkeit der Ausdruckskraft der Sprache und so
weiter in Regeln gegossen ist und durch die Daten repräsentiert wird und nicht so sehr durch den Kontrollrahmen gegeben ist.
Im Kontrollrahmen ist wirklich nicht viel mehr drin, als der Pattern-Matcher,
den ich eben vorgestellt habe, ja. Die Leistungsfähigkeit steckt darin,
dass man richtig schöne Paare findet von Mustern und möglichen Antworten,
die darauf reagiert, die daraus erzeugt werden.
Und das ist in Eliza repräsentiert,
einfach als eine kleine Datenbasis,
wo wir immer die Eingabemuster haben und dann eine
endliche Menge von möglichen Antworten
Und daraus wird dann abgeleitet, was wird durch Zufall eine ausgewählt,
weil zum Baum hatte das noch ein bisschen priorisiert,
wo er gesagt hat, diese sind wichtiger als andere.
Und dann konnte der Dialog losgehen.
Und diese Regeln könnten zum Beispiel aussehen, so aussehen.
Irgendwas und dann kommt das Schlüsselwort, das magische iWant.
Und dann kommt wieder irgendwas und mögliche Rückfragen in einem
solchen Fall sollten eben sein, what would it mean?
If you got
Weil du Yuvonne supposed you got soon, ja?
Also in jedem Fall muss dann immer dieser Y-Teil hier eingesetzt werden.
Und Dysia wird einfach ignoriert. Also das ist das ganze
Geweine vorher, das ignorieren wir. So diese Regeln werden
in der Suchliste zusammengefasst und wir ordnen sie so,
dass die Spezifischsten am Anfang stehen und die Verlegenheitsrückfragen,
bitte mach weiter, die kommen dann am Ende.
Und damit die in der Reihenfolge sind Weizenbonst Prioritäten einfach so abgebildet.
Also ein kleiner Ausschnitt aus der simpelsten Elisa-Datenbasis dir,
wenn Patientin oder Patientin Hello sagen, dann kommt,
sagen wir nur eins, how do you do please state your problem?
So, zweite Regel, wenn da irgendein iWonch kommt,
what would it mean if you got, by do you want,
suppose you got? Ja? Wenn ein If gesagt würde,
do you really thing, it's like, ly do you erwischtet,
what do you think about, really if oder Patient,
Patientin sagen einfach no, also das ist ein No-Go,
macht man nicht, in so einer Sitzung,
dann wird sofort geschimpft, why not?
You are being a bit negative, I you saying,
no just to be negative
Und wenn man einfach sagt, I was,
dann wird zurück, ist es wirklich so?
Wäre Jureli? Perpse eure die New Yore, by do a channel,
you were now? I feel, do you offen feel,
I felt, as a feelings do you have.
So, und damit arbeiten wir jetzt mal los.
In einer Schleife wird so ein Promptzeichen gedrückt,
die Eingabe wird dann mit Ried gelesen, passende Regel gesucht.
Und dann nach den Regeln mit diesem Subluss eine Antwort generiert,
mit Reitlein ausgegeben. Und das Ganze so lange bis Patient,
Patientin bei hat und beisagt und Schluss.
Also der Imax, Variante, die ist so gemein,
die schickt hinterher noch eine Rechnung und die ist ziemlich hoch.
Okay, muss man aber nicht bezahlen. Okay, also unsere Regelbasis.
Use Eliza Rules Input, dies CL-Samm gar nicht drum kümmern.
Es ist die Funktion zusammen, wie man sie aus Recket kennt,
aber weil eben das Windeln mit importiert ist,
ist ein Konflikt in den Namen und dieses CL sagt,
nimm das Sam aus dem Kommenlos-Paket.
Okay, okay und das heißt also, Suche aus der Liste,
die hier unten steht, eine, die Gliza Rules,
eine Regel, für die diese Funktion True gegeben hat.
Und was macht diese Funktion? Die guckt sich die Regel an,
macht ein Pattern-Matching zwischen der Regel, die man gerade durchgeht,
war Judiali und so weiter, mit dem Input,
gibt uns dann die Liste der Variablenbindung zurück,
die finden wir hier und der Result.
Und wenn dieses Resultat kein Fail ist,
dann machen wir mit Subliss, ein Ersetzen der Regeln,
wobei eben die Variablen alle in der möglichen Antwort,
die wir ausgesucht haben, eingesetzt werden.
Jetzt ist hier noch eine zweite Funktion Switch Fewpoint erwähnt,
die ich nicht erwähnt habe,
damit das Ganze grammatikalisch richtig ist, muss aus jedem Ei,
ein New werden, also die Personen einfach ausgetauscht werden.
Bezug die Personalpronomen für den Sprecher, weil Eliza spricht,
fragt ja den Patienten zurück.
Und das wird durch ein Ersetzen, das auch noch gemacht.
Und dann sind wir fertig. Wenn aber hier
das Resultat fail war, geben wir weiter viel zurück
Also das ist die Suice Eliza Rules. Und die Dialogschleife,
die macht einfach nur einen Ried vom Input,
macht ein Whiteline, einen flatten,
nimmt eine Liste von Listen und verbindet die zu einer einzigen flachen Liste.
Das muss geschehen, damit die Teilstücke alle zu einer einzelnen Liste zusammengeführt werden.
Und zwar bei dem, was bei Suice Eliza Rules rauskommt.
Ja, und das Ganze machen wir jetzt so oft,
bis der Patient beisagt. Dafür nehmen wir unsere Funktion höherer Ordnung,
Itorage an Till, Itorante,
eben immer diese Dialogfunktion,
die hier steht
So lange, bis das Resultat, was hier zurückkommt,
war es, und dann sagen wir, ciao, und sind fertig.
Das Switch View Point verwendet auch wieder einfach der Subless. Das wird jedes Mal,
wenn in der, im Muster, was wir nicht im Muster,
sondern in der Eingabe im Input Eye steht,
wird es daraus ein You machen, aus dem You ein Eye,
aus I Me ein You und aus M ein A. Ja,
mit skrammatikalisch ein bisschen überzeugender klingt.
So, also mit dem Programm, wie wir es jetzt realisiert haben,
könnt ihr ein Gespräch mit Elisa so aussehen.
Im Skript habe ich noch einen recht langen Dialog ausgedrückt,
der muss ich mal lange,
lange probieren
Bis ich genug Eingaben gegeben hatte, dass Eliza interessante Rückfragen gestellt hat, ne?
Also, wir sagen, hallo da. Ich leite zurück,
Cau do you do, please take your problem.
I want to test this flogore, by do you want to test this program.
I could see if it works, really if it works,
no, not really, you are being a bit
negative, no, I you saying,
no just to be negative. Forget, forget it,
I was wandering a general to program is.
There you really. Forget it, I was wandering a
general to program is. By do you time,
you were wandering how general to program is now.
I felt like it. What at I feelings to
you have
I feel that is enough. You you're offen feel that is enough.
I do. I'm not sure in a stand you forly
bye bye, bye. Okay. Also in der Form könnte es mit dem,
was wir jetzt realisiert haben, schon funktionieren, ja.
Und das Programm funktioniert also so ganz gut spielen,
sind wir ruhig ein bisschen damit rum.
Und wir haben jetzt schon Pattern Matching und Dialogschleife gesehen,
was wir als nächstes machen werden, nächsten Freitag,
ist, dass wir die Bausteine, die wir jetzt haben,
zur Werkzeugen zusammenfassen und dann damit ein anderes Problem lösen,
nämlich Das automatische Differenzieren, Integrieren, Umformen von allgebraischen Gleichungen.
Im Wesentlichen, so das, was Mathematiker kann,
die Urform davon war entwickelt worden, mit dem Programm Student.
Also das ist ein Programm, was Folgendes leisten konnte.
Die üblichen Textaufgaben, die man so Zweitklässlern stellt, ja.
Klein-Erner geht zum Markt und kauft zehn Eier, die kosten heute einen Euro.
Nächste Woche geht sie hin, will 20,
ah ja, wie viel muss sie jetzt bezahlen?
Also Aufgaben, die in dieser Textform gegeben sind,
analysieren mit Hilfe von Pattern-Matching
Feststellen, was sind die wichtigen Variablen, die Ausdrücke,
Regeln haben, wie man aus diesem Text mathematische Gleichung macht,
die Gleichung auflösen und dann ausrechnen, aha,
für ihre 20 Eier muss Klein Anna das nächste Mal zwei Euro zahlen.
Also Textaufgaben verstehen, dass Gleichungen überführen, Gleichungen auflösen und
die Lösung angeben. Das ist das Programm Student und das
arbeitet mit einer sehr ähnlichen Technik plus ein bisschen dazu.
Das werden wir uns das nächste Mal anschauen,
wie man das machen kann und auf diese Art von Architekturen
gehen eben Programme wie Mathematiker zurück,
die für uns
mit Gleichungen hantieren
So, das kann man uns bei der Gelegenheit noch anschauen.
Ich weiß nicht, ob die Zeit reicht,
vielleicht fährt die auch noch dem General Problem Server, vorstellen.
Und deswegen, wie man den machen kann, der benutzt
eine ähnliche Technik. Was wir an Eliza gesehen haben,
es ist eben wirklich ein Prototyp für einen regelbasierten Übersetzer.
Eine Eingabe kommt rein. Eliza erzeugt daraus einen neuen Text
. Und das ist verkappt tatsächlich ein Übersetzungsvorgang.
Und diesen Übersetzungsvorgaben können wir eben für viele Dinge einsetzen.
Und deshalb werden wir aus dem Pattern-Matcher einen allgemeinen Baustein,
Rulebased Translator machen, Regeln angeben,
wie etwas übersetzt werden soll von A nach B. Und das Dialog-Tool.
Und damit können wir dann das nächste Problem lösen und damit uns eben die Aufgabe machen,
mathematische Gleichungen zu übersetzen und zu transformieren, zu gelösten Gleichungen.
Im Wesentlichen ist unser Rule-Based Translator im Wesentlichen,
besteht ja darin, dass wir eben eine Eingabe geben,
eine Liste von Regeln, dann ein Matching-Werkzeug.
Dafür werden wir
unser Pad Match nehmen
Zug-Akzessor-Funktionen für die Repräsentation der Regeln, das finde ich festgelegst auf ein bestimmtes Format.
Also wenn wir eine Datenstruktur für Regeln haben,
müssen wir eben auf den IFTTAL, Teste der Bedingungen,
ist es erfüllt und was geschehen soll,
wenn es erfüllt ist und die Action,
die dann ausgeführt werden sollen.
Und alles, was man so an Bindungen gesammelt hat,
noch hier, einen solchen Baustein als Funktion höherer Ordnung,
werden wir nächste Woche einsetzen.
Okay,
danke für die Aufmerksamkeit