2.9 Datenstrukturen für boolesche Funktionen Darstellung von f : {0, 1}n → {0, 1}m , anders ausgedrückt: Darstellung von f1 , . . . , fm : {0, 1}n → {0, 1}. f : {0, 1}n → {0, 1} ←→ f −1 (1) Also doch nur Mengen? Ja, aber: Die Mengen sind typischerweise riesig groß. Kombinatorische Überlegung: Es gibt 2n Elemente in {0, 1}n , n 2 also 2 verschiedene Mengen f −1 (1). → Jede Datenstruktur braucht für die meisten Funktionen Ω(2n ) Bits. . – Seite 196/726 Schaltkreise: • Elementare boolesche Operationen z. B. NOT = AND = ∧ OR = + EXOR = ⊕ Außerdem Eingänge x1 , . . . , xn , Konstanten 0, 1. • Schaltkreis beschrieben durch Bausteinliste B1 , . . . , Bm (Gatterliste, gate list). Baustein Bi berechnet elementare Operation auf Vorgängern aus B1 , . . . , Bi−1 , x1 , . . . , xn , 0, 1. Beispiel: Volladdierer in unserer Notation (Addition von zwei Bits mit Übertrag): x0 B3 ∧ y0 c0 ⊕ B1 ∧ + B5 = c1 B4 ⊕ B2 = s0 Ziel: Darstellung vieler und vor allem vieler wichtiger Funktionen in polynomieller Größe und Unterstützung vieler nützlicher Operationen. Welche Operationen? Bezeichne Datenstruktur für f mit Gf , da wir Graphen betrachten werden: 1.) Auswertung (evaluation): Gegeben: Gf und a. Gesucht: f (a). Motivation: offensichtlich. 2.) Gleichheitstest (equality test): Gegeben: Gf und Gg . Frage: Gilt für alle a: f (a) = g(a)? Motivation: Hardwareverifikation. . – Seite 197/726 Neue Realisierung R, die f darstellen soll, sei g die dargestellte Funktion Spezifikation oder bekanntermaßen korrekte Darstellung S von f ? ∀a : S(a) = R(a) auf Schaltkreisebene zu schwierig. Datenstruktur Gf Umformung muss (oft) effizient sein, darf nie die Funktion verändern. Datenstruktur Gg Gleichheitstest . – Seite 198/726 Also brauchen wir Operationen, die eine durch einen Schaltkreis dargestellte Funktion in eine Darstellung innerhalb der Datenstruktur überführen. Verfahren: Gate-by-Gate-Transformation • Datenstruktur für Literale (xi oder xi ) sollte klein und direkt herstellbar sein. • Durchlaufe Bausteinliste z.B. N N h=f g mit ∈ {AND, OR, EXOR, . . . } f g ⊗h Erzeuge Datenstruktur für h aus Datenstrukturen für f und g . . – Seite 199/726 3.) Synthese (binary synthesis): N N Gegeben: Gf , Gg und . Gesucht: Gh für h = f g. Achtung: Selbst kleine Größenzuwächse können sich aufschaukeln! 4.) Erfüllbarkeitstest (satisfiability test): Gegeben: Gf . Frage: ∃ a : f (a) = 1? Dies ist oft ein Basisproblem (→ Vorlesung GTI). Gleichheitstest „=“ Synthese + Erfüllbarkeit: f = g ⇔ f ⊕ g nicht erfüllbar EXOR . – Seite 200/726 5.) Ersetzung durch Funktionen (replacement by functions): Gegeben: Gf , Gg , xi . Gesucht: Gh für h := f|xi =g , genauer: h(x1 , . . . , xn ) := f x1 , . . . , xi−1 , g(x1 , . . . , xn ), xi+1 , . . . , xn . Motivation: Modularer Hardwareaufbau. x1 · · · xn x1 · · · xn g x1 · · · xi−1 xi xi+1 · · · xn f x1 · · · xi−1 xi+1 · · · xn h . – Seite 201/726 Ersetzung durch Konstanten ist der Spezialfall g ≡ c. Oft einfacher durchführbar. Shannon-Zerlegung: f = (xi ∧ f|xi =1 ) + (xi ∧ f|xi =0 ). Damit folgt: f|xi =g = (g ∧ f|xi =1 ) + (g ∧ f|xi =0 ) = if g then f|xi =1 else f|xi =0 = ITE(g, f|xi =1 , f|xi =0 ). Also: Ersetzung durch Funktionen = Ersetzung durch Konstanten + 3 binäre Synthesen = Ersetzung durch Konstanten + ternäre ITE-Synthese. (Viele OBDD-Pakete unterstützen ITE-Synthese direkt.) . – Seite 202/726 6.) Abstraktion oder Quantifizierung (abstraction / quantification): Gegeben: Gf , xi , ∀ oder ∃. Gesucht: Gg für g := (∃xi )f oder Gh für h := (∀xi )f , wobei (∃xi )f := f|xi =0 + f|xi =1 und (∀xi )f := f|xi =0 ∧ f|xi =1 . Motivation: Erfüllbarkeit ⇔ (∃x1 ) . . . (∃xn )f = 1. Lebendigkeits- und Fairnessbedingungen sind Existenzaussagen. Verbotene Konstellationen lassen sich durch Allaussagen beschreiben. . – Seite 203/726 7.) Minimierung (minimization): Gegeben: Gf . Gesucht: Darstellung von f von minimaler Größe innerhalb der betrachteten Datenstruktur. (Wenn Ergebnis eindeutig, auch Reduktion (reduction) genannt.) Motivation: Synthese wird einfacher, wenn irgendeine Darstellung von h das Ziel ist, aber dann entstehen oft sehr große Darstellungen. Gate-by-Gate-Transformation nur bei integrierter Minimierung sinnvoll. . – Seite 204/726 Warum nicht gleich Schaltkreise als Datenstrukturen? Gegeben Schaltkreise Sf und Sg mit |Sf | und |Sg | Bausteinen. Auswertung: O(|Sf |). Synthese: O(|Sf | + |Sg |), aber Ergebnis mit |Sf | + |Sg | + 1 Bausteinen. Ersetzen durch Fktn.: O(|Sf | + |Sg |). Quantifizierung: O(|Sf |). Aber: Gleichheitstest, Erfüllbarkeitstest und Minimierung sind algorithmisch schwierige Probleme (→ Vorlesung GTI). In Theorie und Anwendungen Tagungen über SAT. . – Seite 205/726 OBDDs (ordered binary decision diagrams): OBDD: Gerichteter, azyklischer Graph, der nach folgenden Regeln aufgebaut ist: • Senken: Erlaubte Knoten mit Ausgrad 0 sehen so aus: 0 und 1 • Innere Knoten: Haben genau zwei Nachfolger, Knoten mit Variable markiert, Kanten mit Konstanten 0 bzw. 1. xi w xi w 0 1 w0 w1 w0 w1 Alternativ: 0-Kante gestrichelt, 1-Kante durchgezogen. • Variablenordnung: Liste aller Variablen in irgendeiner Reihenfolge: π = (xi1 , . . . , xin ) (Permutation). Variablen auf jedem Weg im Graph von Quellen zu Senken gemäß dieser Reihenfolge. Name für OBDDs mit Variablenordnung π : π - OBDDs. Variablenordnung ist frei wählbar, hier stets π = (x1 , . . . , xn ), wenn nichts anderes gesagt wird. Der Synthesealgorithmus arbeitet nur, wenn beide OBDDs dieselbe Variablenordnung benutzen. Beispiel Multiplexer (Vorlesung Rechnerstrukturen): gute Variablenordnung: Größe Θ(n), schlechte Variablenordnung: Größe Θ(2n ). . – Seite 206/726 Syntax von π - OBDDs 0 - Kante x1 - Ebene x1 x2 - Ebene x1 x2 xi - Ebene x2 xi xi+1 - Ebene xi+1 xi+1 xi+1 .. . .. . xj - Ebene Alle Kanten sind abwärts gerichtet .. . .. . 1 - Kante xj xj .. . xn - Ebene Senken xn xn 0 1 . – Seite 207/726 Semantik von π - OBDDs Jeder Knoten repräsentiert eine Funktion fv . Option 1: Auswertungsalgorithmus für fv (a). Starte an v , an xi -Knoten wähle ai -Kante, gib Wert der erreichten Senke aus. O(n) unabhängig von der OBDD - Größe. Bezeichnung für so durchlaufenen Weg: Berechnungsweg für Eingabe a. Option 2: Globale Sicht auf alle Berechnungswege. Eingabe a aktiviert alle ai -Kanten aus xi -Knoten. Dann ist fv (a) der Wert der Senke, die auf dem eindeutigen an v startenden aktivierten Weg erreicht wird. . – Seite 208/726 Option 3: Bottom-up-Definition. • Senken: 0 und 1 stellen konstante Funktionen 0 bzw. 1 dar. • Innere Knoten: xi w w0 w1 Seien alle Funktionen fv für v unterhalb der xi -Ebene definiert. Dann ist fw (x) := ITE(xi , fw1 (x), fw0 (x)), wobei w0 der 0-Nachfolger und w1 der 1-Nachfolger von w ist. . – Seite 209/726 Beispiele: x1 ∧ x2 ∧ x3 x1 x1 + x2 + x3 x1 x2 0 x2 x3 0 0 x3 1 0 1 1 x1 ⊕ x2 ⊕ x3 x1 x2 x2 x3 x3 0 1 1 Ein komplexeres Beispiel – Addition von zwei 4-Bit-Zahlen: (x3 , x2 , x1 , x0 )2 + (y3 , y2 , y1 , y0 )2 = (s4 , s3 , s2 , s1 , s0 )2 . s4 s3 x3 x3 s2 y3 y3 y3 x2 y2 y3 x2 y2 y2 x1 x2 y2 y2 y2 s1 x1 x1 s0 y1 y1 x0 y1 y1 x0 x0 y0 0 y1 y1 y0 1 . – Seite 210/726 Erfüllbarkeitstest für fv Starte eine Tiefensuche von v aus, überprüfe, ob die O(|Gf |) 1-Senke erreichbar ist. Beobachtung: Jeder Weg von v zu einer Senke ist für passende Belegung a Berechnungsweg. • Wähle ai je nach „Abzweig“ aus xi -Knoten. • Keine widersprüchlichen Wahlen, da xi höchstens einmal auf dem Weg – wegen Variablenreihenfolge! • Fülle noch fehlende ai -Bits irgendwie beliebig auf. fv (a) = 1: Berechnungsweg zu 1-Senke existiert, damit insbesondere Weg, den Tiefensuche findet. fv (a) = 0 für alle a: Alle Berechnungswege von v aus führen zu 0-Senken. Kein Weg v 1-Senke möglich, da (Beobachtung) dieser Berechnungsweg wäre. . – Seite 211/726 Synthese von Gf und Gg zu Gh durch „Synthese“ der Berechnungswege in Gf und Gg , hier a = (1, 0, 1, 1, 0). Gf Gg v 1 x1 w 1 x1 Gh für h := f ⊗ g (v1 , w1 ) x1 x1 in Gf und Gg bearbeitet v 2 x2 w 2 x2 (v2 , w2 ) x2 x2 bearbeitet, aber in Gf Knoten mit „späterer Variablen“ w 3 x3 (v3 , w3 ) x3 x3 in Gg bearbeitet, in Gf „gewartet“ v 3 x4 w 4 x5 (v3 , w4 ) x4 (v4 , w4 ) x5 x4 in Gf bearbeitet, in Gg „gewartet“ x5 in Gg bearbeitet, in Gf „gewartet“ v4 1 w5 0 (v4 , w5 ) 1 ⊗ 0 Senken in Gf und Gg erreicht, Ergebnis durch ⊗ verknüpft . – Seite 212/726 Synthese durch Kreuzprodukt Gf = (Vf , Ef ), Gg = (Vg , Eg ), ⊗. Gh = (Vh , Eh ) mit Vh = Vf × Vg . (Größen multiplizieren sich!) Am Knoten (v, w) ∈ Vh soll fv ⊗ gw dargestellt werden. 1. Fall: v und w sind xi -Knoten v xi v0 (v, w) xi w xi v1 w0 w1 (v0 , w0 ) (v1 , w1 ) Korrektheit: Falls (v0 , w0 ) fv0 ⊗ gw0 und (v1 , w1 ) fv1 ⊗ gw1 darstellt, dann auch f(v,w) = fv ⊗ gw . . – Seite 213/726 Falls (v0 , w0 ) fv0 ⊗ gw0 und (v1 , w1 ) fv1 ⊗ gw1 darstellt, dann gilt: f(v,w) = [xi ∧ (fv1 ⊗ gw1 )] + [xi ∧ (fv0 ⊗ gw0 )] = [(xi ∧ fv1 ) ⊗ (xi ∧ gw1 )] + [(xi ∧ fv0 ) ⊗ (xi ∧ gw0 )] = (xi ∧ fv1 + xi ∧ fv0 ) ⊗ (xi ∧ gw1 + xi ∧ gw0 ) = f v ⊗ gw . Gleichungen 1 und 4 sind Definitionen. Gleichungen 2 und 3 lassen sich durch Fallunterscheidung (xi = 1 und xi = 0) überprüfen. . – Seite 214/726 2. Fall: v ist xi -Knoten und w ist xj -Knoten mit j > i oder Senke Gf : Gg : v xi (v, w) xi w xj Warten in Gg oder v0 v1 w0 w1 w c (v0 , w) (v1 , w) Falls (v0 , w) fv0 ⊗ gw und (v1 , w) fv1 ⊗ gw darstellt, dann gilt f(v,w) = [xi ∧ (fv1 ⊗ gw )] + [xi ∧ (fv0 ⊗ gw )] = [(xi ∧ fv1 ) ⊗ (xi ∧ gw )] + [(xi ∧ fv0 ) ⊗ (xi ∧ gw )] = (xi ∧ fv1 + xi ∧ fv0 ) ⊗ (xi ∧ gw + xi ∧ gw ) = f v ⊗ gw . . – Seite 215/726 3. Fall: v ist xj -Knoten mit j > i oder Senke und w ist xi -Knoten Spiegelbildlich analog zum Fall 2. 4. Fall: v ist c-Senke und w ist c′ -Senke v c (v, w) c ⊗ c′ w c′ Offensichtlich ist f(v,w) = f v ⊗ gw . Also gilt Korrektheit auf Senkenebene und damit nach Induktion über die Ebenen von unten nach oben überall. O(|Gf | · |Gg |) Problem: Größenzuwachs! Größe ist Knotenzahl, da |Ef | < 2 · |Vf |. . – Seite 216/726 Synthese unter Vermeidung unerreichbarer Knoten: Es soll ja „nur“ h am Knoten (v, w) dargestellt werden. Wenn kein Berechnungsweg, der in (v, w) startet, (v ′ , w′ ) erreicht, kann (v ′ , w′ ) gestrichen werden. Besser: (v ′ , w′ ) gar nicht erzeugen. Idee: Konstruiere Gh startend mit (v, w) (v stellt f und w stellt g dar) mit DFS-Ansatz . – Seite 217/726 Beispiel 1: ⊕ 1 1 x1 x1 2 3 2 3 x2 x2 x2 x2 4 0 1 4 5 x3 0 1 5 6 Beispiel 2: ∧ 1 1 x1 x2 2 x2 2 0 1 3 4 x3 0 1 3 4 Synthese unter Vermeidung unerreichbarer Knoten (Forts.): Problem: Was passiert eigentlich, wenn Knoten bei DFS mehrfach erreicht werden? (v, w) (v ′ , w ′ ) Sollten (wie immer) erkennen, wenn (v ′ , w′ ) wiederholt besucht wird. Dann nicht noch einmal Graph für fv′ ⊗w′ konstruieren! Wollen: DFS-Aufruf (v ′ , w′ ) soll Zeiger auf bereits berechnetes Teil-OBDD für (v ′ , w′ ) liefern, falls vorhanden. Wir brauchen eine dynamische Datenstruktur, die Suchen und Einfügen von Paaren ((v ′ , w′ ), Zeiger auf OBDD-Knoten) unterstützt. Name: Computed-Table. Wie so etwas allgemein geht → Kap.3, erhalten: – Bei Anzahl Einträgen s gibt es Datenstruktur mit Worstcase-Zeit O(log s) für jede Operation. – Es gibt Techniken, die bei typischen Daten Zeit O(1) pro Operation brauchen. Hier s ≤ |Gf ||Gg |. Wir rechnen mit O(1) – sonst Extrafaktor O(log |Gf | + log |Gg |). Soll (v ′ , w′ ) als neuer Knoten generiert werden, dann – Suche in Datenstruktur. – Falls gefunden, Zeiger auf vorhandenen Knoten. – Falls nicht gefunden, neuer Knoten, Zeiger auf neuen Knoten, neuen Knoten in Datenstruktur einfügen. . – Seite 218/726 Lässt sich das Ergebnis-π -OBDD verkleinern? Uns fallen zwei Verkleinerungsregeln ein: xi 0 v v 1 w xi xi 1 0 0 w Eliminationsregel (elimination rule) u xi w 1 u′ w 0 u 1 u′ Verschmelzungsregel (merging rule) . – Seite 219/726 Eliminationsregel: Der xi -Test kann offensichtlich übersprungen werden. Formal fv = xi ∧ fw + xi ∧ fw = fw . Verschmelzungsregel: Wenn fv = fw , können die Zeiger auf v „umgebogen“ werden, um auf w zu zeigen. Es ist fv = xi ∧ fu′ + xi ∧ fu = fw . . – Seite 220/726 Synthese unter Vermeidung nicht erreichbarer Knoten und Integration von Eliminationsregel und Verschmelzungsregel. DFS-basierte Konstruktion vom Startknoten aus. Verwendung von Computed-Table, um Knoten nicht mehrfach zu erzeugen. Wie sehen Zwischenergebnisse aus? Es gibt DFS hat den Backtrack auf die – bestätigte Knoten: v erste Kante zu v vollzogen. – noch nicht angelegte Knoten und – Knoten in Bearbeitung. . – Seite 221/726 – Fertige Knoten bleiben erhalten. – Wegen DFS-Konstruktion gibt es pro Ebene maximal einen Knoten in Bearbeitung. (→ nie mehr als n Kanten mehr erzeugt als im Ergebnis.) – Backtrack erreicht v über die zweite ausgehende Kante. – Integration der Eliminationsregel: Zeigen beide ausgehenden Kanten auf denselben Knoten? Falls ja, Eliminationsregel anwenden. . – Seite 222/726 Integration der Verschmelzungsregel: Weitere Datenstruktur, die Suchen und Einfügen unterstützt. Dort werden Knoten durch (Variable, 0-Nachfolger, 1-Nachfolger) oder (Senke, Wert) abgespeichert. Name: Unique-Table. Vorgehensweise beim Synthese-DFS-Aufruf für (v, w): Rekursiv sei neuer Knoten r erzeugt worden. • Vor dem Backtrack über die Kante zu (v, w) wird überprüft, ob ein zu r äquivalenter Knoten (gleiches Tupel) in der Unique-Table ist. • Gleiches Tupel vorhanden, zugehöriger Knoten r′ : Wirf Knoten r weg. Trage r′ in Computed-Table für (v, w) ein. Gib r′ als Ergebnis des DFS-Aufrufes zurück. • Kein gleiches Tupel vorhanden: Dann bleibt r erhalten. Trage r in Computed-Table für (v, w) ein und gib r als Ergebnis des DFS-Aufrufes zurück. . – Seite 223/726 synthesisDFS(v,w) { if (v.val != UNDEF && w.val != UNDEF) // v,w sind Senken return(Senke mit Wert v.val * w.val); r = ComputedTable.search(v,w); if (r != 0) return(r); // schon mal fuer (v,w) berechnet else { index = min(v.index, w.index); // Fuer Variablenordn. x_1,...,x_n! r0 = synthesisDFS(v0,w0); // Dabei (v0,w0), (v1,w1) wie in r1 = synthesisDFS(v1,w1); // Fallunterscheidung gewählt. if (r0 == r1) // Eliminationsregel schlägt zu r = r0; else { r’ = UniqueTable.search(index,r0,r1); if (r’ != 0) { entsorge r0,r1; r = r’; } else { r = new OBDDNode(index,r0,r1); UniqueTable.insert(index,r0,r1, r); } } ComputedTable.insert(v,w, r); return(r); } } Wie groß werden die Tabellen? Unique-Table: ein Eintrag pro Knoten im Ergebnis. Computed-Table: ein Eintrag pro erreichbarem Knoten im Kreuzprodukt. Das kann viel zu viel sein! Pragmatische Lösung: Verkürze ggf. computed-table (→ Kap. 3). Was passiert mit dem Ergebnis? Schon vorhandene Knoten, die nicht gespeichert sind, werden wiederholt erzeugt, aber am Ende verschmolzen. Time-Space-Trade-Off. . – Seite 225/726 Wie gut ist unser Ergebnis? Satz: Ein π -OBDD ohne nicht erreichbare Knoten, auf das weder Eliminationsregel noch Verschmelzungregel anwendbar sind, hat minimale Größe. Alle minimalen π -OBDDs für f sind bis auf Benennung der Knoten identisch. (In DAP2 ohne Beweis.) . – Seite 226/726 Ersetzung durch Konstanten u xi xi = 0 v w v Dadurch können Knoten unerreichbar und Verkleinerungsregeln anwendbar werden → in DFS-Ansatz zum Finden der xi -Knoten integrierbar. Gleichheitstest, Ersetzung durch Funktionen und Quantifizierung auf die hier behandelten Operationen zurückführbar. . – Seite 227/726 Schaltkreise O(|Sf |) expo. O(1) expo. Auswertung Gleichheitstest Synthese Erfüllbarkeitstest Ersetzung durch Konstanten O(|Sf |) Ersetzung durch Funktionen O(|Sf | + |Sg |) Quantifizierung O(|Sf | + |Sg |) Minimierung expo. π -OBDDs O(n) O(|Gf | · |Gg |) O(|Gf | · |Gg |) O(|Gf |) O(|Gf |) O(|Gf |2 · |Gg |) O(|Gf | · |Gg |) O(Gf ) in Synthese integrierbar . – Seite 228/726