Algorithm Engineering „Symbolische Suche“

Slides:



Advertisements
Ähnliche Präsentationen
8. Termin Teil B: Wiederholung Begriffe Baum
Advertisements

Algorithmen für das Erfüllbarkeitsproblem SAT
Randomisierte Algorithmen Präfix Suche und Konsistentes Hashing
Grundlagen des A*-Algorithmus und Anwendung in der Routenplanung
(Zweistufige) Logiksynthese
Berechne den optimalen (kürzesten, schnellsten) Weg
Single-Source Shortest Paths: SSSP
Vorlesung Informatik 2 Algorithmen und Datenstrukturen (26-Graphenalgorithmen: Wiederholung und Übung) Prof. Th. Ottmann.
Bounded Model Checking II
R. Der - Vorlesung Algorithmen und Datenstrukturen (Magister)
Genetische Algorithmen für die Variogrammanpassung
Marco Barz Seminar über Algorithmen SoSe2007
Verifizieren versus Berechnen
Algorithmen und Komplexität
1 Computergestützte Verifikation SAT-basiertes Model Checking Ansatz: Übersetze das Model Checking Problem in ein aussagenlogisches Erfüllbarkeitsproblem.
1 Computergestützte Verifikation Symbolisches Model Checking 4.1 CTL Model Checking mit Binary Decision Diagrams (1. Systeme 2. Spezifikationen.
Spielbäume Richard Göbel.
Suchbäume Richard Göbel.
Sortierverfahren Richard Göbel.
Sortierverfahren Richard Göbel.
Algorithmentheorie 04 –Hashing
WS Algorithmentheorie 13 - Kürzeste (billigste) Wege Prof. Dr. Th. Ottmann.
Dynamische Programmierung (2) Matrixkettenprodukt
WS Algorithmentheorie 08 – Dynamische Programmierung (2) Matrixkettenprodukt Prof. Dr. Th. Ottmann.
Vorlesung Informatik 2 Algorithmen und Datenstrukturen (27 – Kürzeste Wege) Prof. Th. Ottmann.
Vorlesung Informatik 2 Algorithmen und Datenstrukturen (17 – Bäume: Grundlagen und natürliche Suchbäume) Prof. Th. Ottmann.
1 Vorlesung Informatik 2 Algorithmen und Datenstrukturen (21 – Kürzeste Wege) T. Lauer.
Symbolisches Model Checking mit Binary Decision Diagrams
© 2006 W. Oberschelp, G. Vossen Rechneraufbau & Rechnerstrukturen, Folie 4.1.
Universität Dortmund, Lehrstuhl Informatik 1 EINI II Einführung in die Informatik für Naturwissenschaftler und Ingenieure.
High Performance = Innovative Computer Systems + Efficient Algorithms Friedhelm Meyer auf der Heide 1 HEINZ NIXDORF INSTITUT Universität Paderborn Algorithmen.
Algorithmen und Komplexität
Modelchecker – RED Tool: Region-Encoding Diagram Stefan Neumann.
Teil I: Uninformierte Suche
Handlungsplanung und Allgemeines Spiel „Game Description Language (GDL)“ Peter Kissmann.
Handlungsplanung und Allgemeines Spiel „Ausblick: GDL-II“
Handlungsplanung und Allgemeines Spiel „Instanziierung Allgemeiner Spiele“ Peter Kissmann.
Khatuna Khvedelidze Teona Khizanishvili
Institut für Kartographie und Geoinformation Prof. Dr. Lutz Plümer Diskrete Mathematik II Vorlesung 1 SS 2001 Algorithmus von Dijkstra.
Effiziente Algorithmen
Effiziente Algorithmen
Flüsse, Schnitte, bipartite Graphen
Effiziente Algorithmen
Diskrete Mathematik II
Effiziente Algorithmen Hartmut Klauck Universität Frankfurt SS
Quantum Computing Hartmut Klauck Universität Frankfurt WS 05/
Effiziente Algorithmen
Effiziente Algorithmen
Effiziente Algorithmen
Effiziente Algorithmen Hartmut Klauck Universität Frankfurt SS
Effiziente Algorithmen Hartmut Klauck Universität Frankfurt SS
Effiziente Algorithmen Hartmut Klauck Universität Frankfurt SS
Effiziente Algorithmen
Effiziente Algorithmen Hartmut Klauck Universität Frankfurt SS
Hartmut Klauck Universität Frankfurt SS
Information und Kommunikation
Information und Kommunikation Hartmut Klauck Universität Frankfurt SS
Information und Kommunikation
Algorithm Engineering „GPU Algorithmen“
Technische Informatik II (INF 1211) Aufgabenteil (Mit Unterlagen)
Das Traveling Salesman Problem (TSP)
Algorithmen für das Erfüllbarkeitsproblem SAT
Charles Babbage Profil Entwicklungen Erfindung Ada Lovelace.
1 Computergestützte Verifikation Binary Decision Diagrams (BDD) Inhalt: Die Datenstruktur BDD Operationen auf BDD CTL Model.
Methoden der Medizintechnik
Technische Informatik II
Institut für Kartographie und Geoinformation Prof. Dr. Lutz Plümer Diskrete Mathematik II Vorlesung Datenstrukturen für den Algorithmus von.
Optimierungs- Algorithmen
Der A*-Algorithmus.
Institut für Informationssysteme Technische Universität Braunschweig Institut für Informationssysteme Technische Universität Braunschweig Verdrängung von.
 Präsentation transkript:

Algorithm Engineering „Symbolische Suche“ Peter Kissmann

Spiele Einpersonenspiele Zweipersonenspiele (n² - 1)-Puzzle Solitär Tic-Tac-Toe Clobber Vier Gewinnt

Motivation Zustandsraumexplosion #erreichbare Zustände: (n²-1)-Puzzle: (n²)!/2 15-Puzzle: ≈ 1013 24-Puzzle: ≈ 7,8 x 1024 35-Puzzle: ≈ 1,9 x 1041 Solitär: 375 110 246 Clobber (4x5): 26 787 440 4 Gewinnt: ≤ 70 728 639 995 483 (≈ 7 x 1013) (Allis, 1988) (tatsächlich: 4 531 985 219 092 (≈ 4,5 x 1012))

Motivation Speicher sparen z.B. mittels Binären Entscheidungsdiagrammen (BDDs) verwalten Zustandsmengen sparen unnötige Knoten ein → teils exponentiell viele Beispiel: vollständiges Lösen von allgemeinen Spielen (General Game Playing)

Überblick Wiederholung: BDDs BDD-basierte Suche BFS, Dijkstra, A* Anwendung auf allgemeine Spiele („General Game Playing“) BDDs als perfekte Hash-Funktion

Überblick Wiederholung: BDDs BDD-basierte Suche BFS, Dijkstra, A* Anwendung auf allgemeine Spiele („General Game Playing“) BDDs als perfekte Hash-Funktion

BDDs (Binary Decision Diagrams) Repräsentieren Zustandsmenge gerichteter azyklischer Graph von Wurzel zu 0- oder 1-Senke Knoten für (binäre) Variablen Zwei Ausgänge: low und high (auch 0 und 1) Pfad von Wurzel bis 1-Senke Zustand entsprechender Variablenbelegung in repräsentierter Menge enthalten

OBDDs (Ordered BDDs) Feste Variablenordnung π Gute Variablenordnung → exponentiell weniger Knoten (möglicherweise) Finden guter Variablenordnung NP-schwer Graphisch: Schichten gleicher Variablen

ROBDDs (Reduced OBDDs) Zwei Vereinfachungsregeln: ROBDDs eindeutig Im Folgenden nur ROBDDs x1 x1 x1 x2 x3 x2 x3

BDDs für logische Operatoren x1 x2 1 x1 x2 1 x1 1 x1 x2 1

ROBDDs (Beispiele) column-x row-x diagonal-x

Überblick Wiederholung: BDDs BDD-basierte Suche BFS, Dijkstra, A* Anwendung auf allgemeine Spiele („General Game Playing“) BDDs als perfekte Hash-Funktion

BDD-basierte Suche (Voraussetzungen) S Menge aller Zustände Initialzustand I ∈ S Menge von Zielzuständen G ⊆ S Transitionsrelation T ⊆ S x S beschreibt Zustandsübergänge durch Vorgänger und Nachfolger mögliche Ziele: finde kürzesten Pfad von I nach g ∈ G berechne alle erreichbaren Zustände 2 Variablensätze: x für Vorgängervariablen x‘ für Nachfolgervariablen in Variablenordnung xi und xi‘ abwechselnd (interleaved)

BDD-basierte Suche Finden von Nachfolgern (image) Relationales Produkt: Finden von Vorgängern (pre-image) analog: zusätzlich: nach jedem (pre-)image: Verschieben der Variablen

BDD-basierte Suche Partitionierte Berechnung: T = VaTa für alle Aktionen a ∃ und ∨ kommutieren (entsprechend auch für pre-image) Vorteil: Berechnung monolithischer Transitionsrelation teuer (Zeit und Speicher)

BDD-basierte Suche Finden der Vorgänger, deren Nachfolger alle in s liegen (strong pre-image): strong pre-image auf pre-image zurückführbar → Übungsaufgabe

BDD-basierte Suche strong pre-image image pre-image

Überblick Wiederholung: BDDs BDD-basierte Suche BFS, Dijkstra, A* Anwendung auf allgemeine Spiele („General Game Playing“) BDDs als perfekte Hash-Funktion

Breitensuche (SBFS) iterativ images berechnen reach ← I wiederhole newBDD ← image(reach) ∧ ⌐reach reach ← reach ∨ newBDD solange Abbruchkriterium nicht erfüllt mögliche Abbruchkriterien: newBDD = ⊥ (alle Zustände bestimmt) reach ∧ G ≠ ⊥ (kürzester Weg zum Ziel gefunden)

Mögliche Verbesserung Jeden Zustand nur einmal expandieren (Duplikatserkennung) Dazu: Closed-BDD front ← I wiederhole closed ← closed ∨ front front ← image(front) ∧ ⌐closed solange Abbruchkriterium nicht erfüllt

Bestimmung erreichbarer Zustände mittels SBFS v: Anzahl Variablen für einen Zustand n: Anzahl BDD-Knoten zur Repräsentation aller Zustände s: Anzahl aller erreichbarer Zustände

Bestimmung erreichbarer Zustände in „Vier Gewinnt“ (SBFS)

Bestimmung erreichbarer Zustände in „Vier Gewinnt“ (SBFS)

Bidirektionale Breitensuche (SBBFS) Schnitt gefunden I G

Bidirektionale Breitensuche (SBBFS) BFS von Start und Ziel „gleichzeitig“ Ende, wenn Suchfronten überschneiden ffront ← I, bfront ← G wiederhole falls vorwärts ffront ← image(ffront) sonst bfront ← pre-image(bfront) solange ffront ∧ bfront = ⊥ Auswahlkriterium etwa Zeit der letzten Iteration Verwendung von closed-BDDs möglich

Symbolischer Dijkstra BFS nur bei uniformen Kosten Gewichtete Transitionsrelation → „Single Source Shortest Path“→ Dijkstra Kosten c ∈ {1, …, C} T = VcTc

Symbolischer Dijkstra open0 ← I, closed ← ⊥, g ← 0 wiederhole falls (openg ∧ G ≠ ⊥) STOPP openg ← openg ∧ ⌐closed für c ← 1, …, C openg+c ← openg+c ∨ imagec(openg) closed ← closed ∨ openg g ← g + 1

Symbolisches A* (BDDA*) Ähnlich Dijkstra; Expansion nach f-Wert: Verwendung einer Heuristik z.B. aus Musterdatenbank (pattern database (PDB)) Heuristik h darf nicht überschätzen (zulässig) h = 0 → Dijkstra

Symbolisches A* (BDDA*) g

Symbolisches A* (BDDA*) open(0,h(I)) ← I, closed(0, …, |h|) ← ⊥, f ← h(I) wiederhole für g ← 0, …, f h ← f - g falls (h = 0 & open(g, h) ∧ G ≠ ⊥) STOPP open(g, h) ← open(g, h) ∧ ⌐ closed(h) für c ← 1, …, C succc ← imagec(open(g, h)) für hsucc ← 0, …, |h| open(g + c, hsucc) ← open(g + c, hsucc) ∨ (succc ∧ hsucc) closed(h) ← closed(h) ∨ open(g, h) f ← f + 1

Überblick Wiederholung: BDDs BDD-basierte Suche BDD-BFS, BDD-Dijkstra, BDDA* Anwendung auf allgemeine Spiele („General Game Playing“) BDDs als perfekte Hash-Funktion

Überblick 2 (Lösen allgemeiner Spiele) General Game Playing Einpersonenspiele Zweipersonenspiele Zweipersonen-Nullsummenspiele Zweipersonenspiele mit allgemeinen Gewinnen

Überblick 2 (Lösen allgemeiner Spiele) General Game Playing Einpersonenspiele Zweipersonenspiele Zweipersonen-Nullsummenspiele Zweipersonenspiele mit allgemeinen Gewinnen

General Game Playing Beschreibung für Spiele mit folgenden Eigenschaften: endlich diskret deterministisch vollständige Information Spiele können Ein- oder Mehr-Personenspiele sein gleichzeitige oder abwechselnde Züge ermöglichen

General Game Playing „Game Description Language“ (GDL) Gegeben: Initialzustand Bestimmung legaler Züge Effekt eines Zuges Terminierungsbedingungen Verteilung der Gewinne {0, …, 100} darin Gesucht: Lösung erreichbarer Zustände Bestimmung optimaler Gewinn-Verteilung

General Game Playing Beispiele: Mehr Informationen: Blocksworld Original GDL-Datei: .kif Tic-Tac-Toe Mehr Informationen: http://games.stanford.edu (dort entwickelt; leider veraltet) http://www.general-game-playing.de http://euklid.inf.tu-dresden.de:8180/ggpserver (aktuelle Spiele etc.)

Überblick 2 (Lösen allgemeiner Spiele) General Game Playing Einpersonenspiele Zweipersonenspiele Zweipersonen-Nullsummenspiele Zweipersonenspiele mit allgemeinen Gewinnen

Lösen von Einpersonenspielen Erst: Erreichbare Zustände finden (BFS) Dann: Rückwärtssuche Start: Zielzustände mit Gewinn 100 BFS (rückwärts) Weiter: Zielzustände mit Gewinn 99 dabei: bereits gelöste Zustände auslassen Weiter bis Gewinn 0

Lösen von Einpersonenspielen 75 100 90 80 99 100 100 100 90 80 100 90 80 75

Ergebnisse für Solitär Erreichbar: 375 110 246 Zustände

Überblick 2 (Lösen allgemeiner Spiele) General Game Playing Einpersonenspiele Zweipersonenspiele Zweipersonen-Nullsummenspiele Zweipersonenspiele mit allgemeinen Gewinnen

Lösen von Zweipersonen-Nullsummenspielen Mögliche Gewinne: 0, 50, 100 Jeder Spieler versucht, möglichst hohen Gewinn zu erreichen Lösung liefert Verteilung der Gewinne (bei optimaler Spielweise)

Lösen von Zweipersonen-Nullsummenspielen BFS für Finden erreichbarer Zustände Zwei Rückwärtssuchen (eine pro Spieler): Start bei verlorenen Zielzuständen Bestimmung verlorener Vorgänger (2 Schritte) für alle Züge, die Spieler durchführen kann, kann Gegenspieler Zug zu verlorenem Zustand wählen (pre-image und strong pre-image) Iterieren, solange neue Zustände gefunden player 0‘s turn player 1‘s turn lost for player 0 lost for player 1

Lösen von Zweipersonen-Nullsummenspielen reach ← berechneErreichbareZustände() für jeden Spieler p ∈ {0, 1} front ← verlorenp ← reach ∧ gewinn(p, 0) ∧ G ∧ zugp gewonnen1-p ← reach ∧ gewinn(p, 0) ∧ G ∧ zug1-p wiederhole pred ← pre-image(front) ∧ reach gewonnen1-p ← gewonnen1-p ∨ pred front ← strong-pre-image(gewonnen1-p) ∧ reach ∧ ⌐verlorenp verlorenp ← verlorenp ∨ front solange front ≠ ⊥

Überblick 2 (Lösen allgemeiner Spiele) General Game Playing Einpersonenspiele Zweipersonenspiele Zweipersonen-Nullsummenspiele Zweipersonenspiele mit allgemeinen Gewinnen

Lösen allgemeiner Zweipersonenspiele Mögliche Gewinne ∈ {0, …, 100} Verwendung von (101 x 101)-Matrix Zustand an Position (i, j): i Punkte für Spieler 0 j Punkte für Spieler 1 falls unvollständig, Verwendung als Endspieldatenbank

Lösen allgemeiner Zweipersonenspiele Eine Vorwärts- und eine Rückwärtssuche finde alle Vorgänger, deren Nachfolger alle gelöst sind (strong pre-image) finde optimales Bucket für diese (pre-image) füge sie ein iteriere, bis alle Zustände gelöst

Einschub: Reihenfolge beim Lösen own 100 opponent … schwierig im allgemeinen Fall eigenen Gewinn maximieren (und gegnerischen minimieren)? oder Differenz zum gegnerischen Gewinn maximieren? Hier: 2. Fall own 100 opponent …

Beispiel player 0‘s turn player 1‘s turn player 0 player 1 1 2 3 0/1 1 2 3 0/1 0/1 0/3 0/1 0/1 3/1 0/3 0/1 2/0 0/1 3/1 0/1 0/3 2/0 0/1 2/0 3/1 0/1 3/1 player 0‘s turn player 1‘s turn 0/1 3/1 2/0 3/1

Lösen allgemeiner Zweipersonenspiele reach ← berechneErreichbareZustände() init matrix; solved ← alle Zustände in Matrix unsolved ← reach ∧ ⌐solved solange unsolved ≠ ⊥ für jeden Spieler p ∈ {0, 1} solvable ← strong-pre-image(solved) ∧ unsolved ∧ zugp falls solvable ≠ ⊥ matrix ← fügeZuständeEin(solvable, p, matrix) solved ← solved ∨ solvable unsolved ← unsolved ∧ ⌐solvable

Ergebnisse Game t0-sum tnew Clobber 3x4 - 1.1s Clobber 3x4 0-sum 1.0s 2:14:20 Clobber 4x5 0-sum 0:54:35 1:22:09 Minichess 0.7s TicTacToe 0.1s 0.2s Nim 40 0.0s

Überblick Wiederholung: BDDs BDD-basierte Suche BDD-BFS, BDD-Dijkstra, BDDA* Anwendung auf allgemeine Spiele („General Game Playing“) BDDs als perfekte Hash-Funktion

Hashing Gegeben: Menge von Zuständen S Gesucht: Abbildung S → R ⊆ ℕ Hashfunktion ordnet jedem Zustand einen Wert zu perfektes Hashing: Hashwert jedes Zustandes eindeutig minimales perfektes Hashing: |R| = |S|

Sat-Count Anzahl gespeicherter Zustände in BDD G mögliche Berechnung: sat-count(0-Senke) ← 0, sat-count(1-Senke) ← 1 für Knoten v aus Schicht i mit 0-Nachfolger u in Schicht j > i und 1-Nachfolger w in Schicht k > i sat-count(v) ← 2j-i-1 * sat-count(u) + 2k-i-1 * sat-count(w) falls Wurzel in Schicht i: sat-count(G) ← 2i-1 * sat-count(Wurzel) Laufzeit- und Speicherbedarf: ≤ O(|G|)

Sat-Count (Beispiel) 1 30 14 16 4 2 2 5 3 1 1 2 1 abgedeckte Zustände: 1 30 abgedeckte Zustände: 000001 000111 001011 001101 010011 010100 010101 010110 010111 011011 011100 011101 011110 011111 100011 100100 100101 100110 100111 101011 101100 101101 101110 101111 110010 110011 110111 111010 111011 111111 14 16 4 2 2 5 3 1 1 2 1

Ranking Gegeben: BDD G, Zustand s Gesucht: Hash-Wert von s (in {0, …, sat-count(G) - 1}) Vorverarbeitung: Berechne Sat-Count aller Knoten speichere diese Sat-Counts

Ranking rank(G,s) falls Wurzel in Schicht i d ← Binärwert von (s1, …, si-1) gib (d+1) * lexicographic-count(G,s,Wurzel) - 1 zurück

Ranking lexicographic-count(G,s,v) falls v 0-Senke, gib 0 zurück; falls v 1-Senke, gib 1 zurück falls v in Schicht i mit 0-Nachf. u in j und 1-Nachf. w in k falls si = 0 r0 ← lexicographic-count(G,s,u) d0 ← Binärwert von (si+1, …, sj-1) gib d0 * sat-count(u) + r0 zurück falls si = 1 r1 ← lexicographic-count(G,s,w) d1 ← Binärwert von (si+1, …, sk-1) gib 2j-i-1 * sat-count(u) + d1 * sat-count(w) + r1 zurück

Ranking (Beispiel) 1 30 16 14 4 3 5 2 v0 v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 s ← 011101 rank(G,s) ← [()2 + 1] * lc(G,s,v0) - 1 lc(G,s,v0) ← ()2 * sc(v1) + lc(G,s,v1) lc(G,s,v1) ← 23-2-1 * sc(v3) + (1)2 * sc(v6) + lc(G,s,v6) lc(G,s,v6) ← 25-4-1 * sc(v9) + (01)2 * sc(v13) + lc(G,s,v13) v13 ist 1-Senke → lc(G,s,v13) ← 1 lc(G,s,v6) ← 20 * sc(v9) + 1 * sc(v13) + lc(G,s,v13) = 1 * 1 + 1 * 1 + 1 = 3 lc(G,s,v1) ← 20 * sc(v3) + 1 * sc(v6) + lc(G,s,v6) = 1 * 4 + 1 * 5 + 3 = 12 lc(G,s,v0) ← 0 * sc(v1) + lc(G,s,v1) = 12 rank(G,s) ← 1 * lc(G,s,v0) - 1 = 11

Unranking Gegeben: BDD G, Hash-Wert r Gesucht: zugehöriger Zustand

Unranking unrank(G,r) starte an der Wurzel falls Wurzel in Schicht l (s1, …, sl-1) ← Binärrepräsentation von r div sat-count(Wurzel) r ← r mod sat-count(Wurzel) v ← Wurzel; i ← l wiederhole, bis v 0- oder 1-Senke falls v Knoten in Schicht i mit 0-Nachf. u in j 1-Nachf. w in k falls r < 2j-i-1 * sat-count(u) si ← 0; (si+1, …, sj-1) ← Binärrepräsentation von r div sat-count(u) r ← r mod sat-count(u) v ← u; i ← j falls r ≥ 2j-i-1 * sat-count(u) si ← 1; r ← r - 2j-i-1 * sat-count(u) (si+1, …, sk-1) ← Binärrepräsentation von r div sat-count(w) r ← r mod sat-count(w) v ← w; i ← k

Unranking (Beispiel) 1 30 16 14 4 3 5 2 s ← 1010 s ← 10101 s ← 101011 1 30 16 14 4 3 5 2 v0 v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 r ← 19 i ← 1; r ≥ 22-1-1 * sc(v1) = 1 * 14 = 14 s1 ← 1; r ← r - 22-1-1 * sc(v1) = 19 - 1 * 14 = 5 r ← r mod sc(v2) = 5 mod 16 = 5 i ← 2; r < 24-2-1 * sc(v6) = 2 * 5 = 10 s2 ← 0; (s3) ← (r div sc(v6))2 = (5 div 5)2 = 12 = 1 r ← r mod sc(v6) = 5 mod 5 = 0 i ← 4; r < 25-4-1 * sc(v9) = 1 * 1 = 1 s4 ← 0; r ← r mod sc(v9) = 0 mod 1 = 0 i ← 5; r ≥ 26-5-1 * sc(v12) = 2 * 0 = 0 s5 ← 1; r ← r - 27-5-1 * sc(v12) = 0 - 2 * 0 = 0 r ← r mod sc(v11) = 0 mod 1 = 0 i ← 6; r ≥ 27-6-1 * sc(v12) = 1 * 0 = 0 s6 ← 1; r ← r - 27-6-1 * sc(v12) = 0 - 1 * 0 = 0 r ← r mod sc(v13) = 0 mod 1 = 0

Ranking und Unranking (Analyse) Vorverarbeitung: O(|G|) Ranking pro Zustand: O(n) Unranking pro Zustand: O(n) Vorverarbeitung beschriftet jeden Knoten mit n-bit Zahl → O(n|G|) extra Bits nötig

Zusammenfassung Symbolische Suche zur Verringerung der Speicherlast speichern von Zustandsmengen (als BDDs) statt einzelner Zustände Vorgänger- und Nachfolgerberechnungen (image und pre-image) liefern direkt SBFS und SBBFS Symbolische Formen von Dijkstra und A* Lösen von Spielen mittels symbolischer Suche BDDs als perfekte Hash-Funktion