auseinandergegangen, mit dieser Tabelle, wo wir versucht hatten,
die Fragen zu beantworten, ob ein Verfahren terminiert,
das war insbesondere der strittige Punkt,
wo wir hier lauter Nose drin haben,
was zu Recht die Frage aufgeworfen hat, warum terminiert er Sterben nicht?
Wir haben ja relativ viel Aufwand getrieben,
um die Artefakte der anderen Ansätze zu beseitigen und trotzdem hier ein No drin,
sodass die Vater der Verdacht aufkamen, da stimmt womöglicherweise nicht.
Hat mir jemand in das Buch geguckt? Nein,
es empfiehlt sich in das Buch zu gucken,
hier ist der Ausschnitt aus dem Buch,
eine ähnliche Tabelle etwas abgespeckt gegenüber der auf der Folie
und da finden wir hier unter terminiert das Ganze eine bunte
Verteilung zwischen Jas und Neins
Wie das, mal ja, mal nicht, ja.
Was heißt das? Also insbesondere der strittige Fall war,
terminiert A Stern, ja oder nein,
auf den Folien nein, hier ja.
Es ist hier sogar die weichere Variante,
dass man möglicherweise unendliche Grafen annimmt, während auf den Folien endliche Grafen stand.
Also die Bedingung, auf denen Folien es sogar noch eingeschränkt
gegenüber dem, was hier gemacht wird.
Woran liegt es?
Ich sehe eigentlich
den Unterschied
Künstlichen Grafen argumentiert, dass er aktuell das Problem hat,
zum Beispiel, wenn ich sage, dass ich so eine Strecke habe,
dass zum Ziel ich eine Kante habe,
mit der Kosten eineinhalb, die nächste mit einem Viertel.
Das ist das, das ist das.
Und das ist dort ausgeschlossen. Das hatten wir gestern auch
schon. Das ist das Achill und die Schildkröte-Argument.
Generell Problem. Das haben wir aber hier explizit ausgeschlossen.
Mal sehen, ach sorry, das ist der falsche Foliensatz.
Da müssen wir gucken, ob wir den anderen auch noch
Wenn wir uns die Kostenbedingungen angucken,
also was für Eigenschaften muss eine Kostenfunktion haben,
das war diese Angaben hier, dann entsteht,
alle Kosten sind oberhalb von, also sind positive Zahlen.
Also sie müssen oberhalb eines Äpzilons liegen.
Wenn wir so etwas annehmen, so eine konvergierende Folge,
dann würde das die Bedingung hier verletzen.
Ich hatte genau das gerade daran gelesen und dachte,
es wäre in den Torjägen nicht drin gewesen.
Ja, ja, doch, doch,
das ist leider Gottes da auch mit drin.
Also das schöne Argument aber zieht nicht
Ja, weitere. Dann stand, glaube ich,
auf der Folie nicht, dass sie nur,
dass sie endlich verzweigt sind.
Es sind endliche Grafen auf der Folie, also.
Es geht da even on, hier. Aber halb,
Halt und Finalt Graphs. Dann ist die Folie falsch.
Nein, ist sie nicht. Sie ist tatsächlich wichtig.
Woran liegt das? Bitte? Achso,
das... Wo haben wir denn die da
Also, es ist eine allgemeine Blindheit,
die uns befällt und die uns alle befällt,
die mich gestern auffallen lässt.
Wir müssen in das Kleingedruckte gucken,
wie immer
Und das, was wir tatsächlich alles vergleichen können müssen,
sind wenigstens diese vier Dimensionen. Also ist es der Graf
endlich oder unendlich? Da spielt ja keine Rolle. Hat er
Zyklen oder hat er keine Zyklen? Wir nehmen an,
er hat Zyklen, das sind also auch gleiche Bedingungen.
Wollen wir eine Lösung haben oder wollen wir alle Lösungen haben?
Und das Ganze ist nicht orthogonal. Die sind teilweise abhängig
voneinander. Das ist die relevante Frage. Existiert eine Lösung
oder existiert keine Lösung? Wenn keine Lösung existiert,
läuft natürlich auch A Stern munter im Kreise herum.
Es akkumuliert immer Kosten und man kombiniert immer Kosten,
aber es hat ja noch nichts gefunden
Und das heißt, man kann vermuten, im nächsten Suchschritt
wird die Lösung gefunden. Man kann aber auch die Hoffnung
aufgeben und sagen, es wird keine Lösung geben.
Man weiß es nicht. Das Verfahren terminiert nicht.
Also in den meisten Fällen ist das Terminierungsproblem im Kompliment.
Also nicht bei den positiven Ergebnissen, sondern bei den negativen Ergebnissen zu finden.
Wenn ich das Ganze zwinge, mir eine Aussage darüber zu machen,
dass es gar keine Lösung gibt, dann terminiert das Ganze nicht.
Das ist die Botschaft dabei. Und dann stimmt auch diese Tabelle,
keines dieser Verfahren kann unter diesen Bedingungen sagen, Hallo,
dieser Suchraum enthält gar keine Lösung.
Also stellen Sie sich ganz einfach vor, wir hatten dieses
künstliche Roboter-Problem uns ja angeguckt, wir bauen eine Mauer.
Wir haben also diese Felder hier. Wir haben hier
den Zielzustand G und wir bauen hier ringsherum eine Wiedersehen.
Da liegt aber schon eine Menge. Mann und Mann,
das sind ja ganze Haufen. Wir bauen hier ringsherum eine Mauer. Das heißt,
der Roboter, der sich irgendwo hier draußen befindet,
kann munter im Kreise um die Mauer drumherum laufen.
Er wird bezüglich der Restkosten immer zwischen den verschiedenen Zuständen hin und her springen.
Aber er ist nie in der Lage, sie tatsächlich zu erreichen.
Weil unsere Restkostenabschätzung geht natürlich hier über die Mauer hinweg,
während der Suchpfad durch die Mauer gehen müsste.
Und das kann er nicht. Also das ist ein Beispiel,
wo ich eben nicht nachweisen kann, dass es gar keine Lösung gibt.
Und das ist natürlich eng verwandt mit dem vorhergehenden Kriterium.
Och, falsche Richtung. Mit dem vorhergehenden Kriterium will ich
nur die beste Lösung haben oder will ich alle Lösungen haben.
Wenn ich wirklich, und das unterscheidet auch das Buch,
nie so richtig sauber, wenn ich wirklich alle Lösungen haben will,
Dann ist nach dem Finden der letzten Lösung,
wenn es endlich viele Lösungen gibt, nach dem Finden der letzten Lösung, tritt automatisch dieser Fall in Kraft.
Dann öffne ich die Suche in den gesamten restlichen Raum,
da sind keine weiteren Lösungen mehr, aber wenn dort noch Zyklen sind,
dann geht das Spiel wieder ins Unendliche.
Ja, wir sind jetzt alle weiter.
Gibt es ja eigentlich mal, das Migraphen zu machen.
Wir spenden so immer noch von den Bäumen.
Wir sind immer noch, genau das ist das Argument.
Wir haben... Ein ähnlicher Graph und das klingt eigentlich immer,
dass man Knoten hat und dann Termin aussteigen kann
Ja, das ist richtig. Auch das ist in dem Buch nie sauber unterschieden.
Man müsste eigentlich gleich an den Anfang diese Unterscheidung stellen,
rede ich über Baumsuche oder rede ich über Grafsuche.
Das ist das Allererste. Und das wird nie richtig gemacht
. Aber das Argument ist ganz einfach hier,
wir müssen etwas wegen der Zyklen tun.
Denn die rufen uns dieses Problem ins Haus und deshalb ist
das nächste Thema, wie gehen wir mit Zyklen um?
Also können wir nicht einen Zyklencheck einbauen,
um das Problem auf die Art und Weise zu bekämpfen.
Da muss ich den Sprung machen in diesem Foliensatz
Und da sind wir beim Cycle-Checking. Das ist eigentlich die Argumentationslinie.
Gut, also wir sind bis jetzt mal davon ausgegangen,
wir zerlegen den Suchbau, oder wir expandieren den Suchraum in einen Suchbaum.
Wir sind nicht in der Lage festzustellen, dass wir einen
Punkt schon mal besichtigt haben. Wir haben eben gesehen,
im positiven Falle sorgt die Asternsuche dafür,
dass dann auch die beste Lösung gefunden wird,
weil alle Alternativen, wenn ich in einem Zyklus bin,
immer dafür sorgen,
dass ich dort im Zyklus Kosten akkumuliere,
die diese Lösungsvariante gegenüber anderen Lösungsvarianten
unattraktiv machen
Ja, wenn ich also in der Lage bin,
mit einfachen Mitteln, und das ist immer die Bedingung dabei,
zu überprüfen, wie,
ob ich an einem Punkt schon mal gewesen bin,
ja, also das ist wieder die Großaufnahme unseres Zykluses.
Wir sind von dem Staatszustand hier reingekommen. Wir haben diesen Knoten expandiert,
wir laufen durch den Zyklus hier hin und fassen jetzt diesen Knoten zum zweiten Mal an.
Wenn ich in der Lage bin, das mit einfachen Mitteln festzustellen,
dann kann ich natürlich dafür sorgen,
dass die Expansion unterbunden wird in dem Augenblick,
wo ich feststelle, halt, hier war ich schon mal.
Das ist eine Funktion des Fadens von der Ariadne
Die Frage ist, wie kann ich das am effizientesten machen?
Da müssen wir zwei Verfahren unterscheiden. Entweder wir machen eine
tiefen Suche oder wir machen irgendetwas anderes,
weil es keine Tiefbesuche ist, also zum Beispiel Breitensuche,
da in der Hinsicht unterscheiden sie sich, weiß jemand,
wie ich am einfachsten mit geringstem Aufwand einen Zyklencheck machen kann?
Einfach zu gucken oder zu merken, wo man schon war.
Genau, ja. Komm, dann nehmen wir schon
ein paar
Richtig, ja, also, ich brauche ein Bit dafür,
pro Knoten, wo ich einstelle, hier war ich schon mal.
Und wenn ich zum zweiten Mal an der Stelle komme und das Bit ist gesetzt,
weiß ich, ich bin im Zyklus drin,
ich kann die Expansion auf, unterbinden.
Das ist eben genau das, was bei Tiefensuche funktioniert.
Und das ist mit konstantem Aufwand machbar. Das heißt also,
praktisch ohne Zusatzaufwand kann ich einen solchen Zyklencheck einbauen.
Für andere Methoden ist es wesentlich, es ist komplizierter,
nicht wesentlich komplizierter, ich muss,
das geht dann nicht anders,
ich muss immer den aktuellen Suchpfad nach oben verfolgen und schauen,
ob der Zustand schon mal auf dem Suchpfad aufgetreten ist
oder nicht
Die entscheidende Frage ist natürlich auch hier wieder, was ist der Suchaufwand,
der Basisaufwand, den ich treiben muss und was ist der Metaaufwand,
den ich treiben muss, um Basisaufwand einzusparen.
Also ich möchte durch, naja, hier ist es,
okay, es ist der Unterschied zwischen, naja,
das ist hier nicht ganz interessant, aber trotzdem ist das Argument schon wichtig,
wie teuer ist es, diesen Zyklentrack durchzuführen.
Das ist ja hier nur in Abhängigkeit von der Anzahl der Pfade,
der Knoten auf dem Pfad, die ich habe. Es kann natürlich auch sein,
dass die Bedingungen zum Abtesten komplexer sind,
als einfach nur einen Namen überprüfen oder die Nummer des Zustandes,
ob ich den Zustand 25 schon mal gewesen bin,
dann würde ich den Zustand 25 mir merken müssen,
dass ich da schon mal war und dann schaue ich hinterher die Liste der Zustände nach,
in denen ich schon mal gewesen bin.
Und das kann aber komplizierter werden,
wenn der Zustand eben nicht mehr einfach durch einen Atom gekennzeichnet ist,
sondern über einen Merkmalsausdruck oder aber gar über einen komplexen logischen Ausdruck,
dann wird es komplizierter,
dann kann es exponentiellen Aufwand erfordern,
um für einen Knoten nachzuweisen,
dass ich hier
schon mal war
Also, was weiß ich, Subtimationstests für logische Ausdrücke ist im Allgemeinen NPV-städtig.
Und das müsste ich dann immer überprüfen. Ob dieser Fallschirm
mal eingetreten ist. Gut, wenn ich so einen Zyklencheck einbaue,
heißt das dann auch, dass ich jetzt immer terminiere.
Auf endlichen Grafen ist hier eingeschränkt noch.
Würde ich auch sagen, ja. Also der Grund,
weshalb wir vorher immer da mit No arbeiten mussten,
dass ich nämlich in dem Zyklus hin und her wandere oder herumwandere,
der sollte dadurch
eigentlich entfallen sein
Zweites Problem, was wir haben, ist,
dass zu einem Zustand mehrere Pfade führen können.
Ja, und das ist auch jetzt Grafensuchverfahren.
Ich kann also entweder hier den kurzen Weg nehmen oder hier
einen längeren Weg, lande in dem gleichen Zustand.
Und wenn ich jetzt an kürzesten Faden interessiert bin,
ist natürlich nur einer davon für das Ergebnis relevant, der andere nicht.
Ich kann also hier den längeren Pfad ignorieren,
ich habe jetzt mal angenommen,
dass die geometrische Länge irgendwas mit den Kosten zu tun hat.
Das muss natürlich nicht sein, aber wir nehmen das mal an,
dann wäre das der billigere Pfad,
dann würde ich immer den neben den anderen,
kann ich ignorieren
Die Frage ist, was muss ich alles aufschreiben,
um identifizieren zu können, dass ein solcher Fall vorliegt?
Also was für eine Art von Zwischenspeicher brauche ich,
der mir merkt, Achtung,
jetzt führen zwei Suchtpfade wieder in den gleichen Zustand zusammen?
Die Richtung der Stand der Vermissenschaft verliert werden. Ja,
also wie viele Kosten sind bereits aufgelaufen
bis zu dem Punkt und was noch
Es ist eigentlich, da wir immer davon ausgegangen sind,
wir speichern die Pfade sowieso ab, ist alle Informationen da.
Also der Pfad bisher her, plus die Kosten, die dabei entstanden sind.
Das ist das, was ich mir aufspeichern muss. Und
das muss ich für alle Knoten, die ich bisher besichtigt habe, mir merken.
Eine solche Liste muss ich tatsächlich mitführen. Und dann können wir uns überlegen,
wie ist jetzt das Verhältnis zwischen so einem Test,
der prüft,
ob ich schon mal auf einem billigeren Weg zu einem Knoten gekommen bin,
wie steht das im Verhältnis zu dem Zyklencheck,
den wir
eben gemacht haben
Es ist das Gleiche, tut es mehr, tut es weniger.
Prinzipiell tut es ja mehr. Also es ist wieder Zyklenscheck,
Zyklenscheck, dass es eben merkt, dass es auf den
Zufall so war. Und dann eben aber nochmal guckt,
ob es schon mal quasi schmal da aber mit einer anderen... Gut,
ja, also der Zyklenscheck ist ein Spezialfall dieser Überprüfung hier.
Der einzige Unterschied ist eben, dass wir vorhin für die
tiefen Suchverfahren eine relativ billige Methode haben.
Hier haben wir immer die teure Methode,
dass wir auf der Liste gucken müssen,
ob wir schon mal in dem jeweiligen Zustand gewesen sind
Gut, dann ist die Frage nach dem Terminieren auch relativ einfach beantwortet.
Wenn wir das vorhin mit Ja beantwortet haben,
dann gibt es jetzt keinen Grund, das mit Nein zu beantworten.
Wir haben ein Verfahren, was zumindest das Gleiche tut,
was der Zyklencheck auch getan hat. Es tut noch
ein bisschen mehr. Dann sollten wir also auch erwarten,
dass die Zyklen dadurch zuverlässig vermieden werden. Ja, der Aufwand,
den wir treiben müssen, um den Zyklencheck zu machen,
Ist genau die Verwaltung der Liste, der noch zu Besuchenden,
der schon bereits besuchten Knoten und der Bewertung,
die sie haben.
Und das ist typischerweise mit exponentiellem Aufwand verbunden. Gut,
kann es passieren, dass sich durch dieses Bruden des Pfades
hier eine optimale Lösung verliere,
dass das ganze Verfahren suboptimal wird
Ja? Nein, können wir nicht,
weil wir ja nur das dann ändern,
wo wir eine günstigere Fracht hätten bekommen würden.
Okay, gut. Also natürlich, wir können,
wenn wir uns dumm anstellen, können wir optimale Lösungen verlieren,
aber wir können uns natürlich auch nicht dumm anstellen.
Also die Situation ist, wir finden jetzt einen Pfad später,
der besser ist als einen Pfad, den wir bereits gefunden haben.
Das ist die Situation. Und es gilt prinzipiell drei Möglichkeiten,
die wir wählen können. Entweder wir entfernen alle Pfade aus
der Liste, der noch zu expandierenden Knoten,
die eine höhere Bewertung haben.
Das heißt,
die sind per defiziert
Schlechter. Oder aber wir ändern die initialen Pfade auf der
Liste der noch zu expandierenden Knoten oder aber und den Fall
diskutieren wir nochmal ein bisschen genauer.
Wir wählen ein Suchverfahren, das sicherstellt, dass dieser Fall
nicht eintreten kann. Oder wir formulieren es andersrum,
können wir das Suchverfahren so modifizieren, dass es immer garantiert ist,
dass die kürzesten Pfade zuerst angegangen werden.
Und da sollte man sich in Erinnerung rufen,
dass bei A-Stern hatten wir etwas ähnliches,
dass der optimale Pfad als erstes gefunden wird.
Das haben wir ja gezeigt. Das ist mal genau dann
der Fall, wenn wir eine zulässige Heurestick verwendet haben,
die also und wo die Bewertung bestimmte Bedingungen erfüllt.
Jetzt müssen wir das sozusagen für alle Knoten beantworten.
Nicht nur für die Zielknoten, sondern für alle Knoten des Suchproblems
müssen wir sagen, der beste Pfad wird immer zuerst gefunden.
Und die Frage ist, können wir eine Bedingung angeben,
unter denen das passiert?
Und dazu gucken wir uns wieder ein Gedankenexperiment an.
Wir nehmen an, wir haben einen Pfad,
der zu einem bestimmten Knoten führt.
Eigentlich kann ich doch
auch das hier irgendwie benutzen
Ah, nein, lieber nicht. Ach doch, nein,
da seid extra Rollen angebracht. Wunderbar. Ist das erfüllt.
Also ich habe hier einen Startknoten. Ich nehme an,
ich habe einen Pfad bis zu einem Knoten N. Den habe ich ausgewählt.
Wenn ich ihn ausgewählt habe, heißt es, er muss
eine günstige Bewertung haben. Und dann nehme ich an,
es gibt einen zweiten Pfad, der auch zu Ende führt,
der aber über ein Knoten N Prime führt,
der auf der Grenze zwischen Besuchten und ich bin noch suchten Knoten liegt.
Und wir nehmen an, dass also dieser Pfad hier kürzer
ist als der andere Pfad. Dann, ach so,
das hier ist P. Prime und das ist P. Dann Ja,
ist das jetzt doch, ja.
Okay, dann diesen Party haben wir zuerst gewählt.
Das heißt, es gibt Bedingungen für die Kosten dieses Pfades.
Und das heißt also, die tatsächlich bisher aufgelaufenen Kosten plus
die abgeschätzten Rostkosten müssen kleiner sein als die geschätzten Gesamtkosten für den zweiten Pfad.
Also die Kosten von hier plus die geschätzten Restkosten,
das ist also Kosten von P.
Das ist das, was wir bereits bezahlt haben.
Das ist das, was wir noch bezahlen müssen,
um den Zielknoten zu erreichen
Das muss kleiner sein als die Kosten, die wir haben,
wenn wir von hier aus einen Zielknoten erreichen. Ja,
wir brauchen immer wieder die Summe aus den bisher aufgelaufenen Kosten plus dem,
was in der Zukunft noch zu erwarten ist.
Dann nehmen wir an, wir kennen die tatsächlichen Kosten,
um von diesen Knoten zu diesen Knoten hier zu kommen. Und da wir annehmen,
dass dieser Pfad hier kürzer ist als dieser Pfad ist,
gilt auch noch eine zweite Ungleichung,
Dass nämlich die Kosten, die über diesen Pfadanlauf auflaufen,
kleiner sein müssen als die Kosten, die hier aufgelaufen sind.
Und das können wir jetzt zusammenbauen. Wir können also sagen,
die Kosten, die tatsächlichen Kosten zwischen diesen beiden Knoten müssen kleiner sein,
als die Kosten für den Pfad P. minus die Kosten für den Pfad P. Prime.
Den können wir ja noch drüben umschieben.
Das ist der erste Schritt und der zweite Schritt ist,
der hier oben steht, wir können dieses Diesen Ausdruck umformen,
umformen, indem wir hier Kosten von P-kosten von P-Prime haben.
Und dann haben wir auf der rechten Seite noch stehen,
die Kosten von Endprime minus,
also die geschätzten Restkosten von Endprime minus die geschätzten Restkosten von Edden.
So, das ist die Bedingung, die erfüllt sein müsste,
wenn wir später noch einen Pfad finden, der tatsächlich günstiger ist,
heißt, sehen die mal zuerst angefasst haben.
Das wollen wir verhindern. Wir können eine Bedingung ableiten,
mit der wir das verhindern können. Wenn es passiert wäre,
dann sind die tatsächlichen Kosten zwischen End- und Engement-Prime,
kleiner als die Differenz der geschätzten Restkosten
Und wenn wir umgekehrt fordern,
dass die Differenz der geschätzten Restkosten kleiner ist,
als die tatsächlichen Kostendifferenz zwischen N- und End Prime,
dann können wir sicher sein, dass der Fall nicht eintritt.
Oder mit anderen Worten, wir können garantieren,
dass der bessere Pfad immer zuerst gefunden wird.
Und was wir hier gemacht haben, ist,
dass wir eine zusätzliche Bedingung für unsere Heuristikfunktion formuliert haben.
Jetzt heißt es also nicht nur, sie muss optimistisch sein,
das heißt, sie muss immer einen geringeren Wert liefern,
als die,
als der optimale Wert tatsächlich wäre
Sondern er muss zusätzlich noch die Bedingung erfüllen,
dass die Differenz der geschätzten Restkosten bis zu den Zielzuständen hier kleiner ist,
als die Kostendifferenz, die aktuelle Kostendifferenz zwischen den beiden Teilknoten,
oder Teilfaden, die wir dort betrachten.
Und das wird dann auch als monotone Restriktion für die
heuristische Funktion bezeichnet und muss dann für jede Kante gelten,
die zwischen M und N existiert.
Und wenn das der Fall ist, dann können wir eben garantieren,
dass A. Stern mit diesem Multiple Path Bruning,
immer das erste, den kürzesten Weg zuerst findet.
Und wenn wir danach einen anderen Weg finden,
ebenfalls in diesen Knoten findet, können wir in Blindlings wegwerfen.
Wenn die Heuristik genau diese Bedingung erfüllt. Und das ist
nichts anderes als eine Verschärfung dieses Zulässigkeitskriteriums, dass wir sagen,
tatsächlich muss die Heuristik noch eine zusätzliche Bedingung erfüllen über die optimistische Einschätzung hinaus.
Okay, Ja, jetzt kommt wieder genau die Inkonsistenz hier
hinein, die wir schon diskutiert haben.
Alle Strategien, die garantiert halten können, brauchen exponentiellen Aufwand.
Das bezieht sich eben genau auf das Halten im positiven Falle
nicht auf das Halten, im allgemeinen Falle.
Wir diskutieren jetzt diverse Modifikationen des Themas Suche und eine dieser Modifikationen ist,
ob ihr nicht in irgendeiner Weise die Vorteile der Tiefensuche verbinden können mit den Vorteilen der Breitensuche.
Also der Vorteil der Tiefensuche ist eben immer
der Platzaufwand
Und das ist ein ziemlich hartes Kriterium,
weil Speicher eben immer hart begrenzt ist.
Und der große Nachteil ist eben die Zyklenanfälligkeit. Und die Frage ist,
ob wir nicht die Art und Weise, wie die Tiefensuche vorgeht,
sodass sich immer die gesamte Frantia schrittweise durch den Suchraum bewege,
verbinden kann mit der Unempfindlichkeit gegenüber Zyklen.
Und eine Lösung dafür ist das iterative Deepening.
Und das basiert eigentlich auf einer Idee, die,
wenn man sie das erste Mal hört,
man für völlig verrückt erklärt.
Nämlich,
dass man anstatt die Elemente oder die Such
Zustände abzuspeichern in einer Agenda, dass man sie immer wieder neu berechnet.
Das heißt also, ich gebe eine obere Grenze an,
die obere Grenze ist am Anfang null und ich suche den Baum nur bis zur Tiefe null.
Und dann erhöhe ich schrittweise diese Grenze um eins
und erlaube es der Suche tiefer in den Suchraum vorzudringen.
Und mache aber eine Tiefensuche, die den Vorteil hat,
dass sie immer nur den Pfad und zwar dann der Länge eins,
der Länge zwei, der Länge drei abspeichern muss.
Und wenn denn ich in diesem Teil des Suchraumes nichts gefunden habe,
dann erhöhe ich die Grenze wieder um eins und untersuche den
Suchraum einen Schritt weiter in die Tiefe durch.
Dadurch verhindere ich natürlich, dass ich auf einem Zyklus,
Ad-Infinitum in die Tiefe absause. Denn die Tiefe ist begrenzt,
ich kann immer nur bis zu der vorgegebenen Schranke suchen,
danach bricht die Suche ab. Und wenn in diesem ganzen Suchraum,
den ich bis dahin bearbeitet habe, nichts da ist,
wird die Schranke um eins runtergesetzt und der etwas größere Suchraum durchmustert.
Das Problem ist hier dabei natürlich,
dass ich den Suchraum oben im Baum immer wieder
neue durchsuchen muss
Und das hört sich erstmal völlig verrückt an. Also was
macht es für einen Sinn? Immer und immer wieder die
gleiche Arbeit zu machen, die man schon mal gemacht hat.
In allen anderen Fällen gehen wir hin und machen Memoisation-Techniken.
Wir werden uns dann gleich das Gegenstück dazu angucken.
Das ist dynamische Programmierung. Dynamische Programmierung läuft darauf hinaus,
dass ich mir alle Zwischenergebnisse abspeichere. Und immer gucke,
ob ich dieses Zwischenergebnis sich schon längst mal berechnet habe,
damit ich es sicher zweites Mal berechnen muss.
Es ist tatsächlich so,
dass das in vielen Fällen dynamische Programmierung dazu führt,
dass ich aus dem exponentiellen Bereich in den polynomiellen Bereich von
der Komplexität komme.
Also kontextfreies Pasing ist etwa ein solches Beispiel
Im allgemeinen Fall blinde Suche, exponentiellen Aufwand erzeugt,
wo ich aber dank der Memoisierung, also dank der Tatsache,
dass ich mir die Zwischenergebnisse irgendwo aufschreibe,
ich den Aufwand auf kubische Komplexität drücken kann.
Hier genau das umgekehrte Herangehen. Ich merke mir gar nichts dazwischen,
Ergebnisse, ich behänge sie immer wieder alle neu.
Und dabei mache ich völlig unnötigerweise immer wieder die gleichen Berechnungsschritte,
die ich schon mal gemacht habe.
Gut, wir müssen also dann zwei Zustände unterscheiden.
Entweder die Suche in einem Teilbaum scheitert auf unnatürliche Art und Weise.
Das ist immer das, wenn die tiefen Suchgrenze erreicht ist,
wenn ich den Suchraum vollständig durchmustert habe und in diesem Teil nichts finden kann.
Und natürliches Scheitern heißt, wenn es keine Expansionen mehr gibt für einen Knoten.
Also unnatürlich heißt, ich kann dem Knoten noch expandieren,
aber die Expansion führt in eine Tiefe, die nicht mehr zulässig ist.
Und natürliche Scheitern heißt, ich habe ja einen Knoten,
für den es keine Nachfolger mehr gibt.
Diese beiden Fälle muss man unterscheiden. Und dann kann man
ein Programm aufschreiben, was eine globale Bulsche Variable verwendet,
die auf, ja,
oder,
also auf wahr oder falsch
gesetzt werden kann
Und wir brauchen eine Hilfsprozedur, die im,
heißt ja Debbound Search, also eine tiefenbegrenzte Suche,
der ich immer einen Pfad übergebe, also ab,
wo er zu suchen ist,
und der ich eine Tiefenbegrenzung mitgebe.
Und natürlich muss der Pfad immer kürzer sein als die aktuelle Tiefenbegrenzung.
Und nein, sorry, der Mount ist das,
was noch an Tiefe zur Verfügung steht.
Das wird ja immer getestet auf größer Null.
Also es ist das, was ich noch zum Pfad hinzufügen
kann, bis ich die Grenze erreicht habe
So, und da muss man unterscheiden,
entweder ich habe einen Zielzustand erreicht, ja,
also mit diesem Pfad hier bin ich in einem Zielzustand gelandet und meine Grenze ist gleich null,
dann kann ich das hier als Ergebnis der Suche ausgeben.
Oder aber die Größe, also das ist kein Oder,
sondern das ist alternativ, was dazu führt,
dass ich auch mehrere Suchergebnisse produzieren kann,
indem ich auch nachdem ich ein Ergebnis produziert habe,
wieder noch weiter suche. Wenn die Größe,
wenn ich noch weiter expandieren kann aufgrund der Grenze,
dann expandiere ich eben auf die Folgeknoten von NK Und rufe mit diesem erweiterten Pfad,
wo ich also die Nachfolger von NK jeweils als letzten Knoten hinzugefügt habe und der um eins verringerten Rest tiefe das Ganze wieder auf.
Und wenn denn das nicht der Fall ist, dann,
und es gibt noch Nachbarn, dann setze ich diese globale,
vaiable Natural Failure of Fords.
Gut, und das Ganze wird eingebettet jetzt in das Iterative Deepinning und Iterative Deepinning,
fängt eben mit einer Grenze von Null an,
setzt die Vagable immer auf True
Macht dann die Suche mit dem Staatszustand der Suche und der
aktuellen Grenze, die vorgegeben ist. Und wenn das,
wenn das hier bis zu diesem Punkt kommt,
dann wird diese globale Variable wieder auf Holz gesetzt.
Sie wird ja auf Truh gesetzt und möglicherweise durch diese Unterprozedur
wieder auf Fords gesetzt. Und das Ganze mache ich eben
nur so lange, wie das Ganze noch Truh ist.
Also wenn das hier mal passiert,
dann ist an der Grenze gescheitert
Ja, dann ist eben der Gegen, das Gegenstück dazu,
hier ist die Grenze noch größer als null,
der Gegenstückfall ist dann natürlich, es ist bereits null,
dann muss ich aufhören,
dann wird also dieses Natural Faily of False gesetzt,
der ist nicht auf natürliche Art und Weise gescheitert,
weil es keine Nachfolgeknoten mehr gibt, sondern der ist gescheitert,
weil die tiefe, tiefen Begrenzung erreicht ist.
Gut, und das mache ich eben so lange,
bis ich irgendwann mal tatsächlich nur noch
aufgrund Deck anzuscheitere
Gut, und hier wird also immer, nachdem ich die Suche durchgeführt habe,
die Grenze um eins erhöht und das Ganze wieder von vorne gestartet.
Wieder mit dem Startknoten ganz oben und dann wird schrittweise der Suchraum
nach unten expandiert. So, also eine ziemlich absurde Idee,
die davon lebt, dass immer wieder Aufwand gemacht wird,
der schon mal getrieben worden ist.
Wenn wir uns die Komplexität angucken, dann haben wir das folgende Bild,
dass wir verschiedene tiefen Niveaus in dem Suchraum unterscheiden können.
Also hier sind wir in Tiefe 1,
in Tiefe 2 bis maximal tiefe LKH
Wenn wir die der Ebene 1 und uns angucken,
dann müssen wir bei der Breitensuche, die genau einmal abarbeiten.
Und das Gleiche gilt für die anderen Ebenen,
die Ebene 2 wird einmal abgearbeitet, die Ebene 3 wird einmal abgearbeitet,
die Ebene 4 wird einmal abgearbeitet, worin sie sich unterscheiden,
ist nur die Frage, wie viele Knoten sind auf den verschiedenen Ebenen anzutreffen.
Und auf der Ebene 1 sind es eben B-Knoten,
wenn B, der Verzweigungsfaktor ist, auf der Ebene 2 sind,
dass eben B-Quadratknoten und dann sind es eben hier auf der Ebene k minus 1,
B, hochkam minus 1 Knoten und auf der letzten Ebene B,
hochkarknoten.
Das ist genau der exponentielle Speicheraufwand den ich treiben muss für das Abspeichern der Zwischenergebnisse.
Und das iterative Deepening macht jetzt aber im Unterschied zur Breitensuche,
nicht, dass es jeweils eine Ebene einmal abarbeitet,
sondern die unterste Ebene, die wird nur einmal abgearbeitet.
Bis zur untersten Ebene bin ich erst einmal gekommen.
Die Ebene oben drüber muss ich aber zweimal abarbeiten.
Einmal im letzten Durchlauf, einmal im vorletzten Durchlauf,
die Ebene oben drüber muss ich dreimal abarbeiten im letzten Durchlauf,
im vorletzten Durchlauf und in dem Durchlauf davor.
Und die oberste Ebene, wo sich Karma abarbeiten,
so oft, wie ich die Tiefenbegrenzung erhöht habe,
muss ich
die oberste Ebene durchsuchen
So, und jetzt können wir also im Prinzip den Gesamtaufwand berechnen aus,
kam mal B-Knoten durchmustern, kam minus eins mal B-Quadratknoten durch,
musst dann zweimal und so weiter,
bis zweimal B hochkam minus eins Knoten durchmustern,
bis einmal B-Hochkarknoten durchmustern und das kann man ein bisschen algebraisch umformen,
zu diesem Ausdruck hier unten.
Während ich hier also einen Suchaufwand treiben muss,
der etwas größer ist als B hochka,
weil ich ja auf der letzten Ebene irgendwo mal den Zielknoten finde,
ist hier der Aufwand kleiner, als B hochkam,
mal einem Korrekturfaktor.
Und dieser Korrekturfaktor hat die interessante Eigenschaft, dass wenn er für große Verzweigungsfaktoren,
wenn wir uns die betrachten, geht er gegen eins.
Das heißt also, für große Verzweigungsfaktoren ist das Iterativ Deepinning
nicht viel schlechter, als dies, als die Breitensuche.
Das hört sich erstmal paradox an. Wir machen
irrsinnig viel Zusatzaufwand und trotzdem sieht es so aus,
als ob die Komplexität sich nicht wesentlich ändert
Woran liegt es? Ja, also der Witz ist ja,
dass wir den großen Mehraufwand machen,
wir wollen den oberen, also Ebene in der Tabelle,
also da, wo wir wenig gerufen haben.
Da machen wir es oft, ja. Und wenn wir das so als Polynom haben,
also wenn wir es alles agieren, was jemand erzählt hat,
wenn wir das Ganze ja für große BMK,
wenn das er dominiert durch die letzte Ebene.
Genau. Der Weg, ja,
der wesentliche Aufwand ist immer auf der letzten Ebene.
Alles, was davor passiert ist, ist vernachlässigbar.
Wir sind hier im Bereich des exponentiellen Wachstums. Exponentielles Wachstum
ist jenseits all dessen, was wir uns vorstellen können.
Wir können zwar drüber reden, aber vorstellen können wir es uns nicht.
Und exponentielles Wachstum kann ich auf verschiedenste Arten und Weisen beschreiben.
Und eine Beschreibung ist, was immer in der Vergangenheit
passiert ist, ist irrelevant.
Der nächste Schritt ist der Entscheidende
Ja, das können wir uns an ganz, ganz vielen Beispielen überlegen.
Ich weiß nicht, ob ich das schon mal erzählt habe,
wann immer ich hingehe und für Schüler erkläre,
was das Faszinierende an Informatik ist.
Ja, da gibt es verschiedene Herangehensweisen,
auch von Kollegen, die unterschiedliche Alleinstellungsmerkmale der Informatik diskutieren.
Für mich ist das Wesentliche der Informatik,
dass sie das exponentielle Wachstum beherrschbar gemacht hat.
Über jetzt fast 50 Jahre wächst die Speicherkapazität und wächst
die Rechengeschwindigkeit exponentiell an. Das ist nichts,
was sich irgendjemand von uns vorstellen könnte,
was da passiert ist
Und da habe ich dann immer Vergleiche, dass ich sage,
okay, wir haben jetzt, wir nehmen eine IBM,
360, dieses von Mitte der 60er Jahre,
das ist der erste, in Serie gebaute Großrechner gewesen.
Wir nehmen einen so ein Kasperle-Theater,
Meckintosh aus den 80er Jahren und wir nehmen heutzutage irgendeinen Samsung,
Samsung, Mobiltelefon, was man in der Tasche trägt.
Und dann kann man darüber das exponentielle Wachstum sich veranschaulichen und kann sagen,
okay, wenn also die Rechengeschwindigkeit der IBM 360 die Fußgängergeschwindigkeit
war und der Meckintosh-Rechner das schnellste gebaute Serienauto der Welt ist,
das ist irgendein Bugatti-Sumthing.
Wo sind wir dann bei dem Samsung
Telefon. Ja, jetzt extrapolieren wir das auf die gleiche
Art und Weise, wie die Rechengeschwindigkeit der Prozessoren angewachsen ist.
In welchem Bereich liegen wir? Sind wir noch unterhalb der Lichtgeschwindigkeit?
Sind wir schon oberhalb der Lichtgeschwindigkeit? Wo sind wir? Okay,
das Ergebnis muss man jedes Jahr revidieren, weil die Rechengeschwindigkeit,
glaube ich, mit anderthalb Jahren Zeit, also mit anderthalb Jahren,
ja, Verdopplung läuft und der Speicher mit zwei Jahren oder so ungefähr oder umgekehrt.
Ich bringe die Zahlen auch immer durcheinander. Das kann man also
jedes Jahr neu berechnen. Wir sind zurzeit noch unterhalb der Lichtgeschwindigkeit,
kann man Beruhigen, aber auch das ist jenseits unseres Vorstellungsvermögens.
Alles, was der Mensch jemals an Artefakten produziert hat,
das schnellste Artefakt ist, sind die Voyager-Sonden.
Das sind zwei Stück, die irgendwann vor 20 oder 30
Jahren mal losgegeschickt worden sind und die jetzt gerade dabei sind,
unser Sonnensystem zu verlassen.
Ja, und jetzt kann man die Geschwindigkeit,
die die brauchen, um das Sonnensystem zu verlassen,
das ist die, es gibt immer Fluchtgeschwindigkeiten.
Wie groß muss die Geschwindigkeit sein, dass sich die Erde verlassen kann?
Wie groß muss die Geschwindigkeit sein, dass sich die Sonne
verlassen kann? Und dann kommt die nächste Stufe,
wie groß muss die Geschwindigkeit sein,
dass sich unsere Galaxis verlassen kann
Dann kann ich also die Fluchtgeschwindigkeit aus der Galaxis ins Verhältnis setzen dazu.
Und dann ist also das, was unsere Handys heutzutage können,
wesentlich mehr als die Fluchtgeschwindigkeit aus der Galaxis.
Und das ist das Allerhöchste,
was wir uns im mechanischen Raum überhaupt vorstellen können.
Und das Gleiche kann man jetzt also machen für Speichergröße,
wenn ich annehme, ich rolle den Speicher der IBM 360 aus.
Und das ist ein Meter. Und dann nehme ich,
jetzt weiß ich nicht mehr, wie ich die Bezugsgröße gesetzt habe,
den Mac-Intosh-Rechner da dagegen und habe zwei Punkte.
Und jetzt extra poliere ich das auf die gleiche Art und Weise,
wo bin ich dann? Bin ich noch in Deutschland,
bin ich noch in Europa,
bin ich noch auf der Erde,
bin ich noch im Sonnensystem
Solche Vergleiche kann man dann anstellen. Und das ist jenseits
des Vorstellungsvermögens und in jeder anderen Disziplin führt so ein exponentielles
Wachstum dazu, dass das eine Katastrophe eintritt.
Wenn das in der Physik passiert, ist es eine Atombombenexplosion.
Dann habe ich auch exponentielles Wachstum. Aber nur einmal eine
extrem kurze Zeit, weil danach bricht sofort der Brennstoffzufall zur Reizsamen.
Nur es ist in der kurzen Zeit so viel Schaden entstanden,
dass man mit den Folgen kaum noch leben kann.
Wenn das in der Medizin passiert, dann ist das eine Epidemie,
wahrscheinlich eine Pandemie, die die gesamte Erdbevölkerung der Kraft.
Das sind immer Katastrophenszenarien. In der Informatik haben wir jetzt
dieses exponentielle Wachstum der Ressourcen, über 40 bis 50
Jahre hinweg
Und wir sind immer noch dabei, es beherrschbar zu machen.
Ja. Ich glaube, jetzt habe ich irgendwann die Grenze
erreicht. Gute Frage. Darüber spekuliert man seit zwei.
Darüber spekuliert man seit 20 Jahren. Sind wir nicht inzwischen
so weit, dass das Grenze des Wachstums erreicht ist?
Aber selbst wenn es so ist, haben wir einen Zeitraum überstrichen,
der keine Parallelen in irgendeinem anderen Gebiet kennt.
Und das Verdienst des Informatikers ist nicht, dass er dieses
Wachstum hervorgerufen hat. Das haben hauptsächlich die Physiker gemacht,
die immer kleinere Strukturen entwickelt haben,
wie man bis hin zur atomaren Ebene eben Halbleiterstrukturen manipulieren kann.
Das, was der Informatiker gemacht hat, ist,
dass er die Werkzeuge bereitgestellt hat,
um trotz dieses Wachstums immer noch vernünftig damit umgehen zu können
Also wenn wir mit den gleichen Hilfsmitteln, die wir vor
40 Jahren verwendet hätten, heute modernen Rechner programmieren müssten.
Es wäre eine Katastrophe. Kein Mensch würde das mehr schaffen oder überblicken können,
was doch passiert. Und ich kann ja mal gucken,
ob ich das zufällig hier auf diesem Rechner,
gibt es ja immer wundersame Dinge noch drauf,
ob ich die Grafik noch da habe,
das lohnt sich vielleicht,
wenn ich schon bei dem Thema
mal bin
Nö. Das ist es nicht. Naja, das ist jetzt
wie immer, wenn man, das muss es sein.
Ja, das sieht schon besser aus. Dann kann man hier irgendwie runter. Ja,
das sieht man hier eben die Vergleiche, ja,
das ist das ursprüngliche Bezugssystem gewesen,
das ist dann der Meckern-Touch dazu und dann ist es,
das ist eben schon wieder zwei Jahre alt,
das kann man inzwischen wieder, Ja, genau.
Und das hat man hier. Hier ist mal die,
nicht die Rechengeschwindigkeit, nicht die Speicherkapazität, aber das korreliert miteinander.
Hier ist die Anzahl der Transistoren auf einem Prozessorship aufgetragen.
Über der Zeit von 1971 bis 2011. Das habe ich aus
der Wikipedia irgendwo. Ach ja, da steht es auch.
Das ist von den Wikipedias genommen. Und das ist also eine logarhythmische Skala hier,
wo die Anzahl der Transistoren hier bei 2000 angefangen,
bis hier bei zwei Milliarden irgendwo aufgetragen ist.
Und das sieht also wunderschön, wie eine Die geradeaus über
einer exponentiellen Skala, und das heißt exponentielles Wachstum.
Und wenn man jetzt diese Kurve umrechnet auf,
eine lineare Skala, sodass wir uns das vorstellen können,
was das wirklich bedeutet, dann sieht die Kurve eben so aus.
Das heißt, von 1971 bis ungefähr Mitte der 2000er Jahre
ist nichts passiert. Und dann explodiert es ruckartig.
Das ist exponentielles Wachstum. So sieht das immer aus.
Und genau das Gleiche haben wir in irgendeinem Suchraumproblem.
Auf den oberen Ebenen passiert so gut wie nichts.
Aber auf der letzten Ebene, da schlägt es richtig zu
Und das Schöne an dieser Kurve ist, wenn wir die
gleiche Kurve 1990 aufgemalt hätten, hätte sie qualitativ genauso ausgesehen.
Dann hätte sie so ausgesehen, dass eben bis 1985 nichts passiert ist.
Und seit 1985 ist es explosionsartig in die Höhe gegangen.
Wir können die Kurve an jedem beliebigen Punkt in der Zeit anordnen.
Und sie wird qualitativ immer genau gleich aussehen.
Und das ist die Botschaft. Was in der Vergangenheit passiert
ist, ist vernachlässigbar. Alles, was relevant ist,
ist in den letzten, in einem relativ kleinen Zeitintervall
kurz vor dem aktuellen Zeitpunkt passiert.
Und viel schlimmer. Alles,
was passieren wird, liegt in der Zukunft
Das ist die Botschaft der Informatik. Die relevanten Entwicklungen, die werden hier danach kommen.
Denn wenn ich jetzt die Kurve wieder Zeit verschiebe, ja,
um zehn Jahre beispielsweise, wird sie wieder so aussehen,
dass bis 2015 nichts passiert ist,
aber dann hat es plötzlich zugeschlagen.
Immer unter der Voraussetzung, das Wachstum geht so weiter.
Und da streiten sich jetzt die Jurus,
wird es das oder wird es das nicht?
Ist zum Beispiel die Parallelisierung in der Lage,
die Effekte der nicht mehr wachsenden Transistordichte oder so etwas aufzufangen
Und dadurch die Entwicklung der Rechenkapazität weiterlaufen zu lassen,
auch wenn die Chip-Dichte nicht mehr steigerbar ist, sind neue Paradigmen,
wie Quantencomputing oder so etwas geeignet, die Sache fortzusetzen.
Und in der Vergangenheit ist, das ist ja moores Gesetz,
ist das Ende von Moores Gesetz schon so oft vorhergesagt worden und das ist nie eingetreten.
Es ist schon immer gesagt worden, vier Jahre noch,
dann ist Feierabend. Das Schlimme ist, nein,
das Schlimme nicht, das Fantastische an der Sache ist ja sogar,
dass die großen Chip-Hersteller mit dieser Kurve planen, Ja,
die Investitionskosten für die nächste Generation von Chips sind so gigantisch hoch,
dass man sich da keine Pleiten erlauben kann.
Das heißt, die setzen sich mit den Abnehmern der Chips
zehn Jahre vorher hin und machen die Planung dafür,
wie die nächste Generation von Maschinen aussehen muss, die diese Chips herstellt.
Das ist Planwirtschaft inzwischen, die da betrieben wird.
Das ist nicht mehr wildes Wachstum. Das ist gesteuerte Entwicklung
. Und immer geleitet durch diesen Optimismus,
es hat über die letzten 40 Jahre funktioniert,
es wird auch über die nächsten zehn Jahre weiter funktionieren.
Ob es stimmt, werden wir in zehn Jahren
vielleicht wissen oder in 15 Jahren
Aber jedenfalls das nur zur Illustration, das ist der gleiche Effekt,
der zugrunde liegt, bei diesem Iterativ Deepinning.
Was immer ich in der Vergangenheit an Aufwand getrieben habe,
ist vernachlässigbar. Ich muss mich darum nicht weiter kümmern.
Der Hauptaufwand entsteht hier auf der untersten Ebene.
Und deshalb habe ich also nur einen kleinen Korrekturfaktor.
Dieser kleine Korrekturfaktor beschreibt den zusätzlichen Aufwand,
den ich auf den oberen Ebenen treiben muss,
für das wiederholte Durchrechnen des Suchraumes
Ja, das kann man,
ein zweiter Variation des Suchthemas ist Brunch and Bound,
Brunch and Bound, zählt auch darauf ab,
die Vorteile von der Tiefensuche zu retten, also immer begrenzter Speicherplatzaufwand.
Das ist immer wieder das Thema, was wir haben.
Und wir wollen jetzt diese tiefen Suche mit heuristischer Informationen verbinden,
ohne dass wir den Schritt zur Breitensuche machen müssen.
Und Tiefen, also Brandschen Bound ist dann etwas,
was die optimale Lösung findet,
was auch mehrere Lösungen finden kann,
wenn es mehrere Lösungen gibt,
unter diesen
die Optimale finden kann
Und den Vorteil, der begrenzt, des begrenzten Speicherbedarfs hat.
Die Idee ist ganz simpel. Ich habe immer eine Schranke,
die mir sagt, was ist die beste Lösung, die ich bisher gefunden habe?
Und wenn ich einen Pfad habe, wo die abgeschätzte,
die abgeschätzten Kosten, also bisher hier kosten,
plus Restkosten geschätzt, größer ist als diese Schranke,
die ich vorgegeben habe, dann ignoriere ich diesen Pfad.
Und wenn ich also einen Pfad zu einem Ziel finde,
der noch nicht beseitigt worden ist,
dann muss er besser sein, als der vorangegangene Pfad.
Und ich kann die Schranke, also die Variable Bound,
auf den neuen Wert setzen und sagen, so,
der beste Pfad, den ich bisher gefunden habe,
ist so und so gut.
Und ab sofort möchte ich nur Pfade haben,
die noch besser sind als dieser.
Und das geht eben in einem Tiefensuchmodus, sehr schön zu realisieren.
Die Frage ist, wie müssen wir die Schranke initialisieren?
Haben Sie Vorschläge? Also, auf welchen Wert setzen wir
anfangs die Schranke
Wenn wir sicher gehen wollen, unendlich, ja,
wir können natürlich das auch modifizieren. Also die einfache Antwort
ist unendlich. Und wenn wir die erste Lösung haben,
dann wird die Schranke eben auf die Güte der ersten Lösung
runtergesetzt und dann sukzessive möglicherweise noch weiter verfeinert.
Wir können aber natürlich auch eine Abschätzung des optimalen, der Kosten für den optimalen Pfad verwenden.
Wenn wir das irgendwie gut können in einem Suchproblem,
dann können wir das auch als Anfangswert verwenden.
Wenn wir nämlich eine solche Abschätzung haben,
die nur ein kleines bisschen besser ist, als die Kosten des optimalen Pfades,
dann können wir durch die Schranke die Tiefensuche zwingen,
oder weniger genau die gleichen Klaoten zu betrachten,
wie die A-Sternsuche es auch tun würde.
Dann hätten wir den Vorteil, dass wir die gleichen Aufwands,
den gleichen Aufwand wie die A-Sternsuche treiben,
ohne dass wir diesen exponentiellen Speicherplatzbedarf der A-Sternsuche haben.
Das wäre das Geniale an der Sache. Die Frage ist nur,
haben wir so eine Schätzung, ja oder nein?
Und wie können wir nicht ohne weiteres verantworten?
Hat dann im allgemeinen Fall nicht. Aber möglicherweise in speziellen Anwendungen
kommen wir relativ gut dran. Es ist sogar so,
dass es nicht so schrecklich, eine schreckliche Katastrophe ist,
wenn wir hier etwas etwas falsch liegen.
Wir können nämlich als dritte Variante auch sagen,
wir nehmen erstmal irgendetwas wie eine optimistische Schätzung der Restkosten und gucken,
ob wir nicht eine Lösung finden damit.
Und wenn wir keine Lösung finden,
dann erhöhen wir eben die Schranke ein bisschen und suchen nochmal.
Und wenn wir wieder keine finden,
dann erhöhen wir die Schranke wieder ein bisschen und suchen nochmal.
Das erinnert ein bisschen an Internative Deepening. Nur,
dass wir jetzt eben nicht sagen,
wie tief in den Suchraum sollst du suchen,
sondern wir sagen, suche solange du Lösungen findest,
die besser als eine bestimmte Schranke sind.
Und dann erhöhen wir eben so lange die Schranke,
bis wir irgendwann mal eine Lösung gefunden haben
Dann sind wir in einem Verfahren, was eine große Ähnlichkeit
mit Eteritiative Deep Bidding hat. Also man sieht schon,
man kann den Gedanken von Suche auf verschiedenste Art und Weise modifizieren.
Eine weitere Dimension ist, wie sollte man eigentlich suchen?
Wir haben ja immer einen Suchraum mit einem oder mehreren
Startknoten und einem oder mehreren Zielknoten.
Sollen wir lieber vom Startknoten zu den Zielknoten hinsuchen oder sollen wir
lieber von den Zielknoten zu den Startsuchen, Startknoten hinsuchen?
Beides ist möglich. Die Definition, die wir
bisher verwendet haben, sind vollständig symmetrisch.
Wir können das gegeneinander austauschen
Es gibt ein paar Heuristiken, wie man sich überlegen kann,
was günstiger ist. Eins davon sind die Verzweigungsfaktoren. Ja,
wenn also der Verzweigungsfaktor in der Vorwärtsrichtung
größer ist als der Verzweigungsfaktor in der anderen Richtung,
dann sollten wir eher rückwärts suchen oder umgekehrt.
Also immer in der Richtung,
wo wir den geringeren Verzweigungsfaktor haben,
denn der war die Haupteinflussgröße auf unseren Rechenaufwand
Gut, also hier oben geht der Verzweigungs-,
hier unten ist der Verzweigungsfaktor, das ist hier die Tiefe im Suchraum,
wenn wir den klein halten können,
dann haben wir relativ viel Suchaufwand gespart.
Nicht immer ist die Rückwärtsvariante auch tatsächlich ermöglicht.
In vielen Fällen werde ich also die Suchzustände generieren muss,
steht mir nur eine Richtung zur Verfügung, aber nicht die inverse Richtung.
Dann kann man da nicht eine Auswahl treffen. Eine Idee ist jetzt,
ob man nicht das beides miteinander kombinieren kann,
wenn ich also von vorne suche und von hinten suche,
möglicherweise mich irgendwo da mittendrin treffe
Das kann man machen. Und das führt dann auf einen Gesamtsuchaufwand,
der deutlich kleiner ist als dieser hier,
weil er eben hier einen kleineren Exponenten hat,
der dieser lineare Faktor, der ist dann vernachlässigbar für die Komplexitätsklasse.
Aber der Exponent ist nur noch halb so groß,
ist immer noch exponentielles Wachstum,
aber nicht mehr ganz so starkes exponentielles Wachstum.
Und genau wie die restlichen, der restliche Aufwand exponentiell ist,
ist auch das, was ich spare, exponentiell.
Also ich spare exponentiell vielen Aufwand, aber das,
was übrig bleibt, ist immer noch exponentiell.
Also insofern kann man
sich drehen und wenn,
wie man will
Das Problem hierbei ist nur, dass die Vorwärtssuche sich mit der Rückwärtssuche irgendwie treffen muss.
Wenn ich also beides jetzt mit Tiefen suche, mache,
weil Tiefensuche eben vom Speicherbedarf her attraktiv ist,
dann kann es sehr leicht sein,
dass die ihre Pfade aneinander vorbeibauen und ich nie dazu komme,
dass ich einen gesamten Pfad von vorn nach hinten konstruieren kann.
Das ist ein Problem und das kann man beispielsweise lösen,
dass man in der einen Richtung Breitensuche macht,
in der anderen Richtung Tiefensuche macht,
dann ist garantiert,
dass die Suchräume irgendwann mal
sich treffen müssen
Problem ist nur, dass es sehr schwierig ist zu entscheiden,
in welche Richtung man wie suchen sollte.
Das ist dann meistens suchproblemabhängig und gibt wenige heure Sticken dafür.
Eine weitere Idee ist, ob man nicht im Suchraum bestimmte Inseln identifizieren kann,
durch die der optimale Pfad mit Sicherheit durchgehen muss.
Dass ich also auf dem Weg vom Startknoten zum Zielknoten über
eine bestimmte Anzahl von Teilbereichen im Suchraum muss,
weil ich die initiale Annahme habe,
dass die auf jeden Fall Bestandteil der Suche sein werden
Das führt uns auf hierarchische Planungsprobleme. Also,
wenn wir das Problem, was wir schon mal andiskutiert hatten,
nehmen, wir wollen von hier die Mona Lisa besuchen,
dann wird eine Grundsatzentscheidung sein,
wir fahren mit der Bahn oder wir fahren mit dem,
wir fliegen mit dem Flugzeug.
Wenn wir mit dem Flugzeug fliegen, dann müssen wir über den Flugplatz.
Irgendwie. Weil irgendein Flughafen. Und damit haben wir eine Insel definiert.
Ja, dann können wir nur noch Wege suchen,
ab sofort über diese Insel führen. Und die Teilprobleme,
wie ich von einer Insel zur anderen komme,
die nächste Insel wird dann wahrscheinlich der Flughafen in Paris sein
Und dazwischen gibt es nur relativ wenige Möglichkeiten,
ob ich über Amsterdam fliege oder einen Direktflug habe oder wie auch immer.
Und dann kann ich wieder noch planen, ja,
wie komme ich eigentlich zu dem Flughafen in Hamburg?
Da kann ich mit dem Bus fahren,
ich kann mit der S-Bahn fahren, ich kann ein Taxi nehmen,
kann laufen oder was für Möglichkeiten man da so hat.
Und auf die Art und Weise kann ich jetzt das große Planungsproblem zerlegen,
indem ich eben vorher in einer Grobplanung sage,
was sind eigentlich die Inseln,
über die meine Suchetappe und über die meine Reiseetappen führen sollen.
Und damit habe ich viele kleine Planungsprobleme zu lösen,
die dann mit weniger Aufwand abgearbeitet werden können
als das große
Problem. Und auch da habe ich dann wieder den Vorteil,
jetzt ist es hier eben nicht nur der halbe Aufwand,
wie bei der Kombination von Vorwärts- und Rückwärtssuche,
sondern so viel, wie ich die Probleme zerlege.
Das geht dann hier eben als Quotient in den Exponenten ein. Ja,
natürlich macht man hier Vorentscheidungen mit der Entscheidung für eine solche Insel,
legt man die Suche auf ganz bestimmte Zwischenstationen fest.
Und es kann sein, dass diese Vorentscheidung nicht mehr
den optimalen Pfad garantiert. Das ist eben eine Heuristik,
die ich mache und die kann falsch sein.
Das ist leider so. Aber immerhin bin ich dann in
der Lage, eben hierarchische Planungsprobleme einigermaßen effizient zu lösen.
Und zwar auf der richtigen Granularitätsebene zu lösen. Dann habe ich
eben für das Problem, wie komme ich zum Flughafen,
eine angemessene Repräsentation in Form des Nahverkehrs.
Und ich habe für die Frage,
wie komme ich von Flughafen zu Flughafen, meine angemessene Repräsentation.
Und ich komme nicht auf die Idee,
auf die ein blindes Verfahren natürlich kommen würde, zu versuchen,
von hier nach Paris, mit Hilfe von Nahverkehrsmitteln zu kommen.
Geht ja, gibt bestimmt irgendeine Möglichkeit, das zu machen.
Aber es wäre natürlich hochgradig stupide,
das zu versuchen
Okay, gut,
das waren verschiedene Varianten von Suchproblemen und zum Abschluss wollte ich die Idee des dynamischen Programmierens nochmal ansprechen und zwar etwas ausführlicher als das im Buch und auch auf den Folien,
die die Autoren zur Verfügung gestellt haben, bisher passiert ist,
weil nämlich in ganz, ganz vielen,
das ist jetzt eine subjektive Wahrnehmung, aber in allem,
was ich beobachte, steckt in ganz, ganz vielen Verfahren,
die irgendwie in dem Bereich der künstliche Intelligenz hineinreichen,
die Idee der dynamischen Programmierung drin.
Und es ist auch hier wieder so, wie bei der Sternensuche,
beispielsweise, dass ich ein Optimierungsproblem lösen will,
dass ich einen optimalen Pfad finden will und solche Optimierungsprobleme in nicht strukturierten Domänen,
wo ich also keine analytischen Verfahren anwenden kann,
sondern wo ich gezwungen bin durch Komposition von Suchpfaden,
mir die optimale Lösung zusammenzubauen, die findet man eben in sehr,
sehr vielen Bereichen der intelligenten Systeme.
Und Der Unterschied zur Sternsuche ist, dass ich hier
keine Restkostenabschätzung brauche. Und dass ich auf die Art und
Weise für viele Probleme zu einigermaßen effizienten Lösungen komme,
auch wenn ich über die Restkostenabschätzung gar nicht verfüge.
Das Ganze ist eine Suche nach einer optimalen Lösung.
Wir müssen uns immer im Auge behalten,
dass die allgemeine Suche, wo ich keine Bewertungsfunktion habe,
einen Grenzfall der Suche nach der optimalen Lösung ist
Ja, wenn ich also eine Kostenfunktion habe,
die mir sagt, bestimmte Lösungen sind günstiger als eine andere,
kann ich natürlich die Kostenfunktion immer so definieren,
dass sie gleiche Kosten für alle Lösungen erzeugt.
Dann fällt die Steuerungsfunktion der Kostenfunktion natürlich weg. Dann kann ich
nicht mehr sagen, versuche erstmal diesen Pfad Edoyenenpfad versuchst,
dann sind die alle gleichermaßen gut bedient und dann kann ich so etwas immer benutzen,
um ein Liefer mir alle Ergebnisse, Suche durchzuführen.
Also das ist immer der allgemeine Fall und einer kostenbasierten Suche,
die kann ich immer so einrichten,
dass ich
gleiche Kosten annehme
Also insofern ist das das mit den Kosten nicht zwingend und wir werden auch gleich sehen,
dass man gut und gerne aus so einer dynamischen Programmierung auch alle Lösungen rekonstruieren kann.
Nicht nur die, die besonders gut bewertet sind.
Aber wir gucken uns das als Optimierungsproblem an, haben aber immer im Hinterkopf,
dass Optimierung nur ein Spezialfall der allgemeinen Suche ist.
Die Idee ist relativ alt,
die geht auf einen Ökonomen zurück, der wahrscheinlich auch Mathematiker,
der über Optimierung im betriebswirtschaftlichen Kontext nachgedacht hatte und der die Idee in verschiedenen Varianten formuliert hat,
das ist eine Formulierung von mir hier, die darauf zurückgeht,
wenn ich die Kosten einer, einer komplexen Entscheidungsfolge ermitteln soll.
Oder die optimale, eine optimale Entscheidungsfolge ermitteln soll.
Dann kann ich das in Teilentscheidungen zerlegen.
Und wann immer ich eine Teillösung habe für das Problem.
Und diese Teillösung führt mich in einen bestimmten Zustand des Suchproblems.
Dann kann ich, also partielle Lösung heißt hier,
die optimale Lösung für dieses partielle Problem
Dann wird diese optimale Lösung für das partielle Problem,
Bestandteil der globalen, optimalen Lösung sein,
wann immer dieser Zustand Teil der globalen Lösung ist.
Das heißt, ich rechne für alle Zustände meines Suchraumes aus,
wie ist der optimale Weg, dorthin zu kommen.
Ob dieser Weg oder ob dieser Knoten, den ich gerade betrachte,
jemals Bestandteil der globalen Lösung sein wird,
das weiß ich nicht.
Aber wenn er es ist, dann weiß ich bereits,
wie ich auf optimale Weise
dahin komme
Das ist die Grundidee dafür. Also ich baue eine Tabelle auf,
wo ich alle Kosten abspeichere,
je nachdem, wie rum ich das aufbaue,
ob vorwärts suche oder rückwärts suche, sind es eben die Kosten,
um einen Knoten zu erreichen oder aber diesen Knoten wieder verlassen zu können.
Und das kann ich rekursiv aufbauen,
die Kosten für einen bestimmten Knoten sind nämlich jetzt das Minimum
der Kosten für alle Vorgängerknoten oder alle Pfade,
die zu dem Vorgängerknoten führen,
plus die Kosten,
die es bereitet,
von dem Vorgängerknoten zu dem aktuellen Knoten
zu kommen
Wenn ich also alle diese Vorgängerkosten bereits kenne, brauche ich
immer nur die aktuellen Kosten für den nächsten Schritt darauf zu addieren.
Und dann kriege ich die Kosten bis zu diesem Punkt heraus.
Und diese Idee ist unglaublich unglaublich attraktiv. Ich hatte es
schon angedeutet, also im Parsing kontextfreier Grammatiken führt das dazu,
dass ich eben den exponentiellen Aufwand verlasse,
den Bereich des Worst-Case-Aufwandes exponentiell verlasse und bei Polynumiell-App lande.
Und zwar kubischer Aufwand über der Länge der Eingabekette
Und das ist in vielen Gebieten so,
dass genau auf die Art und Weise man sehr viel Aufwand sparen kann,
weil ich nämlich jetzt nicht mehr den Aufwand über alle Pfade berechnen muss und der ist immer exponentiell,
sondern es reicht mir aus, iterativ diese Tabelle aufzubauen.
Also, das Ganze kann ich immer anwenden,
wenn ich nach einem optimalen Pfad suche,
wie gesagt, wir haben im Hinterkopf,
dass das nur ein Spezialfall einer allgemeinen Suche ist,
wenn ich den Zielzustand vorher kenne, ich muss aber keine Restkostenabschätzung machen können.
Ich muss nicht sagen können, wie teuer wird es
wohl noch werden, diesen Zuzustand tatsächlich zu erreichen
Aber ich muss natürlich wissen, wo er liegt.
Und der Graf muss klein genug sein, weil ich nämlich diese Distanztabelle,
die man hier berechnen muss, diese genau diese Kosten von Emd-Tabelle,
die muss ich für alle Knoten des Suchraumes aufbauen.
Und das ist im Worst Case wieder exponentiell. Wir werden uns angucken,
dass in den praktisch interessanten Fällen es überhaupt nicht exponentiell ist.
Und dadurch wird das Ganze so attraktiv. Die Anwendungsbeispiele sind zahlreich,
wir gucken uns zweimal an. Das eine ist Tippfehler-Korrektur,
wo ich nämlich zwei Zeichenketten aufeinander mappen muss. Das,
was zu korrigieren ist und mögliche Hypothesen wohin man es korrigieren muss.
Und dann will ich ein Ähnlichkeitsmaß oder ein Abstandsmaß zwischen den beiden haben,
wie wahrscheinlich ist es, dass das eine eine Modifikation des anderen ist,
sodass ich es ersetzen kann.
Das ist ja die Aufgabe der Zeichenkettenkorrektur,
ähnliche Probleme hat man in der Genomanalyse,
wo es darum geht,
in Tronds von Exons zu unterscheiden,
also die kodierenden Abschnitte der Gehenstruktur von den nicht kodierenden Abschnitten der Gehenstruktur oder aber auch Gene selber zu erkennen.
Und wir gucken uns noch eine Anwendung aus der Frühzeit der Spracherkennung an.
Die war dann später noch, wenn wir die provabilistischen Modelle haben,
erweitern können auf das,
was heutzutage da in der Welt passiert
Es wird auch verwendet in Bereichen, wo wir strukturelle Klassifikationen betreiben. Strukturelle Klassifikation ist immer dann gegeben,
wenn ich nicht bestimmte Objekte meiner Realität,
der Realität klassifizieren will, nach, das ist ein Fenster,
das ist eine Lampe, das ist ein Beamer,
das ist ein Lautsprecher, also atomare Kategorien habe,
sondern wo die Kategorien, die dort rauskommen, Strukturen enthalten.
Also beispielsweise, Herr Neumann macht so etwas,
ich sehe da draußen ein Haus und ich kann an diesem Haus Strukturen erkennen,
nämlich Reihen von Fenstern, Fenstern sind,
wenn ich gerade Mein Gott,
jetzt fällt mir der Name nicht ein.
100 Wasserhäuser haben, sind die üblicherweise in waagerechten,
also in horizontalen Reihen angeordnet.
Ich kann bestimmte Strukturen erkennen, was ist die Eingangstür eines Hauses?
Das definiert sich nicht durch geometrische Merkmale,
sondern durch die Einbettung eines geometrischen Merkmales in den Kontext.
Eine Haustür kann ich nicht im ersten Stock anbringen.
Dann ist es vermutlich der Eingang zu einem Balkon.
Dann muss das aufgrund der Informationen,
die ich dort habe, der gesamten strukturellen Einbettung eben als
Balkon mit Tür klassifiziert werden
Und das sind strukturelle Erkennungsprobleme und sowas ähnliches hat man eben auch im Bereich der Sprachverarbeitung,
wenn es darum geht, Sätze zu übersetzen beispielsweise.
Das ist keine Einzelentscheidung über Wörter, sondern das ist Entscheidungen über ganze Strukturen.
Ein Satz beispielsweise. Schlimmstenfalls auch ein Satz noch in einem
bestimmten textuellen Kontext. Oder aber, wenn ich diesen Tax,
so eine taktische Struktur eines Satzes ermitteln will,
also mit Hilfe einer Grammatik beispielsweise,
dann ist die Aufgabe da eben eine Entscheidung über die Struktur zu treffen,
die nicht nur lokal sich die einzelnen Wörter anguckt,
sondern die das Gesamtgebilde des Satzes betrachtet
Und das Ergebnis einer solchen strukturellen Klassifikation ist dann eine Strukturbeschreibung für den gesamten Satz,
die mir eben sagt, wo ist das Objekt,
wo ist das Subjekt, wo ist das Prädikat des Satzes,
wo sind Lokalbestimmungen und so weiter und so fort.
So, es gibt immer effiziente Lösungen,
wenn ich einen relativ kleinen Verzweigungsfaktor habe, na gut,
das ist trivial, das ist für jedes Suchproblem,
so, aber was wichtig ist,
in den meisten erfolgreichen Anwendungsfällen ist es so,
dass der Verzweigungsfaktor kompensiert wird durch einen gleichgroßen Rekombinationsfaktor.
Das heißt also,
wo überall mal sich ein Pfad in drei Alternativen Tiefen aufspaltet,
gibt es eine Stelle, wo drei Alternativen wieder zusammengeführt werden,
sodass das exponentielle Wachstum in der Breite der Suche gar nicht auftritt.
Das heißt, die Grenze zwischen dem explorierten und dem nicht
explorierten Bereich ist, auch bei der Breitensuche, konstant.
Sie wächst nicht exponentiell und das ist das Wesentliche dabei.
Also immer dann kann ich das effizient anwenden und wir gucken uns
gleich Beispiele an dafür. Und was auch wichtig ist,
dass die Identität von Knoten, das Ganze basiert darauf,
dass ich entdecke, ich war in diesem Zustand schon mal.
Das haben wir vorhin schon diskutiert,
dann muss auch der Test darauf,
war ich in diesem Zustand schon mal,
in Unit Time erfolgen können
Der darf nicht exponentiellen oder kombinatorischen Aufwand erzeugen.
Das heißt, es muss relativ einfache Beschreibungen geben,
in welchem Suchzustand befindet sich mein Verfahren gerade. So,
erstes Beispiel, wir gucken uns das am Beispiel an,
ist also, wir wollen zwei Zeichenketten miteinander vergleichen.
Und das wird jetzt zerlegt in Einzelentscheidungen, nicht über die gesamte Kette,
sondern dass wir uns paarweise die Buchstaben angucken und immer entscheiden,
passen die zusammen oder passen die nicht zusammen?
Und wir haben nur vier Fälle zu unterscheiden.
Das eine ist, die zwei Buchstaben,
die wir gerade uns angucken,
sind identisch
Ja, dann liegt erst der Fall vor.
Die zweite, sie sind nicht identisch. Dann liegen drei
Fälle vor. Entweder ist es eine Ersetzung des einen durch
das andere oder aber in der einen Kette ist ein Zeichen
eingefügt worden oder aber es ist ein Zeichen weggefallen.
Das können alles Ursachen dafür sein, dass die nicht identisch sind.
Und was ist der Verzweigungsfaktor des Suchproblems?
Ja, vielleicht um die 30,
eine alte Wendschaft
Nö, nö, viel zu hoch. Das ist alphabetunabhängig
. Ich muss keinerlei Annahme über den Zeichenvorrat machen.
Da kann ich beliebige Sachen reinschreiben. Alles, was getestet wird,
ist, sind die Dinger identisch, ja oder nein?
Also, ob das 8-Bit-Repräsentation sind oder 16-Bit-Repräsentationen oder 64-Bit-Repräsentationen,
spielt keine Rolle. Das können chinesische Zeichen sein,
lateinischer, das ist vollkommen egal.
Ja. Bitte? Genau, drei, wieso drei?
Warum nicht vier? Hier stehen noch vier, war ja.
Ja, passen. Oder habe ich das Ergebnis oder ich
habe eigentlich drei Möglichkeiten an Reflexituationen. Ne, Moment,
da hast du dich verstanden,
zwei oder drei
Bitte? Drei. Also meine,
ich weiß nicht genau, ob wir vom Gleichen reden.
Meine Variante ist, die ersten beiden unterscheiden sich eigentlich nicht
in der Art der Abbildung der einen Kette auf die andere.
Ich nehme jeweils das nächste Zeichen und sage, die beiden gehören zusammen.
Worin sie sich unterscheiden, sind die Kosten.
Wenn sie gleich sind, kosten null,
wenn sie nicht gleich sind, kosten eins beispielsweise.
Also die beiden zusammen ist die erste Alternative,
das ist eine zweite Alternative, das ist eine dritte Alternative.
Und das ist ein konstanter Verzweigungsfaktor,
der sich durch das gesamte Problem durchzieht
Ja, also wir müssen jetzt das Stringmapping als Suchproblem irgendwie darstellen.
Und wir müssen diese Eigenschaften definieren. Also wie kann ich
einen Zustand beschreiben? Was ist der Zustand eines Stringmapping-Problems
jetzt in den Begriffen der Suche?
Welche Informationen muss ich in dem Suchzustand alles speichern?
Ja, was ist das für ein Charakter eines Strettertes?
Und ja, von anderen Stringen natürlich auch.
Nee, das reicht nicht aus
Also, wir haben irgend so etwas wie, du dumm.
Ja, was weiß ich, gehen,
machen wir es gleich getrennt, dann ist es besser.
Und geben. Ja, ich fange jetzt an,
von links nach rechts durchzugehen, muss mich irgendwie einigen,
entweder von rechts nach links oder von links nach rechts.
Ich mappe die ersten beiden übereinander,
das ist eine Identität
Ja, ich gehe einen Schritt weiter,
ich merke die beiden übereinander, das ist auch eine Identität.
Jetzt komme ich darauf, dass ich verschiedene Hypothesen habe.
Ich könnte also sagen, okay, hier ist eine Substitution da,
oder aber dieses H ist eingefügt worden,
oder aber dieses B ist weggelassen worden.
Was muss ich alles speichern, damit ich ab dieser Stelle
dann weitersuchen kann? Also für dieses partielle Ergebnis bis hierhin
, was ist die relevante Information?
Also der Buchstabe hier alleine, der tut es nicht.
Das ist nicht die Frage. Das Haar kann mehrfach in
einer Zeichenkette auftreten,
dann weiß ich nicht mehr,
welches davon gemeint ist
Die Position in der Zeichentabelle oder aber der Pfad bis dahin,
das ist identisch, ja,
also es reicht dir völlig auszusagen,
ich bin in der ersten Zeichenkette an Position 3,
ich bin in der zweiten Position auch an Zeichenkette 3,
was brauche ich noch?
Vielleicht was in der Zeichenkabelle an der Stelle,
so wie es in der Haare ist.
Nö, wozu das?
Warum will ich
das abspeichern
Was sagt mir die Information? Ja? Will ich
das wissen? Wofür will ich das wissen?
Was hängt in der Zukunft von dieser Information ab?
Brauche ich das in der Zukunft nochmal für irgendetwas? Ja,
weil mit dem nächsten Vergleich, wenn man sieht, okay,
beim nächsten Buchstaben, da ist der eine identische Bedingung,
da ich jetzt gebraucht bin, dann kann es sein,
dass es nur eins ist.
Oder dass man halt verstehen kann dazu. Sie versuchen,
dir nicht Determinismus zu vermeiden. Wir wollen es als Suchproblem darstellen.
Sie machen gerade einen Algorithmus, wie ich das vermeiden kann.
Alles, was ich brauche, sind auch die Kosten.
In diesem Falle
also null
Also das ist Position in Folge 1. Das ist Position in Kette 2
und das sind die Kosten, die bis dahin aufgelaufen sind.
Das reicht mir völlig aus,
um jetzt im nächsten Schritt zu sagen, okay,
es gibt oder wir machen das mal,
wir gehen mal einen Schritt zurück, sorry.
Wir gehen mal einen Schritt zurück in dem Ganzen.
Damit war tatsächlich das Problem sehen. Wir befinden uns jetzt
hier an dieser Stelle in der Suche.
Wir finden jetzt zwei Zeichen, die nicht übereinstimmen
und wir haben drei mögliche Hypothesen
Die eine ist, es ist eine Substitution,
dann gehen wir nämlich in beiden Ketten eins weiter und erhöhen die Kosten um eins.
Das sagt, es ist ein Fehler aufgetreten und wir befinden uns
jetzt hier in der Suche. Die zweite Variante ist,
wir nehmen an, dieses Haar hier ist eingefügt worden.
Dann gehen wir nur in der ersten Kette eins weiter.
In der zweiten bleiben wir aber stehen und wir sagen,
wir haben einen Fehler gemacht. Also es sind Kosten angefallen.
Und im dritten Fall gehen wir eben in der anderen eins weiter und sagen,
das Ding hier ist weggelassen worden, das heißt,
wir gehen in der zweiten eins weiter und haben
auch Kosten von eins
zu beklagen
Und damit haben wir ein Suchproblem. Jetzt können wir diese
Hypothese überprüfen, jetzt sind wir hier. Was passiert als
nächstes? Und als nächstes passiert, ich kann zu 4,
4 übergehen und die Kosten erhöhen sich nicht mehr,
weil ich nämlich wieder eine Identität habe und hier auch.
Ich kann aber genauso gut die anderen Hypothesen hier überprüfen,
was passiert, wenn es jetzt noch eine Einführung war oder noch eine Weglassung war.
Ich habe überall wieder drei Möglichkeiten und die muss ich einfach in die Tiefe expandieren.
Das Schöne an der Sache ist, dass das Ganze rekombiniert.
Ich komme dann ganz schnell wieder in den gleichen Suchzustand.
Wenn ich also eine eine Substitution habe,
wie diese hier, dann kann ich die auch darstellen.
Dadurch, hier ist ein Ding eingefügt worden und hier ist ein Ding weggelassen worden. Ja,
dann habe ich also den Umweg, ich komme von zwei,
zwei Nullwanders, einerseits über den Pfad 3, 2,
1 und andererseits über den Pfad 2, 3,
1 und dann im nächsten Schritt über drei, 3,
2 oder hier über drei,
3,
2 zu dem gleichen Zustand
Es existiert sogar noch die Möglichkeit, dass ich direkt dorthin gekommen,
ach nein, sorry, da komme ich nicht hin,
sondern es gibt einen Pfad, Multiple-Part-Pruning,
der die Bewertung 3, 3, 1 hat.
Das heißt, ich finde, einen dritten Pfad,
der günstigere Bewertung hat, als die vorhergehenden.
Also, wir müssen es jetzt lernen und deshalb mache ich das Ganze hier.
Ein gegebenes Suchproblem in durch die Brille unserer Suchterminologie zu sehen.
Wir müssen fragen, was sind die Zustände,
die die Suche absolviert? Wie beschreiben wir die Zustände,
was sind Zustandsübergänge und wie können wir dann diese Beschreibung
dem Suchverfahren überlassen,
um die korrekte Lösung zu finden
Bedeutet das, dass jetzt in diesem Fall
in diesem Baum der Verzweiflungsstruktur immer eins oder drei ist?
Nein, er ist immer drei. Ach so, ja,
ja, natürlich, genau. Wenn eine Identität vorliegt,
dann ist er eins, dann, nein, nein,
sorry, auch, dann ist das, was ich vorhin gesagt habe.
Nee, doch, er ist immer drei.
Ich muss auch in dem Falle, dass eine Identität,
nee, er ist immer drei. Ich muss auch,
wenn ich eine Identität vorliege, ich davon ausgehen kann,
es könnte auch sein, dass es meine Einfügung handelt.
Versuchen Sie es mal, sich zu überlegen,
wenn ich, wie haben wir denn ein Beispiel?
Wenn ich die Identität mit berücksichtigen kann
Genau, ich glaube, ein Verzweiflungsfaktor 4,
das macht doch einen Unterschied, ob ich Kosten akkumuliere oder nicht.
Nö, das führt in den gleichen Zustand wieder.
Aber Sie haben die Zustände doch jetzt immer als Triebel.
Alles, alles, alles, was, was passiert ist,
ob hier eins drauf addiert wird oder nicht.
Das ist dann der gleiche und Zustand, der da,
also eigentlich ist ja... Wenn wir jetzt ganz unten rechts sind,
zum Verständnis, dann wird doch jetzt die 15-3
-3-3-3-1,
2-1 und 2-3-1. Ja.
Intuitiv würde ich jetzt sagen, weiterer möglicher Zustand wäre 3
-3-0. Nee, den gibt es nicht.
Den gibt sich, weil diese beiden Dinger hier nicht zusammenpassen
Ich generiere diese zuständige dynamisch. Ich frage, sind
die beiden identisch? Wenn ja, dann nimm an,
es liegt eine Identität vor oder nimm einen,
obwohl eine Identität vorliegt, ist trotzdem was eingefügt worden.
Oder nimm an, obwohl eine Identität vorliegt, es ist trotzdem was weggelassen worden.
Die kann man vereinfachen. Man kann dann ein Modell machen,
welcher Übergänge tatsächlich sinnvoll sind und welche nicht sinnvoll sind.
Aber wenn man es ganz naiv angeht,
in der Basisausstattung, muss ich auch in dem Falle,
dass die übereinstimmen, annehmen,
möglicherweise ist doch trotzdem was eingefügt worden
Damit ich hinterher weiter rechts dann das Alignment wieder noch richtig hinbekomme.
Also stellen Sie sich irgendwo ein Wort vor,
wo der Anfang und der Endteil übereinstimmen und ich jetzt an einer Stelle bin,
obwohl ich eine lokale Identität habe, ist es besser,
erstmal eine längere Zeichenfolge einzufügen,
damit ich dann hinten wieder übereinstimme.
Ja, also eine Nachfolgetiefe, dann ändert sich immer,
der also auch jetzt Identität ist oder sonstige Funktionen.
Und die anderen beiden habe ich immer mit drin
Ja, also ich kann diesen Übergang hier nie benutzen,
wenn eine, nee, nö, ist gut,
was heißt ändert sich? Ja, also ich habe ja,
wenn ich immer drei, ich habe drei Nachrichten.
Genau. Und der eine davon, das hat hier immer,
je nachdem, ob sie übereinstimmen ist,
dass sie der Fall Identität wurde.
Erzeugter Kosten oder nicht, ja. Gut,
also dann haben wir, was sind die Zustände,
wie beschreiben wir die Zustände,
was ist der Startzustand der Suche
Null. Ja, wir brauchen aber einen Triebel, ja?
Genau, also 0-0 mit 0 Kosten.
Damit geht's los. Was ist der Zielzustand? Oder Einzelzustand
. Oder? Nein. Woher weiß ich das? Dass
es 5-0 ist. In diesem konkreten Fall,
ja, aber im allgemeinen Fall
Bitte? Genau, ja, also ich muss gucken,
wie lang sind die Wörter, die ich dort habe,
die ich miteinander vergleichen will.
Und ich muss in beiden hinten beim letzten Zeichen angekommen sein,
also N- oder M-N und die Kosten natürlich nicht null.
Das setzt ja voraus, ich kann nur exakte Wörter miteinander vergleichen.
Über die Kosten kann ich nichts sagen. Ich kann nicht
definitiv vorgeben, welche Kosten der Zielzustand verbinden sollte.
Dann setze ich gleich vornherein voraus,
dass nur eine bestimmte Anzahl von Fehlern und in ihrem Fall
werden es dann gar keine Fehler gemacht werden dürfen.
Also ich muss hier hinten
das Ding natürlich freilassen
Also mit beliebigen Kosten. Und ich bin natürlich an
den Lösungen interessiert, die mit minimalen Kosten verbunden sind.
So, Zustandsübergänge haben wir schon diskutiert. Das ist immer,
gucke dir das nächste Paar von Zeichen an und entscheide,
sind sie identisch oder sind sie nicht identisch und in Abhängigkeit davon,
mache diese drei Transitionen hier mit unterschiedlichen Kostenberechnungen und unterschiedlichen Positionsangaben.
Der Verzweigungsfaktor hatten wir schon,
der S3 und die Größe des Grafen,
ungefähr nur Grob, wie groß ist die,
wie viele Knoten hat seinen Graf
Kommen wir gleich drauf. Werden wir gleich sehen.
Wir nehmen das einfachste Kostenmodell an, was es gibt.
Das haben wir die ganze Zeit schon verwendet. Wir sagen also,
wenn eine Identität vorliegt, mit Kosten null verbunden,
wenn eine dieser drei Fälle vorher liegt, Substitutionen,
Weglassung oder Einfügung, dann sind die Kosten eins.
Wir können jederzeit anspruchsvollere Kostenfunktionen definieren, um zusätzliches Domänenwissen irgendwie zu repräsentieren.
Also Tasten, die nebeneinander auf der Tastatur sind,
sind besonders anfällig für Vertauschungen
Phonetische Ähnlichkeiten sind besonders anfällig für Vertauschungen oder nutzerspezifische Vertauschungen,
wenn. Also irgendein Nutzer systematisch bestimmte Zeichen miteinander verwechselt,
was weiß ich, D und T,
beispielsweise findet man sehr oft,
dann kann ich auch dies als mit bestimmten Kosten belegen.
Dann werde ich das mit geringen Kosten belegen,
um die Fehlerhypothese besonders gut nach oben zu bringen.
Ja, welche? Ja, wenn B,
der SA2 muss, gerade so ein Ende Länge,
dann so ein Überbetuch enden.
Also das ist immer über BOFI von Jiga
in Möbel sind
Das ist ganz schön hochgegriffen. Ich will ja alle knoten.
Ja, ja, alle Knoten. In einer Tiefe hat er
doch immer die, der Verzweiflungsgrad hier auf die Tiefe.
Wenn ich Baumsuche mache, aber wir haben hier eben ein Hochgradien-Rekombinationsfaktor.
Und tatsächlich ist er genauso groß wie der Verzweigungsfaktor hier.
Da ist kein exponentielles Wachstum mehr drin.
Das ist der Graf ist tatsächlich, ach so,
na, das ist jetzt, das kommt dann danach,
dann machen wir das erstmal.
Das ist der Graf.
Das ist eine NMM-Matrix
Das sagt immer nur, was passiert, wenn ich,
das sind die lokalen Distanzen, was passiert,
wenn ich das C hier auf ein C hier meppe,
wie kosten, wenn ich das O auf das C meppe,
das sind genau diese Paare von Positionen in den beiden Ketten.
Und ja, alles andere sind Paare, die wieder zusammengeführt werden. Gut,
was man hier, das, was ich übersprungen habe,
ist, wenn ich also zwei solche Zeichenketten habe,
ich muss jetzt hier immer nur festlegen,
das sind meine drei Optionen,
gehe ich in beiden Ketten eins weiter,
also bilde ich die nächsten beiden aufeinander ab oder gehe ich
nur in einer Kette eins weiter,
hier oben und bilde das auf das ab
Oder aber gehe ich in der anderen Kette hier unten eins weiter und bilde das auf das ab.
Das sind die Entscheidungen, die ich treffen muss.
Und das ist also ein Alignment, was ich machen kann.
Das Haar ist mit dem O verwechselt worden,
das E mit dem A und das A mit dem S.
Und ich kann natürlich etwas andere Alignments machen,
dass ich sage, ja, okay,
das A ist vermutlich auf das A hier abzubilden.
Das heißt aber, hier ist ein S eingefügt worden.
Und hier bilde ich ein Vokal wieder auf ein Vokal ab,
damit es aber ein Haar eingefügt worden.
Ein anderes Alignment hat aber die gleiche Levenstanddistanz von drei
Oder aber dieses Mapping, da gibt es also verschiedene Alignments,
das sind nicht mal alle, die ich hier dargestellt habe,
mit denen man beiden Ketten aufeinander abbilden kann.
So, und wie geht das Ganze?
Das müsste ihn, wer es schon gemacht hat,
im Algorithmen und Datenstrukturen unter dem Diaxtra-Algorithmus bekannt sein.
Hier gucken wir uns eher die Variante an, wie wir da schrittweise machen können.
Ups. Okay, wir müssen also aus den lokalen Distanzen,
die wir gegeben haben, jetzt die globalen Distanzen berechnen.
Und wir haben immer die Möglichkeit,
auf verschiedene Arten und Weisen in einen Zustand zu kommen.
Also wir haben hier Wir müssen jetzt gucken, was passiert,
wenn wir die ersten beiden Buchstaben aufeinander mappen.
Also das C, hier auf das C hier.
Das ist mit lokalen Kosten von null verbunden. Und das,
dies hier habe ich schon ausgefüllt. Wenn wir also die Hypothese haben,
dass hier am Anfang ein C eingefügt worden ist,
dann ist das mit Kosten eins verbunden.
Genau das Gleiche passiert, wenn wir die Hypothese haben,
dass hier bereits ein C eingefügt worden ist,
dann ist das auch mit Kosten eins verbunden.
Wenn wir annehmen, das C wird auf das C gemappt,
dann sind die identisch und das ist mit Kosten null verbunden.
Und auf die Art und Weise können wir jetzt tatsächlich
die Kosten Matrix füllen
Jetzt sind wir in diesem Zustand hier, wir haben als
nächstes die Möglichkeit, das Haar auf das O abzubilden.
Das ist mit Kosten 1 verbunden, weil es eine Substitution ist.
Oder wir haben die Möglichkeit, das C auf das Haar abzubilden,
dann ist es auch mit Kosten 1 verbunden,
weil es eine Einfügung in dieser Kette ist.
Oder aber wir können dann, dass dieses C auf dieses O abbilden,
dann ist es eine Einfügung in dieser Kette.
Und da sehen wir hier immer diesen Verzweigungsfaktor, der in
die Richtung führt. Die anderen habe ich nicht aufgeführt.
Es gibt nämlich auch noch diese Übergänge von hier nach hier.
Das ist eben Einfügen von C. Am Anfang Einfügen von C
in der anderen Kette
am Anfang
Wenn ich also in diesem Zustand bin, achso,
das hat man gerade diskutiert, nehmen wir an,
ich bin in diesem Zustand,
da habe ich wieder die drei Möglichkeiten,
im nächsten Schritt kann ich das C hier auf ein E abbilden.
Das ist mit zusätzlichen Kosten von eins verbunden. Das heißt,
die Gesamtkosten addieren sich zur O2. Ich kann in beiden eins
weitergehen, dann wird das O auf das E abgebildet.
Das hat auch die Kosten zwei zur Verfügung zur Folge.
Oder aber ich kann das Haar auf das,
im Moment jetzt bin ich verrutscht
Wo war ich? Hier bin ich gewesen. Also ich kann
das E auf das C abbilden. Ich kann das Haar
auf das O abbilden und die dritte Variante ist das E auf das O abzubilden.
Die Hier ist jetzt keine Verbindung eingezeichnet,
aus dem ganz einfachen Grunde, weil wenn ich von hier gekommen bin,
ich bereits Kosten eins ermittelt habe,
wenn ich von hier komme und das O auf das Haar abbilde,
würde es zu Kosten zwei führen.
Ich habe aber bereits ein besseres Ergebnis und deshalb
bleibt das bessere Ergebnis
dort stehen
Ich habe bereits ein Alignment bis zu diesem Punkt der Kette,
was mit einer Vertäuschung auskommt.
Wenn ich diesen Weg hier gewählt hätte, hätte ich
zwei Fehler annehmen müssen. Das ist ein suboptimales Ergebnis.
Und dynamische Programmierung heißt, ich habe hier ein Zwischenergebnis vorliegen.
Ich kann neue Ergebnisse immer vergleichen bezüglich ihrer Bewertung,
wenn das neue Ergebnis besser ist, dann übernimmt natürlich die neue Bewertung,
wenn das neue Ergebnis schlechter ist, dann lasst die alte Bewertung stehen.
Und das ist dieses Recyceln, was passiert. Dass ich
also in den gleichen Zustand immer auf drei verschiedene Arten kommen
kann oder aber das Gleiche auf drei verschiedene Arten verlassen kann.
Aber das Wesentliche ist, ich kann auf drei verschiedene Arten
da reinkommen und kann also von unterschiedlichen Ausgangspunkten den gleichen Zustand erreichen.
Das ist die Rekombination von Faden. Und immer dann,
wenn diese Rekombination stattfindet, kann ich entscheiden,
was ist der bis dahin optimale Pfad?
Und wenn es einen optimalen Pfad bis zu diesem Zustand gibt,
dann wird er auch Bestandteil des global optimalen Pfades sein,
wenn dieser Zustand Bestandteil des global optimalen Pfades ist.
Nur das weiß ich noch nicht. Und deshalb muss ich
die Matrix für alle diese Punkte füllen,
um dann irgendwann mal entscheiden zu können, ja,
ist dieser Zustand denn hier Teil des globalen Pfades
Und das kann in einem Backtracking-Schritt zum Schluss passieren.
Das kann man auch on the fly gleich mitführen.
Das ist beides möglich. Wenn ich hier hinten in
dem Zielzustand bin, weiß ich, die optimale Lösung,
der optimale Abbildung dazwischen, kommt mit drei Fehlern aus.
Mehr muss ich nicht annehmen. Und dann kann ich das zurückverfolgen.
Wie komme ich in diesen Zustand hier von den drei Vorgängerzuständen?
jeweils mit der optimalen Bewertung. Und dann sehen wir,
jeder rote Pfad, der sich hier durchwindet,
ist ein Alignment zwischen diesen beiden Zeichenketten.
Und das sind ziemlich viele, die man dann rauskriegt,
also was weiß ich, eins,
naja,
jetzt müssen wir nicht durchzählen
Was wir hier sehen ist, ein Optimierungsproblem, ich kriege
die optimale Lösung, die optimale Lösung ist nicht allein.
Es gibt viele optimale Lösungen mit der gleichen Bewertung,
was eben ganz einfach daran liegt,
dass sich hier so eine 0-1-Bewertung eingeführt habe.
Und auf die Art und Weise kriege ich die Zuordnungen.
Und was ich in dem Falle nur haben will, ist,
dass ich ein Ähnlichkeitsmaß habe oder besser gesagt ein Unähnlichkeitsmaß,
ein Unähnlichkeitsmaß, was sagt,
Küste und Betrügen unterscheiden sich in mindestens drei,
durch mindestens drei Austauschoperationen
Das ist das Ergebnis, was ich haben will.
Das Alignment selber will ich gar nicht haben. Ich möchte nur
die optimale Zuordnung finden und genau die liefert mir das dynamische Programmieren.
Und das Ganze eben in einem überschaubaren Suchraum,
da ist nichts exponentieller Aufwand dabei, das Ganze ist,
wenn man das jetzt linear über der Zeit machen würde,
also nehmen wir mal an,
das ist der nächste Schritt bei der Spracherkennung,
wenn das hier ein unendlicher Inputstream wäre und wir schicken das Cheat über diesen Inputstream drüber,
dann können wir das in zeitsynchronerweise machen.
Und das gucken wir uns nächsten Montag an als
nächstes Beispiel dafür