Boolesche Funktionen – Algorithmen und Komplexität Vorlesungsnotizen Autor: Martin Dietzfelbinger Nach handschriftlichen Aufzeichnungen des Autors geschrieben von: Benjamin Hiller 17. November 2009 Inhaltsverzeichnis 1 Grundbegriffe und Komplexitätsmaße 1.1 Boolesche Funktionen als Boolesche Algebra . . . . . . . . . . 1.2 Boolesche Formeln . . . . . . . . . . . . . . . . . . . . . . . . 1.3 Schaltkreise und Straight-Line-Programme . . . . . . . . . . . 1.4 Größenmaße für Schaltkreise . . . . . . . . . . . . . . . . . . . 1.5 Komplexitätsklassen für Schaltkreise (Boolesche Funktionen) 1.5.1 Uniforme (algorithmisch erzeugte) Schaltkreise . . . . 1.5.2 Nichtuniforme Turingmaschinen (Advice-TM) . . . . . 3 3 5 7 12 13 15 15 2 Minimierung zweistufiger Schaltkreise 2.1 Formeln und Normalformen . . . . . . . . . . . . . . . . . 2.2 Entscheidungsfragen . . . . . . . . . . . . . . . . . . . . . 2.3 Minimierung und Primimplikanten . . . . . . . . . . . . . 2.4 Algorithmus von Quine/McCluskey . . . . . . . . . . . . . 2.5 Weitere Methoden zur Berechnung der Primimplikanten . 2.5.1 Rekursive Methode („Baummethode“) . . . . . . . 2.5.2 Iterierter Konsensus . . . . . . . . . . . . . . . . . 2.5.3 Doppeltes Produkt . . . . . . . . . . . . . . . . . . 2.6 Berechnung eines Minimalpolynoms . . . . . . . . . . . . . 2.6.1 Minimalpolynom bei Eingabe der Funktionstabelle 2.6.2 Minimalpolynom bei Eingabe eines Polynoms . . . . . . . . . . . . . . 21 21 25 26 30 33 33 37 41 42 42 48 . . . . . . . . . . 50 50 51 55 56 56 59 64 65 68 70 3 Schaltkreiskonstruktionen 3.1 Additionsschaltkreise . . . . . . . . . . . . . . . . . . . 3.1.1 Parallele Präfixberechnung (Postfixberechnung) 3.1.2 Fischer-Ladner-Addierer . . . . . . . . . . . . . 3.2 Multiplikationsschaltkreise . . . . . . . . . . . . . . . . 3.2.1 Wallace-Tree-Multiplizierer . . . . . . . . . . . 3.2.2 Karatsuba-Ofman-Multiplizierer . . . . . . . . 3.3 Divisionsschaltkreise . . . . . . . . . . . . . . . . . . . 3.3.1 Newtonmethode . . . . . . . . . . . . . . . . . 3.3.2 IBM-Dividierer . . . . . . . . . . . . . . . . . . 3.4 Schnelle Fourier-Transformation (FFT) . . . . . . . . . 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . INHALTSVERZEICHNIS 4 OBDDs 4.1 Ordered Binary Decision Diagrams . . . . . . . . . . . . 4.2 Minimierung und Reduktion . . . . . . . . . . . . . . . . 4.3 Effiziente Algorithmen für OBDD-Operationen . . . . . 4.3.1 OBDD-Minimierung . . . . . . . . . . . . . . . . 4.3.2 Weitere Operationen . . . . . . . . . . . . . . . . 4.3.3 Synthese . . . . . . . . . . . . . . . . . . . . . . . 4.4 Beispiele für reduzierte (minimierte) OBDDs . . . . . . 4.4.1 Binäre Addition . . . . . . . . . . . . . . . . . . . 4.4.2 Schwellwertfunktionen, symmetrische Funktionen 4.4.3 Speicheradressierungsfunktion . . . . . . . . . . . 4.4.4 Multiple Addition . . . . . . . . . . . . . . . . . 4.4.5 Multiplikation . . . . . . . . . . . . . . . . . . . . 4.5 Schaltkreisverifikation . . . . . . . . . . . . . . . . . . . 4.6 Variablenordnungen . . . . . . . . . . . . . . . . . . . . 4.7 Analyse sequentieller Systeme . . . . . . . . . . . . . . . 4.8 Minimalpolynome mit OBDDs . . . . . . . . . . . . . . 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75 75 81 87 87 88 91 96 96 98 99 100 102 107 107 110 112 Kapitel 1 Grundbegriffe und Komplexitätsmaße 1.1 Boolesche Funktionen als Boolesche Algebra Definition 1.1.1 Bn := {f | f : {0, 1}n → {0, 1}} ist die Menge der n-stelligen Booleschen Funktionen (mit einem Ausgabebit). Bn,m := {f | f : {0, 1}n → {0, 1}m } ist die Menge der n-stelligen Booleschen Funktionen mit m Ausgabebits. Man kann jede Funktion aus Bn explizit durch ihre „Wertetabelle“, d. i. eine Liste von 2n Bits, beschreiben. Daraus ergibt sich |Bn | = 2|{0,1} n| n = 22 Jede Funktion aus Bn,m kann man sich auch aus m Funktionen zusammengesetzt denken, wobei diese je ein Ausgabebit liefern. Es ist daher n |Bn,m | = |Bn |m = 2m2 . Man beachte die Asymmetrie zwischen der Zahl der Eingaben n und der Zahl der Ausgaben m: Mit n wächst die Anzahl der möglichen Funktionen viel schneller als mit m. Definition 1.1.2 Eine Struktur A = (A, 0, 1, +, ·, ) heißt Boolesche Algebra, wenn • A eine Menge ist • 0, 1 ∈ A, 0 = 1 3 KAPITEL 1. GRUNDBEGRIFFE UND KOMPLEXITÄTSMAE 4 • +, · sind zweistellige (Infix-)Operationen: +, · : A × A → A • ist einstellige Operation: : A → A, so dass folgendes gilt: a·b=b·a a+b =b+a a · (b + c) = a · b + a · c a + b · c = (a + b) · (a + c) a+0=a a·1=a a+a =1 a · a = 0. Beispiel: 1. B = ({0, 1}, 0, 1, ∨, ∧, ¬) ist eine Boolesche Algebra. (B ist die Boolesche Algebra der zweiwertigen Logik.) 2. Für X = ∅ ist (P(X), ∅, X, ∪, ∩, ) eine Boolesche Algebra. Es ist leicht zu sehen, dass diese isomorph ist zu (Notation: B A = {f : A → B}) ({0, 1}X , 0-Funktion, 1-Funktion, ∨, ∧, ), wobei die Operationen ∨, ∧, komponentenweise von B fortgesetzt werden, d.h. für f, g : X → {0, 1} definiere (f ∨ g)(x) := f (x) ∨B g(x) ∀x usw. Das ist ein Spezialfall einer allgemeineren Konstruktion: Sei A eine Boolesche Algebra A = (A, 0, 1, +, ·, ) und Y = ∅ eine Menge. Dann ist AY := (AY , 0-Funktion, 1-Funktion, +, ·, ) auch eine Boolesche Algebra, wobei die Operationen wieder komponentenweise gebildet werden. 3. n Bn,m = ({0, 1}m ){0,1} , 0-Funktion, 1-Funktion, +, ·, ist eine Boolesche Algebra, wobei die Verknüpfungen +, · und als „bitweise Operationen“ auf Wörtern der Länge m zu interpretieren sind. KAPITEL 1. GRUNDBEGRIFFE UND KOMPLEXITÄTSMAE 5 Aus den Axiomen sind allgemeine Rechenregeln ableitbar: a+a=a a·a=a a+1=1 a·0=0 a+a·b=a a · (a + b) = a a · (b · c) = (a · b) · c a + (b + c) = (a + b) + c (a + b) = a · b a·b=a+b (Idempotenz) (Absorption) (Assoziativität) (DeMorgan) a=a Für jede Rechenregel (Formel, Aussage) S existiert eine duale Rechenregel (Formel, Aussage) S d . Diese entsteht aus S durch Ersetzen der Operationen1 entsprechend den folgenden Regeln : · + 0 1 → + → · → 1 → 0 Es gilt dann das Dualitätsprinzip: S ⇔ Sd. Der Grund hierfür ist, dass die Axiome durch das Dualisieren gemäß obiger Regeln ineinander übergehen. 1.2 Boolesche Formeln Sei X = {X1 , X2 , . . . , Xn } eine Menge von Symbolen, die Variablen. Definition 1.2.1 (Formeln über X) 1. Die Symbole 0, 1 sind Formeln über X. 2. Für 1 ≤ i ≤ n ist Xi Formel über X. 3. Wenn φ, ψ Formeln über X sind, dann auch φ + ψ, φ · ψ und ¬φ = φ. Formeln kann man auch als Worte über einem geeignetem Alphabet auffassen. 1 Wie auch anderweitig üblich, fassen wir Konstanten als 0-stellige Operationen auf. KAPITEL 1. GRUNDBEGRIFFE UND KOMPLEXITÄTSMAE 6 Definition 1.2.2 (Jede Formel beschreibt eine Funktion.) Jeder Formel φ ist wie folgt eine Funktion fφ ∈ Bn zugeordnet: φ≡0 fφ = 0-Funktion φ≡1 fφ = 1-Funktion φ ≡ Xi fφ = proji φ ≡ (ψ + θ) fφ = fψ ∨ fθ φ ≡ (ψ · θ) fφ = fψ ∧ fθ φ ≡ (¬ψ) fφ = fψ Man beachte den Unterschied in der Symbolik: In Formeln treten die Zeichen +, ·, ¬ auf, in den Funktionen die Operationen ∨, ∧, . Formeln sind äquivalent, wenn die durch sie beschriebenen Funktionen identisch sind: φ ≡ ψ ⇔ fφ = fψ Behauptung 1.2.3 (Vollständigkeit der Basis ∧, ∨, ) Für jede Funktion aus Bn existiert eine Formel φ über X1 , . . . , Xn mit f = fφ . Beweis. Wir zeigen per Induktion über 0 ≤ i ≤ n: IBi Wenn f ∈ Bn nicht von ai+1 , . . . , an abhängt, dann existiert eine Formel φ über X1 , . . . , Xi mit f = fφ . i = 0: f ist konstant f ≡0 f ≡1 φ := 0 φ := 1 0 < i ≤ n: Sei f nicht von ai+1 , . . . , an abhängig. Wir definieren zwei Hilfsfunktionen g und h: g(a1 · · · an−1 an ) := fi,0 = f (a1 · · · ai−1 0ai+1 · · · an ) h(a1 · · · an−1 an ) := fi,1 = f (a1 · · · ai−1 1ai+1 · · · an ) g und h hängen nicht von ai , . . . , an ab. Daher existieren nach Induktionsvoraussetzung Formeln φ, ψ über X1 , . . . , Xi−1 mit g = fφ und h = fψ . Die Funktion f lässt sich nun darstellen als f = proji ∧ g ∨ (proji ∧h) . (Shannon-Zerlegung) Jetzt ist θ = Xi φ + Xi ψ eine Formel mit f = fθ . 2 KAPITEL 1. GRUNDBEGRIFFE UND KOMPLEXITÄTSMAE 1.3 7 Schaltkreise und Straight-Line-Programme Beispiel: Aus früheren Vorlesungen ist der Volladdierer bekannt, der für drei Eingabebits das Summenbit s und das Übertragsbit c (Carry) bei binärer Addition berechnet. Diesen kann man sich aus zwei Halbaddierern zusammengesetzt vorstellen. Halbaddierer (a1 , a2 ) → (c, s) s = a1 ⊕ a2 c = a1 ∧ a2 Volladdierer (a1 , a2 , a3 ) → (c, s) X2 ∧ ⊕ c s X1 X2 ∧ ⊕ X3 ∧ ⊕ s = a1 ⊕ a2 ⊕ a3 c = (a1 ∧ a2 ) ∨ (a2 ∧ a3 ) ∨ (a1 ∧ a3 ) X1 ∨ c s Der Spezifikation eines Problems durch Formeln steht die Realisierung durch Schaltkreise bzw. Gatter gegenüber. Daraus ergibt sich das sogenannte Äquivalenzproblem: Überprüfe algorithmisch die Gleichheit der spezifizierten Funktion mit der realisierten Funktion. Wir führen eine sequentielle Notation für Schaltkreise ein, sogenannte „Straight-Line-Programme“ (diese enthalten keine Schleifen). Ein SLP für den obigen Volladdierer sieht z.B. so aus: 1: ∧(X1 , X2 ) 2: ⊕(X1 , X2 ) 3: ∧(G2 , X3 ) 4: ⊕(G2 , X3 ) 5: ∨(G1 , G3 ) Ausgabe: (c, s) = (5, 4) Jede Zeile beschreibt die Funktion eines Gatters, das Variable Xi mit bereits berechneten Ergebnissen anderer Gatter Gj verknüpft. Man kann jeden Schaltkreis, der keine Kreise enthält, als SLP schreiben. Dazu führt man auf dem Graph des Schaltkreises eine sogenannte topologische Sortierung2 durch. Vor der eigentlichen Definition der Straight-Line-Programme betrachten wir noch ein Beispiel allgemeinerer „Schaltkreise“. 2 siehe Vorlesung „Effiziente Algorithmen“ KAPITEL 1. GRUNDBEGRIFFE UND KOMPLEXITÄTSMAE 8 Beispiel: (Arithmetische Schaltkreise) f (a1 , . . . , a4 ) = (a1 a2 + a3 + a4 )/(a1 a2 /a3 + a4 ) ai ∈ Q (R, K) X1 X2 1 · 3 + X3 2 4 + / 5 6 X4 + / 1: ·(X1 , X2 ) 2: +(X3 , X4 ) 3: +(G1 , G2 ) 4: /(G1 , X3 ) 5: +(G4 , X4 ) 6: /(G3 , G5 ) Ausgabe: (f)=(6) Definition 1.3.1 Sei A eine Struktur A = (A, E), wobei A eine Menge und E = (op1 , . . . , ops ) eine Liste von Operationen auf A mit opr : Ak(r) → A k(r) : Stelligkeit ist. Dann ist ein Straight-Line-Programm über A eine numerierte Liste 1: I1 2: I2 .. . c: Ic Ausgabe: (j1 , . . . , jm ) von „Instruktionen“ It , wobei It das Format opr (p1 , . . . , pk(r) ) opr ∈ E p1 , . . . , pk(r) ∈ {X1 , . . . , Xn , G1 , . . . , Gt−1 } hat. (Jede Operation verknüpft Eingaben Xi und bereits berechnete Zwischenergebnisse anderer Gatter Gj .) Zu jedem SLP gehört auch eine Liste von Ausgängen (j1 , . . . , jm ) ∈ {1, . . . , c}m . Beispiel: (für Strukturen) • B = ({0, 1}, (0, 1, ¬, ∨, ∧)) SLPs über B heißen (¬, ∨, ∧)-Schaltkreise. • ({0, 1}, B0 ∪ B1 ∪ B2 ) Boolesche Schaltkreise KAPITEL 1. GRUNDBEGRIFFE UND KOMPLEXITÄTSMAE 9 • A = ({0, 1}, (¬, (∧m )m≥2 , (∨m )m≥2 , 0, 1)) U-Schaltkreise ((¬, ∧, ∨)-Schaltkreise mit unbeschränktem Fan-In) • SLPs über (Z, ({c | c ∈ Z}, +, −, ·, . . . )) heißen arithmetische Schaltkreise Im Allgemeinen entspricht jedem SLP ein Schaltkreis und umgekehrt (Vorsicht bei nicht-kommutativen Operationen!). Die Semantik eines SLP 1: opr1 .. . c: oprc Ausgabe: (j1 , . . . , jm) lässt sich imperativ und funktional beschreiben. Imperative Beschreibung (inputorientiert, punktweise) Berechne die c Werte b1 , . . . , bc , das sind die Ergebnisse der jeweiligen Operation. Algorithmus 1.1: EvalSLP(S) Eingabe: S – SLP, Belegung (a1 , . . . , an ) der Variablen Ausgabe: (bj1 , . . . , bjm ) ∈ Am – Ergebnis der Berechnung von S (1) for t := 1 to c (2) if It = opr (p1 , . . . , pk(r) ) (3) Setze für 1 ≤ j ≤ k(r) ai falls pi = Xi qj := bs falls pi = Gs (4) bt := opr (q1 , . . . , qk(r) ) (5) return (bj1 , . . . , bjm ) ∈ Am Funktionale Beschreibung Ordne jedem Gatter eine Funktion zu: Gatter Gt → Funktion gt . Dies geschieht induktiv nach t: Seien g1 , . . . , gt−1 schon definiert und It = opr (p1 , . . . , pk(r) ). Dann definiere für 1 ≤ j ≤ k(r): proji falls pj = Xi Qj := gs falls pj = Gs KAPITEL 1. GRUNDBEGRIFFE UND KOMPLEXITÄTSMAE 10 Die zur Operation t gehörende Funktion ist gt := Komposition von opr mit Q1 , . . . , Qk(r) . Die vom gesamtem SLP berechnete Funktion ist dann (gj1 , . . . , gjm ). Beispiel: Schaltkreise für (SUMn )n≥1 Eingabe: n Bits a1 , . . . , an Ausgabe: bin(a1 + · · · + an ) = bk · · · b0 , k = log2 (n + 1) n = 2: Halbaddierer n = 2k : induktive Konstruktion: SUMn/2 ist bekannt Xn/2+1 ··· Xn SUMn/2 ··· yk−1 Xn/2 ··· X1 SUMn/2 y1 y0 yk−1 · · · y1 y0 HA VA .. z1 . z0 VA zk zk−1 Resultat: zk · · · z0 Falls n keine Zweierpotenz ist, setze eine entsprechende Anzahl von Bits auf 0. Wir bestimmen jetzt die Gatterzahl Cn dieser Schalkreise in Abhängigkeit von n. Ein SUMn enthält 2 SUMn/2 , k − 1 Volladdierer (VA) und 1 Halbaddierer (HA). Da jeder VA aus 5 Gattern und jeder HA aus 2 Gattern besteht, folgt die Rekursionsbeziehung C2 = 2 Cn = 2Cn/2 + 5(k − 1) + 2. Die Tabelle der ersten Glieder dieser Folge sieht wie folgt aus: KAPITEL 1. GRUNDBEGRIFFE UND KOMPLEXITÄTSMAE n k Cn 2 1 2 4 2 11 8 3 34 16 4 85 32 5 192 64 6 411 11 128 7 854 Behauptung 1.3.2 Cn ≤ 9n − 10 log n − 2 Beweis. Beweis durch Induktion über k = log n. k ≤ 3: C2 ≤ 9 · 2 − 10 − 2 = 6 C4 ≤ 9 · 4 − 10 · 2 − 2 = 14 C8 ≤ 9 · 8 − 10 · 3 − 2 = 40 k ≥ 4: Cn ≤ 2Cn/2 + 5k − 3 n n ≤ 2(9 · − 10 log − 2) + 5k − 3 2 2 = 9n − 20(k − 1) − 4 + 5k − 3 = 9n − 15k + 13 ≤ 9n − 10k − 2 ⇔ 5k ≥ 15 ⇔ k ≥ 4. 2 Für die Tiefe Dn von SUMn überlegt man sich grob (die Tiefe eines VA ist 3): D2 = 1 Dn ≤ Dn/2 + 3 log n n ≤ Dn/4 + 3 log + log n 2 n n n ≤ D /8 + 3 log + 3 log + log n 4 2 .. . n n n + log k−1 + · · · + log + log n) k 2 2 2 ≤ 3(0 + 1 + · · · + k) 3 = k(k + 1) ∈ O(k2 ) = O((log n)2 ) 2 ≤ 3(log Ein feineres Resultat erzielt man durch Pipelining: Behauptung 1.3.3 In SUMn stehen die Ausgaben nach den im folgenden Bild angegeben Takten zur Verfügung: KAPITEL 1. GRUNDBEGRIFFE UND KOMPLEXITÄTSMAE ··· Xn 12 X1 SUMn yk 4k−4 yk−1 4k−5 ··· y3 2k+3 y2 2k+1 y1 2k−1 y0 k Fazit: Dn ≤ 4k = 4 log n. Geht es besser als log n? Folgende Überlegung zeigt, dass stets logarithmische Tiefe erforderlich ist. 1. z0 wird von allen Inputs beeinflusst 2. 1 Gatter kombiniert 2 Zwischenergebnisse ⇒ brauche für z0 ≥ n − 1 Gatter; diese erzwingen einen Binärbaum mit n Blättern und n − 1 inneren Knoten ⇒ Tiefe log n 1.4 Größenmaße für Schaltkreise Sei S ein Schaltkreis/SLP mit Gattern (G1 , . . . , Gc ). Dann heißt C(S) := c die Größe von S (Gatterzahl). C(S) bedeutet die Schrittzahl bei sequentieller Abarbeitung. Die Schrittzahl bei paralleler Abarbeitung kann davon erheblich abweichen. Wir haben z.B. schon gesehen: VA SUMn Takte sequentiell 5 ≤ 9n Takte parallel 3 4 log n Allgemein: Teile Gatter G0 , . . . , Gc in Schichten L0 , L1 , . . . ein. L0 := {X1 , . . . , Xn } Li := {Gt | alle Vorgänger vonGt liegen in Li−1 ∪ · · · ∪ L0 , Gt ∈ Li−1 ∪ · · · ∪ L0 } für i ≥ 1 Äquivalent zu dieser Definition ist: Gt ∈ Li ⇔ der längste Weg in Graph zu Schaltkreis S von Input Xj zu Gt hat i Knoten. (1 ≤ j ≤ n) Jetzt können wir den Schaltkreis getaktet ausführen: In Takt i schalten die Gatter der Schicht Li . Die zu dieser Abarbeitung notwendige Taktzahl heißt Tiefe D(S) von S: D(S) := max{i | Li = ∅}. KAPITEL 1. GRUNDBEGRIFFE UND KOMPLEXITÄTSMAE 13 In der Praxis ist es unerwünscht, wenn Kanten viele Schichten überspringen. Schaltkreise, bei denen alle Inputs der Schicht i aus der Schicht i − 1 kommen, heißen synchronisiert. Diese lassen sich aus nicht synchronisierten durch Einfügen von ids (Gatter, die die identische Funktion berechnen) immer konstruieren. Ebenfalls praktisch unbequem ist ein großer Ausgrad k eines Gatters. Satz 1.4.1 Zu einem Booleschen Schaltkreis S mit beliebigem Ausgrad kann man einen Booleschen Schaltkreis S finden, der • dieselbe Funktion wie S berechnet • D(S ) ≤ 2D(S) und C(S) ≤ 2C(S) aufweist und • Ausgrad 2 hat. 1.5 Komplexitätsklassen für Schaltkreise (Boolesche Funktionen) Wir wollen nun die Komplexität Boolescher Funktionen analysieren. Diese soll wie üblich in Abhängigkeit von einer Inputgröße n angegeben werden. Da jede Boolesche Funktion eine feste Eingabegröße (die Anzahl der Eingabebits) besitzt, benötigen wir das Konzept der Funktionenfolgen. Definition 1.5.1 Eine Funktionenfolge (fn )n≥1 = (f1 , f2 , . . . ) ist eine Familie von Funktionen mit fn ∈ Bk(n),m(n) , wobei k, m : N → N monotone Funktionen sind. Beispiel: (Funktionenfolgen) • ADD = (ADDn )n≥1 ist die Folge der Funktionen ADDn : {0, 1}2n → {0, 1}n+1 a, b → c mit (c)2 = (a)2 + (b)2 , wobei k(n) = 2n und m(n) = n + 1 ist. • SUM = (SUMn )n≥1 mit k(n) = n und m(n) = log2 (n + 1) Analog zu den Funktionenfolgen definiert man Schaltkreisfolgen. Definition 1.5.2 Die Klasse P/poly besteht aus allen Funktionenfolgen (fn )n≥1 mit: • es existiert eine Schaltkreisfolge (über B0 ∪ B1 ∪ B2 ) (Sn )n≥1 , wobei fn von Sn berechnet wird • es existiert ein Polynom p mit C(Sn ) ≤ p(n) für alle n. KAPITEL 1. GRUNDBEGRIFFE UND KOMPLEXITÄTSMAE 14 Beispiel: • Addition von 2 n-bit-Zahlen: (ADDn )n≥1 ∈ P/poly, da man für die Schulmethode 1 Halbaddierer und n Volladdierer benötigt • Multiplikation von 2 n-bit-Zahlen: (MULTn )n≥1 ∈ P/poly, denn C(S) ∈ O(n2 ) (Schulmethode) Wir nehmen stets an, dass k(n) ≤ 2p(n), da Boolesche Schaltkreise höchstens 2 Inputs besitzen. In (Sn )n≥1 muss kein Zusammenhang zwischen Sn und Sn bestehen für n = n . Dieses „Nicht-Uniformitätsproblem“ führt dazu, dass P/poly zu viele Funktionenfolgen enthält, wie folgendes Beispiel zeigt. Beispiel: Jeder Funktionenfolge (fn )n≥1 mit fn ∈ Bn kann man eine Sprache Lf := {x ∈ {0, 1}∗ | f|x| (x) = 1} zuordnen, einer Sprache L umgekehrt eine Funktionenfolge 1 x ∈ L, |x| = n (fL,n )n≥1 mit fL,n = 0 sonst. Diese Sprachen können sehr komplex sein. Wir konstruieren aus der nicht rekursiven Diagonalsprache K eine Funktionenfolge (fn )n≥1 in P/poly. 1 bin(n) ∈ K fn (x) := 0 sonst ist eine konstante Funktion. Die zugehörige Sprache Lf = {y | bin(|y|) ∈ K} ist nicht rekursiv. Andererseits kann man eine Schaltkreisfolge (Sn )n≥1 angeben, die fn berechnet: bin(n) ∈ /K bin(n) ∈ K 0 1 C(S) ist offensichtlich 1. Es sind also auch nicht berechenbare Funktionen in P/poly! Es gibt nun zwei Möglichkeiten, das „Nicht-Uniformitätsproblem“ in den Griff zu bekommen. KAPITEL 1. GRUNDBEGRIFFE UND KOMPLEXITÄTSMAE 1.5.1 15 Uniforme (algorithmisch erzeugte) Schaltkreise Definition 1.5.3 Eine Schaltkreisfolge (Sn )n≥1 heißt logspace-uniform, wenn eine TM existiert, die mit Input 1n auf read-only-Eingabeband mit Arbeitsbandplatz ≤ c log n auf einem write-only-Ausgabeband den Schaltkreis Sn ausgibt (z.B. als Gatterliste). Man kann zeigen, dass aus • Sn berechnet fn ∈ Bn und • (Sn )n≥1 ist logspace-uniform (P-uniform) folgt: L = Lf ∈ P. Alle in dieser Vorlesung konstruierten Schaltkreise sind logspace-uniform. Bemerkung Es gibt auch allgemeinere Uniformitätsbegriffe; z.B. definiert man P-uniforme Schaltkreisfolgen analog zu den logspace-uniformen, verzichtet aber auf die Platzbeschränkung. 1.5.2 Nichtuniforme Turingmaschinen (Advice-TM) Definition 1.5.4 Eine Sprache L ist in P/poly, falls eine TM M mit polynomieller Laufzeit sowie ein Polynom q(n) und eine Folge (wn )n≥0 , wn ∈ {0, 1}q(n) existiert, so dass für x ∈ {0, 1}n gilt M akzeptiert x#wn ⇔ x ∈ L. Die Folge (wn )n≥0 heißt Advice für die Turingmaschine M , da die wn von M als „Ratschlag“, „Hilfestellung“ genutzt werden. x # wn advice“ ” Beachte: Wir haben zwei unterschiedliche Klassen P/poly definiert, nämlich eine Klasse von Funktionenfolgen und eine Klasse von Sprachen. Es besteht folgender Zusammenhang. Satz 1.5.5 fn ∈ Bn , n ≥ 0 ⇒ (fn )n≥0 ∈ P/poly ⇔ Lf ∈ P/poly Beweisskizze. „⇒“ Gegeben (Sn )n≥0 ; C(Sn ) ≤ r(n), r Polynom Idee: Wir geben der TM M als Advice die (Kodierung der) Gatterliste wn für den Schaltkreis Sn . M wertet jetzt auf Input x#wn den Schaltkreis Sn aus. Klar: Polynomial-Zeit. „⇐“ Gegeben sei eine Advice-TM M für Lf . KAPITEL 1. GRUNDBEGRIFFE UND KOMPLEXITÄTSMAE 16 Kodiere Bandalphabet Γ und Zustandsmenge Q binär: Q = {0, 1}l Γ = {0, 1}k Jeder Übergang der Zustandsüberführungsfunktion δ : Q × Γ → Q × Γ × {L, R, N } δ(q, a) → (q , a , D) wird durch einen Schaltkreis ausgedrückt: q a l k δ-Schaltkreis l q a k Problem: Wo befindet sich der Band-Kopf nach t Schritten bzw. wie berücksichtigen wir die Kopfbewegung D? Lösung: Wir benutzen „oblivious“ oder „inputbewegungsinvariante“ TM M : Die Kopfbewegung von M hängt nur von n = |x| ab, d.h. für alle Eingaben derselben Länge führt M exakt dieselben Bandbewegungen aus. x#wn ∗ ... M simuliert M in p (n) = 2p(n)(n + q(n) + 2p(n)) Schritten, wenn M p(n)zeitbeschränkt ist. Abbildung 1.1 zeigt die Struktur eines Schaltkreises für eine oblivious-TM. Die Paare (t , t), so dass der in t geschriebene Buchstabe in t gelesen wird, sind leicht aus n zu berechnen. Für jedes n wird ein anderer Schaltkreis Sn konstruiert, in dem der jeweilige 2 Advice wn fest „verdrahtet“ ist. Definition 1.5.6 Eine Basis B heißt beschränkt, wenn für jedes f ∈ B die Zahl der Eingabebits und die der Ausgabebits durch eine Konstante beschränkt sind. KAPITEL 1. GRUNDBEGRIFFE UND KOMPLEXITÄTSMAE 17 Band der TM 1 2 3 4 5 x1 x2 x3 x4 x5 ... Zeit 0 1 δ q a 2 δ q a 3 δ q a t t+1 t+2 δ ... δ q a ... ... δ q a ... q q ∈ F? Abbildung 1.1: Aufbau des Schaltkreises Sn , der eine oblivious-TM simuliert KAPITEL 1. GRUNDBEGRIFFE UND KOMPLEXITÄTSMAE 18 Definition 1.5.7 1. Für k ≥ 1 gehört (fn )n≥1 , fn ∈ Bk(n),m(n) , zu NCk (NC=„Nick’s class“), falls eine Schaltkreisfolge (Sn )n≥1 über einer beschränkten Basis fn berechnet und es ein l gibt mit C(Sn ) ∈ O(nl ) (polynomiell beschränkte Gatterzahl) D(Sn ) ∈ O((log n) ). k 2. NC := k≥1 NC k (polylogarithmisch beschränkte Tiefe) . Beispiel: • (SUMn )n≥1 ∈ NC1 • (PARITY n )n≥1 ∈ NC1 , weil D(PARITY n ) = log n und C(PARITYn ) = n−1 Bemerkung Man sieht sofort: NC ⊆ P/poly. Die Frage, ob sogar NC = P/poly gilt, ist offen. Außerdem sind logspace-uniforme (P-uniforme) Schaltkreisfolgen aus NC auch in P, wobei auch hier die Gleichheit ungeklärt ist. Da P die Klasse der (sequentiell) effizient entscheidbaren Sprachen ist, und NC zudem schnelle parallele Berechenbarkeit bedeutet, kann man die Fragestellung NC = P auch so interpretieren: Gibt es Probleme, die schnell parallel gelöst werden können, die jedoch nicht effizient sequentiell lösbar sind? Definition 1.5.8 • Die Menge U := {¬} ∪ {ORm , ANDm } heißt unbeschränkte Basis. • Schaltkreise über U heißen U -Schaltkreise. Definition 1.5.9 Für k ≥ 0 gehört (fn )n≥1 zu ACk („alternating class“), falls eine Schaltkreisfolge (Sn )n≥1 über U fn berechnet und es ein l gibt mit C(Sn ) ∈ O(nl ) D(Sn ) ∈ O((log n)k ). Besonders interessant ist AC0 . Offensichtlich sind (ANDn )n≥1 und (ORn )n≥1 in AC0 . Es wurde jedoch bewiesen, dass (PARITY n )n≥1 ∈ AC1 \ AC0 ist. Beispiel: (ADDn )n≥1 gehört zu AC0 . ADDn ist die Funktionenfamilie, die die n-Bit-Addition realisiert. Formal: KAPITEL 1. GRUNDBEGRIFFE UND KOMPLEXITÄTSMAE 19 Eingabe: zwei n-Bit-Zahlen an−1 · · · a0 , bn−1 · · · b0 Ausgabe: sn · · · s0 mit (sn · · · s0 )2 = (an−1 · · · a0 )2 + (bn−1 · · · b0 )2 Die Zahlen an−1 · · · a0 und bn−1 · · · b0 seien durch die 2n Variablen Xn−1 , . . . , X0 bzw. Yn−1 , . . . , Y0 gegeben. Wichtig sind die Carry-Bits, die den Übertrag angeben. ci = Carrybit aus letzten i + 1 Bits 1 (ai · · · a0 )2 + (bi · · · b0 )2 ≥ 2i = 0 sonst. Überträge entstehen an bestimmten Stellen und werden über eine Anzahl Bits transportiert. i ... 0 0 1 1 ... ... 1 1 0 1 ... erzeugt Carry (linkeste 11 ) Transport ci = 1 Zur Berechnung der Carrybits benutzen wir die Hilfsfunktionen (0 ≤ i < n) ui = Xi ⊕ Yi vi = Xi Yi . Diese sind mit Tiefe 3 und 6n Gattern zu berechnen. An der i-ten Stelle entsteht ein Übertrag, wenn beide Bits 1 sind (dann ist vi =1) oder wenn genau ein Bit 1 ist (ui = 1) und ein Übertrag an der Stelle i − 1 entstanden ist, also ci = vi ∨ ui ci−1 . Allgemein: ci = vi ∨ vi−1 ui ∨ vi−1 ui−1 ui ∨ · · · uk vj ∧ = 0≤j≤i j+1≤k≤i 1 ∧-Gatter auf Tiefe 4 1 ∨-Gatter auf Tiefe 5 Diese Überlegung zeigt, dass die si auf folgender Stufe berechnet werden können: Tiefe 3 s0 = u0 si = ui ⊕ ci−1 , sn = cn−1 1≤i<n Tiefe 8 Tiefe 5 KAPITEL 1. GRUNDBEGRIFFE UND KOMPLEXITÄTSMAE 20 Für Sn gilt D(Sn ) = 8 C(Sn ) = 6n + n n2 + 12n, + n + 5(n − 1) ≤ 2 2 d.h. ADDn ist mit konstanter Tiefe und polynomieller Gatterzahl (der Basis U ) berechenbar. Satz 1.5.10 ∀k ≥ 1 : ACk−1 ⊆ NCk ⊆ ACk . Beweis. 1. NCk ⊆ ACk Für (fn )n≥1 existiert eine B2 -Schaltkreisfolge (Sn )n≥1 mit C(Sn ) ∈ O(nl ) und D(Sn ) ∈ O((log n)k ). Konstruiere Sn aus Sn , indem in Sn alle op ∈ B2 durch {¬, ∧, ∨}-Gatter ersetzt werden. Dann ist Sn ∈ ACk . 2. ACk−1 ⊆ NCk Sn sei ein U -Schaltkreis mit C(Sn ) = O(nl ), D(Sn ) = O((log n)k−1 ). Wir ersetzen in Sn jedes ANDm -Gatter durch einen Binärbaum von m−1 ∧-Gattern mit Tiefe log m (analog für ORm ). Sinnvoll ist es nur, ein Gatter mit höchstens allen Ausgängen anderer Gatter und allen Eingaben zu verschalten. Wir können daher voraussetzen, dass m ≤ C(Sn ) + n ≤ 2 max{C(Sn ), n} gilt. Dann ergibt sich: log m ≤ 1 + log(max(C(Sn ), n)) ≤cnl ≤ O(1) + l log n = O(log n) D(Sn ) = O((log)k−1 ) · O(log n) = O((log n)k ) C(Sn ) ≤ C(Sn ) ·(C(Sn ) +n) ≤ c(c + 1)n2l ∈ O(n2l ). cnl cnl Folgerung k≥0 ACk = k≥1 NCk = NC. 2 Kapitel 2 Minimierung zweistufiger Schaltkreise 2.1 Formeln und Normalformen Definition 2.1.1 (Polynome) 1. X1 , X2 , . . . heißen Variable 2. X1 , X1 , X2 , X2 , . . . heißen Literale 3. Monome oder Terme sind Produkte l1 l2 · · · ls von Literalen (s ≥ 0) Xi · Xj , I ∩ J = ∅ allgemein: mI,J = i∈I leeres Monom: j∈J m∅,∅ =: 1. 4. Ein Boolesches Polynom (oder eine DNF-Formel ) ist eine Summe von Monomen. Es ist klar, dass jedes Polynom p über den Variablen X1 , . . . , Xn eine Funktion f ∈ Bn darstellt, die wir fp nennen. Es gibt 3n Monome über n n n Variablen und daher 23 Polynome. Andererseits gibt es aber nur 22 Boolesche Funktionen mit n Variablen, Polynome sind also eine „redundante Darstellung“. Es ist sinnvoll, nach dem jeweils billigsten Polynom zu einer gegebenen Funktion zu suchen. Definition 2.1.2 Der Minterm zu einer Eingabe a ∈ {0, 1}n ist Xi · Xj . ma := ai =1 Für eine Funktion f ∈ Bn heißt pf := aj =0 a∈f −1 (1) 21 ma KAPITEL 2. MINIMIERUNG ZWEISTUFIGER SCHALTKREISE 22 die kanonische disjunktive Normalform (KDNF ) von f . Satz 2.1.3 1. pg stellt g dar, d. h. fpg = g. 2. Kein anderes Polynom aus Mintermen als pg stellt g dar. Definition 2.1.4 (KNF-Formeln) 1. Eine Klausel ist eine Summe von s ≥ 0 Literalen. Xi + Xj , I ∩ J = ∅ allgemein: CI,J = i∈I leere Klausel: j∈J C∅,∅ =: 0. 2. Der Maxterm zu a ∈ {0, 1}n ist Xi + Xi . Ma = ai =0 ai =1 Es gilt: Ma (b) = 0 ⇔ a = b. 3. Qf := Ma a∈f −1 (0) heißt kanonische konjunktive Normalform von f . Definition 2.1.5 Die duale Funktion f d von f ist f d(a1 , . . . , an ) := f (a1 , . . . , an ). f d ist strukturell gleichwertig zu f . (Man vertauscht sowohl im Input als auch im Output die 0 und die 1.) Beispiel: Offenbar gilt (ANDn )d (a1 , . . . , an ) = ANDn (a1 , . . . , an ) = · · · = ORn (a1 , . . . , an ). Fakt 2.1.6 d f d = f. Satz 2.1.7 Sei p Polynom mit fp = f . Dann erhält man KNF-Formel für f d , indem man in p + durch · und · durch + ersetzt. KAPITEL 2. MINIMIERUNG ZWEISTUFIGER SCHALTKREISE 23 Beweis. Sei p = m1 + · · · + mr . Q bezeichnedie Konjunktion von Klauseln, die aus p durch die Vertauschung von + und · entsteht: Q = C1 · C2 · · · Cr . f (a1 , . . . , an ) = 1 ⇔ ∃j : mj (a1 , . . . , an ) = 1 ⇔ ∃j : Cj (a1 , . . . , an ) = 0 ⇔ fQ (a1 , . . . , an ) = 0 2 Fazit: Wir betrachten nur Polynome, da die entsprechenden KNF-Formeln daraus konstruierbar sind. Es gibt eine weitere Normalform, die sogenannte Ringsummenexpansion (Reed-Muller-Expansion). Diese verwendet die Basis {∧, ⊕} (entspricht Rechnen im Ring Z2 , d. h. ·, + mod 2). Definition 2.1.8 Ein ⊕-Polynom ist eine ⊕-Summe von Monomen mit Faktoren aus {X1 , . . . , Xn } („positive Monome“). Für I ⊆ {1, . . . , n} und S ⊆ P({1, . . . , n}): Xi mI = i∈I rS = mI I∈S Beispiel: • X1 ⊕ X1 X2 ⊕ X2 X3 X4 . • X1 ⊕ X2 ⊕ · · · ⊕ Xn stellt PARITYn dar. • X1 X2 · · · Xn stellt ANDn dar. • ORn : Wir wissen (Übung): X = 1 ⊕ X. Damit und mit der DeMorganschen Regel: ORn (X1 , . . . , Xn ) = 1 ⊕ (1 ⊕ X1 ) · (1 ⊕ X2 ) · · · (1 ⊕ Xn ) Ausmultiplizieren liefert: für n = 2: 1 ⊕ (1 ⊕ X1 ) · (1 ⊕ X2 ) =1 ⊕ (1 ⊕ X2 ⊕ X1 ⊕ X1 X2 ) =X1 ⊕ X2 ⊕ X1 X2 analog ergibt sich für n = 3: X1 X2 X3 ⊕ X1 X2 ⊕ X1 X3 ⊕ X2 X3 ⊕ X1 ⊕ X2 ⊕ X3 und allgemein I⊆{1,...,n} I=∅ MI KAPITEL 2. MINIMIERUNG ZWEISTUFIGER SCHALTKREISE 24 Behauptung 2.1.9 Für jede Boolesche Funktion f existiert (bis auf die Reihenfolge der positiven Monome) genau eine Ringsummenexpansion r mit f = fr . Beweis. 1. Existenz Für f existiert eine KDNF f= ma , a∈f −1 (1) wobei jedes Minimalpolynom ma genau einen 1-Punkt hat. Deshalb gilt a = b ⇒ ma + mb = ma ⊕ mb und für f folglich f= ma . a∈f −1 (1) Ferner ist ma = Xi · ai =1 = rf = Xi ai =0 Xi · ai =1 (1 ⊕ Xi ) . ai =0 ausmultiplizieren: ra ra (streiche Paare identischer Monome) a∈f −1 (1) Beispiel: NAND(X1 , X2 ) =(1 ⊕ X1 )(1 ⊕ X2 ) ⊕ (1 ⊕ X1 )X2 ⊕ X1 (1 ⊕ X2 ) =1 ⊕ X1 X2 . 2. Eindeutigkeit |B| = 22 n Anzahl der Ringsummenexpansionen (RSE) r ist |P(P({1, . . . , n}))| = 22 . n positive Monome Nach 1. besitzt jedes f ∈ Bn eine RSE rf , wegen der gleichen Mächtigkeit beider Mengen höchstens eine. 2 Beispiel: • NANDn : 1 ⊕ X1 · · · Xn • 0-Funktion: leere Summe • 1-Funktion: leeres Monom 1 KAPITEL 2. MINIMIERUNG ZWEISTUFIGER SCHALTKREISE 2.2 25 Entscheidungsfragen bekannt: NP, NP-vollständig, Satz von Cook, co-NP Eine Sprache L ist co-NP-vollständig, wenn 1. L ∈ co-NP 2. ∀L ∈ co-NP : L ≤p L. Fakt 2.2.1 L co-NP-vollständig ⇔ L NP-vollständig. SAT SAT co-NPC NPC co-NP P NP Was unterscheidet co-NP-vollständige von NP-vollständigen Problemen? Betrachten wir Sat: ϕ ∈ Sat: ϕ ∈ Sat: 1 Belegung raten nachweisen, dass fϕ (a) = 0 für alle a Anscheinend sind co-NP-vollständige Probleme schwerer, es ist allerdings offen, ob nicht doch co-NPC = NPC gilt. Entscheidungsprobleme haben z. B. die Form: • Pn ⊆ Bn , n ≥ 1. Ist ein gegebenes f ∈ Bn auch in Pn ? • Pn ⊆ Bn × Bn , n ≥ 1. Ist für f, g ∈ Bn das Paar (f, g) ∈ Pn ? f ∈ Bn kann dabei in verschiedenen Formaten gegeben sein: • Polynom • Wertetabelle • KNF-Formel • SLP KAPITEL 2. MINIMIERUNG ZWEISTUFIGER SCHALTKREISE 26 • Boolesche Formel • RSE Die Größe der Eingabe ist die Bitzahl der jeweiligen Darstellung. Einige Beispiele für Pn sind: Erfüllbarkeit Tautologie Widerspruch Nullierbarkeit Äquivalenz Dominanz Pn Pn Pn Pn Pn Pn = {f ∈ Bn | f ≡ 0} = {f ∈ Bn | f ≡ 1} = {f ∈ Bn | f ≡ 0} = {f ∈ Bn | f ≡ 1} = {(f, g) ∈ Bn × Bn | f ≡ g} = {(f, g) ∈ Bn × Bn | f ≤ g} Eine Übersicht über die Komplexitäten einiger Entscheidungsprobleme bei verschiedenen Eingabeformaten enthält Tabelle 2.1. 2.3 Minimierung und Primimplikanten Jedes Polynom kann leicht durch einen zweistufigen Schaltkreis ausgewertet werden. Ein Schaltkreis, der die durch p = m1 + m2 + · · · + mr gegebene Funktion berechnet, benötigt |m1 | − 1 + 1 + |m2 | − 1 + 1 + · · · + |mr | − 1 Gatter, wobei |m| die Anzahl der Literale von m ist. Wir nennen |mi | = Zahl der Literale von p cost(p) := 1≤i≤r die Kosten von p. Definition 2.3.1 Unter einer Minimierungsaufgabe verstehen wir folgendes Problem: Zu p finde p∗ mit fp = fp∗ und ∀q : fp = fq ⇒ cost(q) ≥ cost(p∗ ). Jedes solche p∗ heißt ein Minimalpolynom von p. Beispiel: Wir betrachten folgende Funktion f : 110 100 000 010 101 001 111 011 f −1 (1) KNF-Formel Polynom B2 -Formel 4 NPC polynomiell NPC co-NPC polynomiell co-NPC polynomiell1 co-NPC5 co-NPC8 polynomiell NPC NPC co-NPC2 co-NPC6 co-NPC co-NPC3 co-NPC7 co-NPC NPC NPC NPC U -Schaltkreis NPC co-NPC co-NPC NPC co-NPC co-NPC NPC RSE O(1) O(1)9 O(1)10 O(1) polynomiell11 polynomiell12 polynomiell φ → (φ, 0) KNF-Widerspruch ≤p KNF-Dominanz 5 4 (KNF) φ → (Polynom) φd KNF-Widerspruch ≤p Polynom-Tautologie erfüllbares Monom finden Polynom-Tautologie ist in co-NP; co-NP-vollständig: φ → (φ, X1 ∧ X1 ) KNF-Widerspruch ≤p KNF-Äquivalenz 3 KNF-Nichtäquivalenz {(φ, ψ) | fφ ≡ fψ } ist in NP, d.h. Äquivalenz ∈ co-NP; co-NP-vollständig: 2 teste, ob jede Klausel Ci ein Paar Xi + Xi enthält Reduktion von KNF-Widerspruch (entspricht Sat) auf KNF-Dominanz: 1 φ → (φ, 1) Polynom-Tautologie ≤p Polynom-Äquivalenz Polynom-Äquivalenz ist in co-NP; co-NP-vollständig: 9 B2 -Tautologie ist ein Spezialfall von Polynom-Tautologie ist φ leer? 10 ist φ das Monom 1? 11 Idee: f ≤ g ⇔ f g ≡ 0 ⇔ f (1 ⊕ g) ≡ 0. Die letzte Gleichung läßt sich in polynomieller Zeit ausmultiplizieren, kürzen und auf 0 testen. 12 gleiche Terme? 8 7 φ Tautologie ⇔ 1 ≤ fφ φ → (1, φ) Polynom-Tautologie ≤p Polynom-Dominanz Die Reduktion geht in Polynomialzeit: Vertausche + durch ·; sie klappt wegen fφ ≡ 0 ⇔ fφd = f d ≡ 1. 6 Polynom-Dominanz ist in co-NP; co-NP-vollständig: Tabelle 2.1: Komplexität der Beispielprobleme bei den verschiedenen Eingabeformaten (Eingabegröße Wertetabelle: N = 2n ) Erfüllbarkeit Widerspruch Tautologie Nullierbarkeit Dominanz Äquivalenz Nicht-Äquivalenz Wertetabelle Θ(N ) Θ(N ) Θ(N ) Θ(N ) Θ(N ) Θ(N ) Θ(N ) KAPITEL 2. MINIMIERUNG ZWEISTUFIGER SCHALTKREISE 27 KAPITEL 2. MINIMIERUNG ZWEISTUFIGER SCHALTKREISE 28 Offenbar kann ein Polynom für f keine Einzelliterale enthalten, d. h. die Terme haben (mindestens) die Form Xi Xj . Wegen |f −1 (1)| = 5 sind drei Terme dieser Form in jedem Polynom für f zwingend notwendig. „Kurze“ Polynome sind z.B. p1 = X1 X0 ∨ X1 X0 ∨ X2 X0 p2 = X2 X1 ∨ X1 X0 ∨ X1 X0 . Satz 2.3.2 Wenn die Minimierungsaufgabe einen Polynomialzeitalgorithmus besitzt, dann ist P = NP. Beweis. Der Algorithmus A berechne zu p ein Minimalpolynom p∗ in PolynomialZeit. Wir konstruieren daraus einen Algorithmus B, der das Tautologieproblem löst. Algorithmus 2.1: B(p) Eingabe: p Ausgabe: ist p Tautologie? (1) Berechne p∗ mittels A. (2) 1. Fall: p∗ = 1-Monom (3) Ausgabe: NEIN (4) 2. Fall: p∗ = 1-Monom (5) Ausgabe: JA Man sieht: B löst das Tautologieproblem. Da A in Polynomial-Zeit läuft, gilt dies auch für B. 2 Bemerkung Wenn ein Algorithmus C existiert, der aus p die Kosten des Minimalpolynoms cost(p∗ ) berechnet, dann ist P = NP. (Beweis: Übung) Definition 2.3.3 Sei f eine Funktion aus Bn . 1. Ein Monom m heißt Implikant von f , in Zeichen m ≤ f (d. h. fm ≤ f ), falls m−1 (1) ⊆ f −1 (1) oder gleichbedeutend ∀a : m(a) = 1 ⇒ f (a) = 1. Die Menge aller Implikanten von f bezeichnen wir mit I(f ): I(f ) := {m | m Monom, m ≤ f }. 2. Ein Monom m heißt Verkürzung von m, falls m ≤ m und m aus m durch Streichen von Literalen hervorgeht. (Jedes Monom ist Verkürzung von sich selbst. Gilt |m | < |m| so heißt m echte Verkürzung von m.) 3. Ein Monom m heißt Primimplikant von f , falls • m ∈ I(f ), • m hat keine Verkürzung, die Implikant ist: ∀m ∈ I(f ) : m Verkürzung von m ⇒ m = m . Die Menge aller Primimplikanten ist PI(f ). KAPITEL 2. MINIMIERUNG ZWEISTUFIGER SCHALTKREISE 29 Satz 2.3.4 Wenn p∗ = m1 + · · · + mr ein minimales Polynom für f ist, dann ist mi ∈ PI(f ), 1 ≤ i ≤ r. Beweis. Klar: fp∗ = f ⇒ mi ≤ f . Betrachte m1 = l1 · · · ls . Wir nehmen an (im Gegensatz zur Behauptung), dass m1 ∈ I(f ) eine echte Verkürzung von m1 ist. Dann erfüllt p := m1 + m2 + · · · + mr die Gleichung fp = f , da f = m1 + · · · + mr ≤ m1 + · · · + mr ≤ f + · · · + f ≤ f. Allerdings gilt auch cost(p ) < cost(p∗ ), weswegen p∗ nicht minimal gewesen sein kann. 2 Es gilt sogar noch mehr, nämlich f = fp für p = m. m∈PI(f ) Wegen m ≤ f für alle m ist fp ≤ f klar. Für die andere Richtung ist zu zeigen: ∀a ∈ f −1 (1) ∃m ∈ PI(f ) mit m(a) = 1. Wir erhalten m durch Streichen von Literalen aus ma , solange das resultierende Monom noch Implikant ist. Das Monom ist dann ein Primimplikant und damit in p enthalten. Allgemeiner gilt, dass es für jeden Implikanten m von f eine Verkürzung m gibt, die Primimplikant ist. Daraus ergibt sich folgender Ansatz zur Berechnung eines Minimalpolynoms: 1. Berechne PI(f ). 2. Wähle Primimplikanten aus, um Minimalpolynom zu erhalten. Beispiel: Für manche Funktionen kann man direkt sehen, dass dieser Ansatz ein sehr schlechtes Laufzeitverhalten hat. Wir definieren induktiv Funktionen fk ∈ B2k−1 , so dass fk eine Darstellung mit k Monomen hat, aber 2k − 1 Primimplikanten. Für diese Funktionen kostet der (Um)Weg über die Primimplikanten also schon exponentielle Zeit. Allerdings ist dies wegen Satz 2.3.2 prinzipiell unvermeidlich (außer es gilt P = NP). Setze f1 = X1 und für k ≥ 1 setze fk+1 = X2k ∧ fk ∨ X2k X2k+1 . Aus der Definition folgt sofort durch Ausmultiplizieren in jedem Schritt, dass fk als Polynom mit k Termen geschrieben werden kann, die Kosten KAPITEL 2. MINIMIERUNG ZWEISTUFIGER SCHALTKREISE 30 (Anzahl der Literale) sind O(k2 ). (Man multipliziere f4 aus!) Also sind auch die Kosten eines Minimalpolynoms für fk nicht größer als O(k2 ). Behauptung: fk hat 2k − 1 Primimplikanten. – Dies beweist man durch Induktion über k. Dass f1 nur X1 als Primimplikanten hat, ist klar. Als I.V. nehmen wir an, dass die Behauptung für fk stimmt. Sei nun m ein beliebiger Primimplikant von fk . Wir zeigen, dass X2k m und X2k+1 m beides Primimplikanten von fk+1 sind. (Zudem ist X2k X2k+1 Primimplikant, wie man leicht sieht, das ergibt zusammen 2(2k − 1) + 1 = 2k+1 − 1 viele.) „X2k m“: Es ist X2k m ≤ X2k fk ≤ fk+1 , also ist X2k m Implikant. Kann eine echte Verkürzung Implikant sein? Wenn a = a1 . . . a2k+1 Input ist mit m(a1 . . . a2k−1 ) = 1 und a2k = 0 und a2k+1 = 0, dann ist fk+1 (a) = 0; also ist m kein Implikant. Sein nun m echte Verkürzung von m. Weil m Primimplikant von fk ist, gibt es a1 . . . a2k−1 mit m (a1 . . . a2k−1 ) = 1 und fk (a1 . . . a2k−1 ) = 0. Wenn wir a2k = 1 und a2k+1 = 0 setzen, dann folgt X2k m (a1 . . . a2k+1 ) = 1 und fk+1 (a1 . . . a2k+1 ) = 0, also ist auch die Verkürzung X2k m kein Implikant. „X2k+1 m“: Sei a ∈ 0, 12k+1 Input mit X2k+1 m(a) = 1. Das heißt: m(a1 . . . a2k−1 ) = 1 und a2k+1 = 1. Wenn nun a2k = 1 ist, dann wird (X2k ∧ fk )(a) = 1, also fk+1 (a) = 1. Wenn a2k = 0 ist, wird (X2k X2k+1 )(a) = 1, also wieder fk+1 (a) = 1. Also ist X2k+1 m Implikant von fk+1 . Der Nachweis, dass X2k+1 m nicht verkürzbar ist, sei dem Leser zur Übung überlassen. 2.4 Algorithmus von Quine/McCluskey Als Eingabe sei die Funktionstabelle von f durch N = 2n Bits gegeben (oder als Liste von f −1 (1)). Für den Algorithmus sind die Mengen Qk := {m ∈ I(f ) | |m| = k}. wesentlich. Wir berechnen aus dem bekannten Qn = {ma | a ∈ f −1 (1)} induktiv Qn−1 , Qn−2 , . . . , Q1 , Q0 und sondern unterwegs die Primimplikanten aus. Lemma 2.4.1 Sei m Monom der Länge k. 1. k = n ⇒ (m ∈ Qn ⇔ m ist f -Minterm) 2. k ≤ n − 1: Seien Xi , Xi nicht in m. Dann: m ∈ Qk ⇔ mXi , mXi ∈ Qk+1 . 3. m ∈ Qk : m ist in PI(f ) genau dann, wenn keines der k Monome, die durch Kippen eines Literals in m entstehen, in Qk ist. KAPITEL 2. MINIMIERUNG ZWEISTUFIGER SCHALTKREISE 31 Beweis. zu 2.: Die Richtung „⇒“ ist klar. Für die „⇐“ seien mXi , mXi ∈ Qk+1 . Dann haben wir: mXi , mXi ≤ f ⇒ mXi + mXi ≤ f ⇒ mXi + mXi = m(Xi + Xi ) = m ≤ f und damit m ∈ Qk . zu 3.: „⇒“: Sei m ∈ PI(f ). Angenommen, m = m Xi und m Xi ∈ Qk . Daraus folgt m = m Xi + m Xi ≤ f, d. h. m ist echte Verkürzung von m ∈ I(f ) im Widerspruch zur Primimplikanteneigenschaft von m. „⇐“: Sei m ∈ / PI(f ), d. h. es existiert eine Verkürzung m von m, die durch Streichen eines Literals Xi oder Xi aus m entsteht und Implikant ist. Dann 2 sind m Xi , m Xi ∈ Qk . Algorithmus 2.2: Quine-McCluskey(Qn ) Eingabe: Qn – Menge aller Minterme von f Ausgabe: PI(f ) – Menge aller Primimplikanten von f (1) foreach k = n − 1, n − 2, . . . , 1 (2) while Qk = ∅ (3) Qk−1 := ∅ (4) Pk := Qk (5) foreach Paar mXi , mXi ∈ Qk mit |m| = k − 1 und Xi , Xi nicht in m (6) Qk−1 := Qk−1 ∪ {m} (7) Pk := Pk \ {mXi , mXi } (8) P0 := Q0 (9) return Pn ∪ Pn−1 ∪ · · · ∪ P0 Behauptung 2.4.2 1. Der Algorithmus gibt PI(f ) aus. 2. Die Laufzeit ist bei cleverer Implementierung O(n3 3n ) bzw. O((log N )3 · N log2 3 ) für die Eingabegröße N = 2n . Beweis. zu 1.: folgt aus dem vorherigen Lemma KAPITEL 2. MINIMIERUNG ZWEISTUFIGER SCHALTKREISE 32 zu 2.: Wesentlich ist die Verwendung „schlauer“ Datenstrukturen. Die Monome speichert man als Vektoren über {0, 1, 2} (z.B. entspricht X1 X2 X4 dem Vektor (1 0 2 1)). Außerdem wird Qk aufgespalten in die Mengen Qk,0 , . . . , Qk,k mit Qk,i = {m ∈ Qk | m hat i negative Literale}, die jeweils als balancierter Suchbaum der Tiefe O(log|Qk,i |) = O(n) verwaltet werden. In einer Runde sucht man dann Paare in Qk,i−1 × Qk,i , das entspricht k|Qk,i−1 | Suchen im Qk,i -Baum mit Zeit O(n·n·n). Für die Runde k ergibt sich O(|Qk |n3 ) und insgesamt O( k |Qk |n3 ) = O(3n n3 ). 2 Diese Laufzeit ist leider praktisch nicht verbesserbar, da es Funktionen f mit sehr vielen Primimplikanten gibt, wie folgendes Beispiel zeigt. Beispiel: Sei n = 3k. Wir definieren eine Funktion MDn („mittleres Drittel“): 1 , falls k < 1≤i≤n ai ≤ 2k MDn (a1 , . . . , an ) := 0 , sonst. Wie sehen die Primimplikanten von MDn aus? Es muss gesichert werden, dass MDn für eine Eingabe mit mindestens k Einsen 1 wird, aber auch, dass MDn für mehr als 2k Einsen, d. h. weniger als k Nullen, den Wert 0 annimmt. Es ergibt sich folgende Charakterisierung durch eine „isomorphe“ Menge von 0-1-2-Folgen: Xi · Xj |I| = |J| = k, I ∩ J = ∅ PI(MDn ) = i∈I j∈J ={012-Folgen ˆ der Länge n | k Nullen, k Einsen, k Zweien} (3k)! |PI(MDn )| = (k!)3 Mit der Stirlingschen Formel n! ≈ √ 2πn n n e können wir weiter abschätzen: √ 3k √ n 2π3k 3k 3 3 33k (3k)! e · ∈ Θ . ≈ = √ k k 3 (k!)3 2π k n 2πk e KAPITEL 2. MINIMIERUNG ZWEISTUFIGER SCHALTKREISE 2.5 33 Weitere Methoden zur Berechnung der Primimplikanten Die in diesem Abschnitt betrachteten Algorithmen berechnen aus einem Polynom p das Polynom der Primimplikanten p∗ = m∈PI(f ) m. 2.5.1 Rekursive Methode („Baummethode“) In dem folgenden Algorithmus werden an mehreren Stellen Vereinfachungen durchgeführt, die wir in dem Unteralgorithmus Vereinfache zusammenfassen. Diese Vereinfachungen verändern die berechnete Funktion nicht. Algorithmus 2.3: Vereinfache(p) Eingabe: p – Polynom Ausgabe: p – vereinfachtes Polynom (1) Streiche alle widersprüchlichen Monome (z.B. · · · Xi · · · Xi · · · ). (2) Ersetze in allen Monomen mehrfach vorkommende Literale durch eine Kopie des Literals. (3) Wenn p zwei Monome Xi und Xi enthält, dann ersetze p durch 1. (4) Wenn ein Monom m und eine echte Verkürzung m von m in p sind, dann streiche m. (Wiederhole dies, solange solche Paare zu finden sind.) Die Idee der Baummethode ist, das Polynom rekursiv in Teilpolynome zu zerlegen (mittels Shannon-Zerlegung), diese zu vereinfachen, die entsprechenden Primimplikanten zu berechnen und daraus die Primimplikanten von p zu konstruieren. Algorithmus 2.4: Baummethode(p) Eingabe: p: vereinfachtes Polynom Ausgabe: p∗ (1) 1. Fall: p enthält kein Monom oder das 1-Monom oder nur Monome der Länge 1 (2) p∗ = p: (3) 2. Fall: sonst (4) Sei Xi Variable in einem Monom der Länge ≥ 2. (Heuristik für Auswahl: Xi kommt in vielen Monomen vor) (5) Bilde pi,0 := pX =0 (Ersetze Xi durch 0 und Xi durch 1) i (umgekehrt) pi,1 := p Xi =1 und vereinfache beide, Ergebnis sei wieder pi,0 und pi,1 . KAPITEL 2. MINIMIERUNG ZWEISTUFIGER SCHALTKREISE (6) 34 Finde rekursiv p∗i,0 = Baummethode(pi,0 ) p∗i,1 = Baummethode(pi,1 ) (7) Bilde (8) multipliziere p aus: liefert p ; Vereinfache(p ); Resultat: p∗ return p∗ . p := Xi p∗i,0 + Xi p∗i,1 + p∗i,0 p∗i,1 , Bevor wir uns dem Nachweis zuwenden, dass p∗ tatsächlich das Polynom der Primimplikanten ist, werden wir ein technisches Lemma beweisen, das allgemein die Beziehung zwischen Primimplikanten von Funktionen f und ihren Subfunktionen fi,0 und fi,1 klärt. Die Subfunktionen von f sind dabei wie folgt definiert: Funktionen fi,0 (a1 · · · an ) = f (a1 · · · ai−1 0ai+1 · · · an ) fi,1 (a1 · · · an ) = f (a1 · · · ai−1 1ai+1 · · · an ), aus denen man mit der schon bekannten Shannon-Zerlegung f = proji · fi,0 + proji ·fi,1 f erzeugen kann. Lemma 2.5.1 1. m0 ∈ I(fi,0 ), m1 ∈ I(fi,1 ) ⇒ Xi m0 ∈ I(f ), Xi m1 ∈ I(f ), m0 m1 ∈ I(f ) 2. m ∈ PI(f ), m = Xi m1 ⇒ m1 ∈ PI(fi,1 ) 3. m ∈ PI(f ), m = Xi m0 ⇒ m0 ∈ PI(fi,0 ) 4. m ∈ PI(f ), m enthält weder Xi noch Xi ⇒ ∃m0 ∈ PI(fi,0 ), m1 ∈ PI(fi,1 ) : m = m0 m1 (nach Vereinfachung). Beweis. In diesem Beweis werden wir oft p ≤ f für ein Polynom p und eine Funktion f schreiben und meinen damit eigentlich fp ≤ f . Die Feststellung p ≤ p bedeutet fp ≤ fp ; die Feststellung p ≡ p heißt fp = fp . Man beachte, dass für Monome m, m die Beziehung m ≤ m genau dann gilt, wenn m eine Verkürzung von m ist (auch m = m eingeschlossen). zu 1.: Sei m0 ∈ I(fi,0 ) und m1 ∈ I(fi,1 ), d. h. m0 ≤ fi,0 und m1 ≤ fi,1 . Daraus folgt Xi m0 ≤ proji · fi,0 ≤ proji · fi,0 + proji ·fi,1 = f KAPITEL 2. MINIMIERUNG ZWEISTUFIGER SCHALTKREISE 35 Analog zeigt man Xi m1 ∈ I(f ). Es gilt ebenfalls m0 m1 ∈ I(f ): m0 m1 ≡ (Xi + Xi ) · m0 m1 ≡ X i m0 m1 + X i m0 m1 ≤ X i m1 + X i m0 ≤ proji ·fi,1 + proji · fi,0 = f. zu 2.: Wir müssen zwei Dinge zeigen: dass m1 Implikant von fi,1 ist, und dass m1 nicht verkürzbar ist, ohne seine Implikanteneigenschaft zu verlieren. Sei a = a1 . . . an ∈ {0, 1}n beliebig. Weil Xi m1 ≤ f gilt und weil m1 und fi,1 von ai unabhängig sind, können wir rechnen: m1 (a1 · · · an ) = m1 (a1 · · · ai−1 1ai+1 · · · an ) = (Xi m1 )(a1 · · · ai−1 1ai+1 · · · an ) ≤ f (a1 · · · ai−1 1ai+1 · · · an ) = fi,1 (a1 · · · an ). Also gilt m1 ∈ I(fi,1 ). Zu zeigen bleibt, dass m1 Primimplikant von fi,1 ist. Annahme: m1 ≤ fi,1 ist eine echte Verkürzung von m1 . Dann ist Xi m1 Implikant von f wegen Xi · m1 ≤ Xi · fi,1 + Xi · fi,0 = f. Zudem ist Xi m1 eine echte Verkürzung von Xi m1 = m. Dies widerspricht der Voraussetzung, dass Xi m1 ∈ PI(f ) ist. zu 3.: analog zu 2. zu 4.: Sei m ∈ PI(f ) von Xi unabhängig. – Wir zeigen zunächst: m ∈ I(fi,01 ) und m ∈ I(fi,1 ). Sei dazu a = a1 . . . an ∈ {0, 1}n eine Eingabe. Wir rechnen: m(a) = m(a1 · · · ai−1 0ai+1 · · · an ) ≤ f (a1 · · · ai−1 0ai+1 · · · an ) = fi,0 (a). Analog: m(a) = m(a1 · · · ai−1 1ai+1 · · · an ) ≤ f (a1 · · · ai−1 1ai+1 · · · an ) = fi,1 (a). Weil m Implikant von fi,0 und von fi,1 ist, hat m eine Verkürzung m0 ∈ PI(fi,0 ) und eine Verkürzung m1 ∈ PI(fi,1 ), und für diese gilt: m = m · m ≤ m0 · m1 . Das Monom m0 m1 kann aber keine echte Verkürzung von m sein, denn wegen 1. ist m0 m1 ∈ I(f ), und wenn m0 m1 eine solche echte Verkürzung von m wäre, wäre m kein Primimplikant. Also gilt m = m0 m1 . 2 Satz 2.5.2 Die Baummethode liefert als Ergebnis p∗ das Polynom aller Primimplikanten. KAPITEL 2. MINIMIERUNG ZWEISTUFIGER SCHALTKREISE 36 Beweis. 1. Terminierung Jeder Rekursionsschritt verringert die Variablenzahl, d. h. die Rekursionstiefe ist durch die Variablenzahl begrenzt. 2. Korrektheit Wir zeigen durch Induktion über die rekursiven Aufrufe folgendes: Das Resultat p∗ ist das Polynom aller Primimplikanten. (Daraus folgt: fp = fp∗ , siehe 2.3.) Im Basisfall (1. Fall im Algorithmus) ist nicht schwer zu sehen, dass p∗ Polynom der Primimplikanten ist. (Übung.) Seien nun die Resultate p∗i,0 , p∗i,1 korrekt. Zunächst zeigen wir durch Anwendung von 1. des vorherigen Lemmas, dass fp = fp gilt. Das Polynom p = Xi p∗i,0 + Xi p∗i,1 + p∗i,0 p∗i,1 , das als Ausgabe der Baummethode gebildet wird, erfüllt p ≥ p: p ≥ Xi p∗i,0 + Xi p∗i,1 ≡ Xi pi,0 + Xi pi,1 ≡ p. Es gilt aber auch p ≤ p, weil: Xi p∗i,0 ≡ Xi pi,0 ≤ p Xi p∗i,1 ≡ Xi pi,1 ≤ p p∗i,0 · p∗i,1 = (m1 + · · · + mr )(m1 + · · · + ms ) ≡ mi mj ≤ p. 1≤i≤r 1≤j≤s Ausmultiplizieren von p liefert p . Mit Lemma 2.5.1 zeigen wir, dass p alle Primimplikanten von fp enthält. Sei dazu m Primimplikant von fp . Es gibt drei Fälle: (a) m = Xi · m0 : Dann kommt m0 in p∗i,0 vor, also m in Xi · p∗i,0 , also in p . (b) m = Xi · m1 : Dann kommt m1 in p∗i,1 vor, also m in Xi · p∗i,1 , also in p . (c) Xi , Xi nicht in m: Wegen Lemma 2.5.1 gibt es Monome m0 , m1 , wobei m0 in p∗i,0 und m1 in p∗i,1 auftritt. Das Monom m entsteht dann beim Ausmultiplizieren von p , ist also in p . 2 Jeder Primimplikant von p tritt also in p auf. Beim Vereinfachen werden alle Monome aus p gestrichen, die keine Primimplikanten sind. (Wenn nämlich m in p vorkommt und nicht Primimplikant ist, ist m Implikant von fp . Durch Streichen von Literalen entsteht ein Primimplikant m , der Verkürzung von m ist. Dieses m kommt in p vor, also wird m bei der Vereinfachung gestrichen.) Daher enthält das resultierende Polynom p∗ alle Primimplikanten und nur diese. Beispiel: Wir betrachten p = X1 · · · Xm + Xm+1 · · · X2m + · · · + X(m−1)m+1 · · · Xm2 . KAPITEL 2. MINIMIERUNG ZWEISTUFIGER SCHALTKREISE 37 Es treten n = m2 Variable auf. Die Basis der Rekursion wird erst nach mindestens m Rekursionsstufen erreicht. Der Rekursionsbaum enthält daher einen vollen binären Baum der Tiefe m, der 2m Knoten besitzt. Es ergibt sich √ n eine Laufzeit von Ω(2 ). Das heißt: Eingabe und Ausgabe haben Kosten √ O(n), aber der Aufwand für die Baummethode ist exponentiell in n groß. Frage: Kann es überhaupt einen Algorithmus geben, der zu einem gegebenen Polynom p das Polynom p∗ aller Primimplikanten berechnet und dabei in cost(p) + cost(p∗ ) polynomiellen Aufwand hat? Sei A ein Algorithmus, der p∗ aus p wie oben berechnet. Wir konstruieren aus A, der Polynom-Tautologie (co-NP-vollständig) in Polynomialzeit entscheidet. Algorithmus 2.5: B(p) Eingabe: p Ausgabe: ist p Tautologie? (1) Führe maximal q(cost(p) + cost(1)) Schritte von A auf p aus, wobei q(·) die Laufzeitschranke für A ist (2) if A(p) = p∗ = 1 (3) return JA (4) else (5) return NEIN Der Algorithmus B löst Polynom-Tautologie: Wenn p eine Tautologie ist, ist p∗ = 1 und A benötigt auf p höchstens q(cost(p) + cost(1)) Schritte für diese Ausgabe, d. h. p wird von B akzeptiert. Ist p andererseits keine Tautologie, so ist p∗ = 1 und B verwirft p. Fazit: Wenn P = NP, dann existiert kein Algorithmus zur Berechnung des Polynoms aller Primimplikanten, der einen in cost(p) + cost(p∗ ) polynomiellen Aufwand hat. 2.5.2 Iterierter Konsensus Der (einfache) Konsensus zweier Monome mXi , mXi ist m. Allgemein ist mm der Konsensus von mXi und m Xi , falls mm = 0. Lemma 2.5.3 mXi + m Xi ≡ mXi + m Xi + mm . Beweis. Zu zeigen ist nur: mm ≤ mXi + m Xi . mm = (Xi + Xi )mm = Xi mm + Xi mm ≤ mXi + m Xi . 2 KAPITEL 2. MINIMIERUNG ZWEISTUFIGER SCHALTKREISE 38 Bemerkung Man beachte, dass in der Aussagenlogik die Resolvente zweier Klauseln {Xi , 1 , . . . , r } und {Xi , 1 , . . . , s } als {1 , . . . , r } ∪ {1 , . . . , s } definiert ist. Konsensus und Resolvente sind also duale Begriffe. Die duale Form des Lemmas lautet: Wenn C die Resolvente zweier Klauseln C1 und C2 ist, dann haben C1 ∧ C2 und C1 ∧ C2 ∧ C dieselben erfüllenden Belegungen. Diese Aussage ist für die Resolution grundlegend. Aus dem Lemma ergibt sich folgende Idee zur Erzeugung aller Primimplikanten: Füge iterativ den Konsensus zweier Monome zum Polynom hinzu und streiche gegebenenfalls Verkürzungen. Algorithmus 2.6: Iterierter Konsensus(p) Eingabe: Polynom p Ausgabe: p∗ (1) while es existiert Konsensus m von Monomen mi und mj in p, wobei es in p keine Verkürzung von m gibt (2) füge m zu p hinzu (3) vereinfache p (4) return p Aus Lemma 2.5.3 folgt sofort, dass das Polynom p während des Ablaufs des Algorithmus immer dieselbe Funktion darstellt: Hinzufügen von Konsensus-Monomen und Vereinfachen ändern diese Funktion nicht. Der nächste Satz besagt, dass nach Terminieren des Algorithmus das Polynom genau seine Primimplikanten enthält. Satz 2.5.4 Sei p ein vereinfachtes Polynom. Wenn es in p zu jedem Konsensus von Monomen eine Verkürzung gibt, dann enthält p genau alle Primimplikanten von fp . Beweis. Wir bezeichnen zur Abkürzung die geforderte Eigenschaft mit A(p): A(p) : zu jedem Konsensus von Monomen in p gibt es eine Verkürzung in p Es genügt zu zeigen, dass aus A(p) folgt, dass p alle Primimplikanten von fp enthält. (Für die Eliminierung der Nicht-Primimplikanten sorgt dann die Vereinfachung.) Der Beweis erfolgt mittels Induktion über die Anzahl der Variablen in p. n = 0: Es ist p ≡ 0 oder p ≡ 1. In beiden Fällen gilt A(p). n ≥ 1: Sei m ∈ PI(p). Dann ist zu zeigen: m kommt in p vor. 1. Fall: m = 1 Sei m = Xi m . (Die Argumentation verläuft für m = Xi m analog.) Dann können wir p durch Ausklammern von Xi bzw. Xi wie folgt zerlegen: p = Xi p0 + Xi p1 + p2 . Man sieht sofort den folgenden Zusammenhang mit den Subfunktionen von fp : fp0 +p2 = (fp )i,0 und fp1 +p2 = (fp )i,1 . KAPITEL 2. MINIMIERUNG ZWEISTUFIGER SCHALTKREISE 39 Beobachtung: Falls A(p1 + p2 ) gilt, ist m in p: Nach Induktionsvoraussetzung enthält p1 + p2 dann alle Primimplikanten von p1 + p2 = pi,1 . Dies wenden wir an: • Wegen Lemma 2.5.1 ist m Primimplikant von pi,1 und kommt daher in p1 + p2 vor. • m kann nicht in p2 sein: Wäre m in p2 , wären m Implikant von fp und echte Verkürzung des Primimplikanten m. Also: m ist in p1 . Somit ist m = Xi m in p. Wir müssen jetzt nur noch zeigen, dass A(p1 + p2 ) gilt. Seien dazu m1 Xj , m2 Xj Monome in p1 + p2 mit Konsensus m1 m2 . Zu zeigen ist: p1 + p2 enthält eine Verkürzung von m1 m2 . Definiere , falls m1 in p2 m1 M1 := m1 Xi , falls m1 in p1 M2 := m2 , falls m2 in p2 m2 X i , falls m2 in p1 (Man macht das Streichen von Xi wieder rückgängig, wenn es denn erfolgt ist.) Die Monome M1 und M2 sind in p. Wegen A(p) hat der Konsensus M1 M2 eine Verkürzung M̃ in p. Nach Konstruktion von M1 M2 kommt Xi nicht in M̃ vor. Also ist M̃ Monom in Xi p1 + p2 . Durch Weglassen von Xi entsteht aus M̃ ein Monom m̃, das Verkürzung von m1 m2 ist und in p1 + p2 ist. Damit folgt: A(p1 + p2 ), wie gewünscht. 2. Fall: m = 1 Wir wissen dann, dass fp ≡ 1 gilt, jedoch könnte p theoretisch aus vielen Termen bestehen und das 1-Monom nicht enthalten. Wir zeigen, dass dies nicht passieren kann, weil dann immer ein Konsensus existiert, der zu einem neuen Monom führt. Wir nehmen an (Ziel: Widerspruch), dass p ≡ 1-Monom gilt. Weil p nicht leer ist, enthält p eine Variable Xi , die wir für eine Zerlegung wie eben benutzen. p = Xi p0 + Xi p1 + p2 Klar ist: fp0 +p2 = (fp )i,0 = 1-Funktion fp1 +p2 = (fp )i,1 = 1-Funktion. Wie im 1. Fall überlegt man sich, dass A(p1 + p2 ) und A(p0 + p2 ) gelten. Wegen der Induktionsvoraussetzung enthält dann sowohl p0 + p2 als auch p1 + p2 den Primimplikanten 1. Nach obiger Annahme ist 1 nicht in p. ⇒ 1 ist nicht in p2 ⇒ 1Xi und 1Xi sind in p ⇒ (nach Bedingung A(p)): der Konsensus 1 von Xi und Xi ist in p. Dies widerspricht der Annahme. Falls fp ≡ 1, ist die Ausgabe also 1. 2 KAPITEL 2. MINIMIERUNG ZWEISTUFIGER SCHALTKREISE 40 Korrektheit des Algorithmus: 1. Terminierung Es gibt höchstens 3n Monome. Jedes m wird höchstens einmal zu p hinzugefügt. Danach ist immer entweder m oder eine Verkürzung von m in p enthalten, so dass m kein zweites Mal hinzugefügt werden kann. 2. Korrektheit Das resultierende Polynom erfüllt A(p). Nach dem eben bewiesenem Satz enthält es alle Primimplikanten von p. Wenn man die Funktion fk aus Beispiel 14 benutzt und sie zu gk := fk ∨ X2k ∨ X2k modifiziert, gk ausmultipliziert und dann den Algorithmus „Iterierter Konsensus“ anwendet, wobei möglichst lange möglichst weit links gearbeitet wird, dann werden erst alle 2k −1 Primimplikanten von fk berechnet und dann erst mit dem Konsensus X2k , X2k das 1-Monom. Die Laufzeit ist also exponentiell, Eingabe und Resultat haben nur Länge O(k2 ) bzw. O(1). Bemerkung Wir bemerken, dass zwischen dem Algorithmus „Iterierter Konsensus“ und der (aussagenlogischen) Resolution ein enger Zusammenhang besteht. Wenn man genau hinsieht, liefert der Korrektheitsbeweis für „Iterierter Konsensus“ einen Korrektheitsbeweis für das gewöhnliche Resolutionsverfahren sowie ein etwas verbessertes, „schlankeres“ Verfahren. Dualität übersetzt Polynome in KNF-Formeln, das 1-Monom in die leere (unerfüllbare) Klausel, und Konsensus-Schritte in Resolutionsschritte: Der Konsensus-Schritt X1 X2 X4 X6 ∨ X2 X4 X7 X10 → X1 X4 X6 X7 X10 entspricht dem Resolutionsschritt (X1 ∨ X2 ∨ X4 ∨ X6 ) ∧ (X2 ∨ X4 ∨ X7 ∨ X10 ) → (X1 ∨ X4 ∨ X6 ∨ X7 ∨ X10 ). Der allgemeine Resolutionsalgorithmus schreibt vor, ausgehend von einer gegebenen KNF-Formel ϕ immer wieder solche Schritte auszuführen, bis keine neue Klausel mehr entsteht oder bis die leere Klausel erzeugt wurde (dann ist die Ausgangsformel unerfüllbar). Wir können sogar noch Vereinfachungsschritte hinzufügen, die dafür sorgen, dass gewisse überflüssige Klauseln gar nicht erzeugt werden: Wenn Klausel C eine Verlängerung von Klausel C ist, streiche C . Bei der Anwendung des Resolutionsschritts erzeuge Verlängerungen existierender Klauseln erst gar nicht. Der entstehende Algorithmus ist dual zum Algorithmus „Iterierter Konsensus“. Nach Satz 2.5.4 liefert dieser modifizierte Algorithmus das Produkt aller „Primklauseln“ der Ausgangs-KNF-Formel ϕ, das sind Klauseln C mit der Eigenschaft, dass aus C(a) = 0 folgt, dass fϕ (a) = 0 gilt und dass keine Verkürzung von C diese Eigenschaft hat. KAPITEL 2. MINIMIERUNG ZWEISTUFIGER SCHALTKREISE 41 Was hat das jetzt mit dem Ziel des Resolutionsverfahrens zu tun, nämlich zu testen, ob KNF-Formeln ϕ erfüllbar sind? Nun, wenn ϕ unerfüllbar ist, dann ist die leere Klausel eine Primklausel und wird nach Satz 2.5.4 vom Algorithmus irgendwann erzeugt (der darauffolgende Vereinfachungsschritt streicht alle anderen Klauseln, der Algorithmus gibt „unerfüllbar“ aus). Wenn aber ϕ erfüllbar ist, dann kann nie die leere Klausel erzeugt werden, der Algorithmus bleibt also nach endlich vielen Schritten stehen, ohne diese erzeugt zu haben. In diesem Fall gibt der Resolutionsalgorithmus korrekterweise „erfüllbar“ aus. 2.5.3 Doppeltes Produkt Algorithmus 2.7: DoppeltesProdukt(p) Eingabe: Polynom p Ausgabe: Polynom der Primimplikanten p∗ (1) Vereinfache p (2) Dualisiere p zur KNF-Formel Q (3) Multipliziere Q aus und vereinfache zu Polynom p (4) Dualisiere p zu KNF-Formel Q (5) Multipliziere Q aus und vereinfache zu Polynom p∗ Satz 2.5.5 Das Polynom p∗ , das von DoppeltesProdukt berechnet wird, ist das Polynom aller Primimplikanten von p. Beweis. Zunächst vergewissern wir uns, dass p∗ dieselbe Funktion wie p berechnet. Aus dem Satz über Dualisierung erhalten wir fQ = fpd und fp = fQ . Einsetzen: d fp∗ = fQ = (fp )d = fpd = fp . Es bleibt zu zeigen, dass jeder Primimplikant m von p auch in p∗ auftritt, d. h. in Schritt 5 beim Ausmultiplizieren vorkommt. Sei Q = C1 ∧ · · · ∧ Cr , Ci Klausel, wobei Ci nicht trivial (nicht von der Form (· · · + Xi + · · · + Xi + · · · )) sein kann, da sonst das Monom · · · Xi · · · Xi · · · in p in Schritt 3 entfernt worden wäre. Die Produkte in Schritt 5 haben die Form h1 h2 · · · hr , hi Literal aus Ci . m sei nun Primimplikant von fp . Dann gilt: m ≤ fp = fQ = C1 ∧ · · · ∧ Cr ⇒ m ≤ Cj , 1 ≤ j ≤ r ⇒ ∀i : ∃hi in Ci mit m ≤ hi , sogar: hi in m, d. h. m = l1 · · · ls enthält h1 , . . . , hr . KAPITEL 2. MINIMIERUNG ZWEISTUFIGER SCHALTKREISE 42 ⇒ h1 · · · hr ist Verkürzung von m und h1 , . . . , hr kommt in der Ausgabe p∗ vor; fp = fp∗ ≥ h1 · · · hr ⇒ h1 · · · hr ∈ I(p) ⇒ m = h1 · · · hr , da m Primimplikant ist 2.6 2 Berechnung eines Minimalpolynoms Zur Berechnung eines Minimalpolynoms kann die Eingabe in zwei Formen vorliegen, nämlich 1. als Funktionstabelle (Wertetabelle) 2. als Polynom p. 2.6.1 Minimalpolynom bei Eingabe der Funktionstabelle Sei die Funktion in Form der Funktionstabelle gegeben. Eine Primimplikanten-Tafel (PI-Tafel) ist eine Tabelle, die für jeden Primimplikanten eine Zeile und für jeden Input, der als Ergebnis 1 liefert, eine Spalte enthält. In jeder Zelle steht der Wert des Primimplikanten auf der Eingabe (0 oder 1). Formal: a ∈ f −1 (1) m∗ (a) m∗ ∈ PI(f ) Beispiel: 0010 0011 0100 0101 0111 1010 1011 1110 1111 1 X1 X2 X3 X1 X2 X4 X2 X3 X3 X4 X1 X3 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 Anschauliche Interpretation: Die Spalten entsprechen den Eingaben, für die die Funktion 1 ist. Jede Zeile ist eine Teilfunktion, die gewisse Spalten überdeckt, also dort auch 1 ist. Ziel ist es jetzt, mit möglichst wenig Zeilen (Primimplikanten) alle Spalten zu überdecken, um so an allen nötigen Stellen die 1 zu erzeugen. Formal: Finde überdeckende Menge S ⊆ PI(f ), sodass ∀a ∈ f −1 (1) : (∃m∗ ∈ S : m∗ (a) = 1) mit cost(S) := m∗ ∈S |m ∗| minimal. KAPITEL 2. MINIMIERUNG ZWEISTUFIGER SCHALTKREISE 43 Definition 2.6.1 1. m∗ ∈ PI(f ) heißt Kernimplikant, falls ∃a ∈ f −1 (a) : m∗ (a) = 1 ∧ ∀m∗ ∈ PI(f ), m∗ = m∗ : m∗ (a) = 0 . (anschaulich: es gibt eine Eingabe a, die von keinem anderen Primimplikanten überdeckt wird) 2. Spalte für a majorisiert Spalte für a , wenn ∀m∗ : m∗ (a) ≤ m∗ (a ). (anschaulich: Spalte für a enthält in allen Zeilen eine 1, in denen auch a eine 1 enthält; jeder Primimplikant, der a abdeckt, deckt auch a ab) Beispiel: • Im letzten Beispiel sind X1 X2 X3 , X2 X3 und X1 X3 Kernimplikanten. • Die Spalte für 1011 wird von der Spalte für 1111 majorisiert. Diese beiden Konzepte nutzt man zur Reduktion der PI-Tafel auf eine einfachere Form. Die Kernimplikanten müssen im Minimalpolynom auftreten, deshalb kann man sie als gewählt betrachten; majorisierte Spalten werden stets durch Primimplikanten für andere Spalten abgedeckt, so dass sie keine weitere Information liefern. Reduktion der PI-Tafel: 1. Wähle (Markiere) alle Kernimplikanten m∗ . Streiche alle Spalten a, die von einem gewählten m∗ überdeckt werden. 2. Streiche alle Spalten, die majorisiert werden. (Dabei entstehen keine neuen Kernimplikanten.) Resultat: reduzierte PI-Tafel Beispiel: 0111 X1 X2 X4 X3 X4 1 1 In diesem Fall ist X3 X4 billiger, es ergibt sich also das Minimalpolynom X1 X2 X3 + X2 X3 + X1 X3 + X3 X4 . Die reduzierte PI-Tafel ist eine Instanz des NP-vollständigen Problems SetCover. SetCover: KAPITEL 2. MINIMIERUNG ZWEISTUFIGER SCHALTKREISE 44 Eingabe: Mengen A1 , . . . , Ar mit Ai ⊆ A und ri=1 Ai = A; Gewichte β1 , . . . , βr ∈ N Aufgabe: Finde S ⊆ {1, . . . , r} mit i∈S Ai = A und cost(S) = i∈S βi minimal Fakt 2.6.2 Jede Instanz des SetCover-Problems, wo alle βi gleich sind, ist reduzierte PI-Tafel einer Funktion f mit Kosten |m∗ |. Der Fakt besagt, dass das SetCover-Problem nicht nur auf wenigen exotischen Eingaben, sondern stets schwer ist. Ein Ausweg aus dieser Situation ist die Verwendung einer Heuristik, wie z. B. Branch & Bound. Branch & Bound-Heuristiken können auch zur Lösung anderer schwerer Probleme verwendet werden. Branch & Bound zur Bestimmung des Minimalpolynoms Betrachten wir unseren konkreten Fall von SetCover: Eingabe ist eine PITafel x. Eine Lösung ist eine Menge S ⊆ PI(f ) mit ∗ m (a) = 1 für alle a ∈ f −1 (1) und m∗ ∈S cost(S) = |m∗ | ist minimal. m∗ ∈S Wir versuchen, die Lösung schrittweise aufzubauen: Für jedes m∗ ∈ PI(f ) entscheiden wir nacheinander, ob wir es nehmen (+) oder nicht (−). Jede Teillösung entspricht einem Teilproblem, dass wir als 4-Tupel TP = (M + , M − , M, A) schreiben, wobei die einzelnen Komponenten die Bedeutung M+ M− M A gewählte m∗ ausgeschlossene m∗ noch nicht behandelte m∗ noch relevante Inputs a haben und (M + , M − , M ) eine Partition von PI(f ) ist. Zu jedem Teilproblem gehören die Lösungsmengen {S | M + ⊆ S, M − ∩ S = ∅, S ⊆ PI(f )}. Jedes Teilproblem stellt eine teilweise gestrichene PI-Tafel dar. Auf einer teilweise gestrichenenen PI-Tafel (M̃ + , M̃ − , M̃ , Ã) kann man eine relative Reduktion ausführen: KAPITEL 2. MINIMIERUNG ZWEISTUFIGER SCHALTKREISE 45 1. füge die relativen Kernimplikanten m∗ mit m∗ ∈ M̃ , ∃a ∈ à : ∀m∗ ∈ M̃ + ∪ M̃ : m∗ (a) = 0 zu M̃ + hinzu; streiche aus à alle a mit m∗ (a) = 1; streiche m∗ aus M̃ 2. streiche aus à alle a, deren Spalten majorisiert werden Resultat der relativen Reduktion: reduziertes Teilproblem (M + , M − , M, A) Bei der relativen Reduktion können durch das Streichen der m∗ aus M̃ neue Majorisierungssituationen entstehen. Dadurch wird die Lösungsmenge aber nicht verändert. Verzweigungsschritt („Branch“) Aus dem reduzierten Teilproblem TP = (M + , M − , M, A) kann man an einem beliebigen m∗ ∈ M „verzweigen“, d. h. zwei Teilprobleme TP1 , TP2 erzeugen: M̃1+ := M + ∪ {m∗ } M̃2+ := M + M̃1− := M − M̃2− := M − ∪ {m∗ } M̃1 := M \ {m∗ } M̃2 := M \ {m∗ } Ã1 := A \ {a | m∗ (a) = 1} Ã2 := A Reduktion liefert: TP1 = Reduktion liefert: (M1+ , M1− , M1 , A1 ) TP2 = (M2+ , M2− , M2 , A2 ) Die Baumwurzel TP0 gewinnen wir durch Reduktion aus ˜ 0 := (∅, ∅, PI(f ), f −1 (1)). TP Die Blätter des Baumes sind die Teilprobleme mit A = ∅. Der Gesamtbaum ist endlich, da die Tiefe ≤ |PI(f )| ist. (M + , M − , M, A) TP0 +m∗0 + M01 :=M + ∪{m∗0 } +m∗01 −m∗0 TP01 TP11 −m∗01 +m∗00 − :=M − ∪{m∗0 } M11 −m∗00 TP010 TP011 TP110 TP111 ... ... ... ... KAPITEL 2. MINIMIERUNG ZWEISTUFIGER SCHALTKREISE 46 Die Besonderheit des Branch & Bound-Verfahrens besteht darin, in jedem Knoten den spaltenden Primimplikanten m∗ geschickt zu wählen. Man baut den Baum vorsichtig auf, mit dem Ziel, das Durchsuchen des gesamten Baumes zu vermeiden. Die aktuellen Teilprobleme heißen Baumperipherie {TP1 , . . . , TPr }. TP1 TP5 TP6 TP7 TP2 TP3 TP4 Beschränken („Bounding“) Um das zu spaltende Teilproblem auszuwählen, berechnet man für alle Teilprobleme untere Schranken UTP und obere Schranken OTP der in dem jeweiligen Teilproblem erzielbaren Kosten. Wir betrachten dazu das Teilproblem TP = (M + , M − , M, A). Obere Schranken Eine obere Schranke UTP muss erfüllen |m∗ |, UTP ≥ cost(S) = m∗ ∈S für alle optimalen Lösungen S von TP. Zu TP suchen wir explizit ein S mit cost(S) = UTP . Dafür benutzen wir eine Greedy-Strategie, d. h. wir wählen jeweils das Monom aus M , das die meisten noch nicht überdeckten Eingaben neu überdeckt. Algorithmus 2.8: GreedyCover(TP) Eingabe: TP = (M + , M − , M, A) Ausgabe: STP (1) S := M + ; B := A (2) while B = ∅ (3) Wähle m∗ ∈ M \ S mit |B ∩ (m∗ )−1 (1)| maximal (4) S := S ∪ {m∗ }; B := B \ (m∗ )−1 (1) (5) return STP := S KAPITEL 2. MINIMIERUNG ZWEISTUFIGER SCHALTKREISE 47 Nachdem wir jetzt eine Menge STP für jedes Teilproblem gefunden haben, definieren wir UTP := cost(STP ) U := min{UTP1 , . . . , UTPr }. Das so konstruierte U erfüllt die Invariante U ≥ cost(S ∗ ), für optimale Lösung S ∗ . Außerdem läßt sich aus den in der Peripherie möglichen Lösungen immer eine optimale Lösung konstruieren, da die Teilprobleme TP1 , . . . , TPr stets den gesamten Raum aller legalen Lösungen überdecken. Untere Schranken Analog zu den oberen Schranken muss jede untere Schranke LTP erfüllen |m∗ |, LTP ≤ m∗ ∈S für alle Lösungen S von TP. Um LTP zu berechnen, sei z = |A| die Anzahl noch zu überdeckender Eingaben. Wir nehmen weiter an, dass die M = {m1 , . . . , mt } aufsteigend nach Kosten sortiert sind, d. h. |m1 | ≤ · · · ≤ |mt |. Jedes der Monome hat einen 1-Bereich, dessen Größe berechnet werden kann durch n−|mi | . |m−1 i (1)| = 2 Aus der Sortierung folgt 2n−|m1 | ≥ · · · ≥ 2n−|mt | . Eine minimale Überdeckung S muss noch z Eingaben abdecken und hat dafür nur die Monome aus M zur Verfügung und benötigt dafür mindestens s Elemente, wobei 2n−|m1 | + · · · + 2n−|ms | ≥ z, s minimal. Also ist LTP := |m1 | + · · · + |ms | eine untere Schranke für die Minimalkosten von TP und L := min{LTP1 , . . . , LTPr } eine untere Schranke für das Gesamtproblem. KAPITEL 2. MINIMIERUNG ZWEISTUFIGER SCHALTKREISE 48 Auswahl des zu spaltenden Teilproblems Wir haben nun die oberen und unteren Schranken L := min{LTP1 , . . . , LTPr } U := min{UTP1 , . . . , UTPr } berechnet. 1. Fall: L = U Wir haben eine optimale Lösung gefunden. Es gilt U = UTPj für ein j und die zugehörige Lösungsmenge Sj ist optimal. 2. Fall: L < U Wir haben noch keine optimale Lösung und müssen daher ein Teilproblem aufspalten. Wir wählen ein Teilproblem TPj mit LTPj = L und zerlegen TPj an einem Primimplikanten m∗ ∈ Mj . Bemerkung Diese Wahl von j ist nur heuristisch. Allerdings muss an diesem Teilproblem in jedem Fall gearbeitet werden. Wird nämlich zuerst ein anderes Problem TPl gespalten, so kann die untere Schranke Ll eines entstehenden Teilproblems nur größer sein als Ll . Wegen L < Lj ≤ Ll ≤ Ul ≤ U kann man aber die eventuelle Optimalität nicht feststellen, ohne vorher TPj zu spalten. obere Schranke untere Schranke opt j l l l Branch & Bound ist eine allgemeine Strategie für Optimierungsprobleme, bei denen Lösungen komponentenweise nacheinander spezifiziert werden können, z.B. Rucksack. Man kann auch Lösungen approximieren, indem man bei U − L < ε abbricht. 2.6.2 Minimalpolynom bei Eingabe eines Polynoms Sei jetzt die Funktion f durch ein Polynom p gegeben. Daraus können wir das Polynom aller Primimplikanten p∗ = m∗1 + · · · + m∗r KAPITEL 2. MINIMIERUNG ZWEISTUFIGER SCHALTKREISE 49 berechnen und betrachten es ebenfalls als gegeben. Problematisch ist, dass ein Monom m von p nicht zwingend von einem Primimplikanten überdeckt wird. Wenn wir also wir wie schon zuvor einen Branch & Bound-Algorithmus benutzen wollen, so ergibt sich für ein Teilproblem TP TP = (M + , M − , M, q), q Teilpolynom von p die folgende Teilaufgabe: Bestimme eine möglichst billige Auswahl S, S ⊆ M ∪ M + , S ∩ M − = ∅ mit m∗ ≥ q. m∗ ∈S Ein Teilschritt in diesem Algorithmus ist das Bestimmen der Kernimplikanten. Ein Kernimplikant m∗0 ∈ M von TP erfüllt m∗ ≥ q. m∗ ∈M ∪M + \{m∗0 } Diese Aussage ist äquivalent zu ∃m in q : m∗ ≥ m. m∗ ∈M ∪M + \{m∗0 } Das folgende Lemma besagt, dass das Finden der Kernimplikanten äquivalent dem Nullierbarkeitsproblem für Polynome (NP-vollständig) und damit schwer ist. Lemma 2.6.3 p ≥ m = X1a1 · · · Xlal ⇔ p X1 =a1 ,...,X =a ≡ 1 (nullierbar) l l (Konvention: X 0 = X, X 1 = X) Fazit: Simple Einzelschritte sind schwierig und tendenziell sehr aufwendig. Trotzdem ist der Branch & Bound-Ansatz vernünftig. Kapitel 3 Schaltkreiskonstruktionen 3.1 Additionsschaltkreise In diesem Abschnitt werden wir uns Schaltkreise für die Funktionenfolge (ADDn )n≥1 überlegen. Wir haben im Beispiel 9 gesehen, daß sich die Schulmethode der Addition mit konstanter Tiefe und O(n2 ) Gattern realisieren läßt. Als Verbesserung geben wir den Fischer-Ladner-Addierer an, dessen Gatterzahl nur linear wächst. Dafür ist etwas Vorarbeit nötig. Wir wollen zwei n-Bit-Zahlen a und b addieren: an−1 an−2 · · · ai · · · a0 + bn−1 bn−2 · · · bi · · · b0 . Offensichtlich ist si = ai ⊕ bi ⊕ ci−1 . Das Problem besteht jetzt darin, die Carry-Bits c0 , c1 , . . . , cn−1 in geringer Tiefe billig zu berechnen. Wieder benutzen wir die Hilfsgrößen ui = Xi Yi vi = Xi ⊕ Yi , die das Übertragsverhalten an der i-ten Position beschreiben. Offenbar treten für (ui , vi ) nur die Kombinationen (1, 0), (0, 1) und (0, 0) auf. Wie verhält sich das Carry-Bit ci bei diesen Kombinationen? (ui , vi ) = (0, 0): ai = bi = 0 (ui , vi ) = (1, 0): ai = bi = 1 (ui , vi ) = (0, 1): ai = bi ci−1 wird an dieser Stelle auf jeden Fall „verschluckt“; „E-Stelle“ (eliminate) unabhängig von ci−1 entsteht hier ein Übertrag; „G-Stelle“ (generate) ci−1 wird an dieser Position „weitergeleitet“: „P-Stelle“ (propagate) 50 KAPITEL 3. SCHALTKREISKONSTRUKTIONEN 51 Beispiel: a= b= 0 1 1 1 0 0 1 1 1 0 0 1 1 0 0 1 P P P G P E P G Die Kernidee ist nun, größere Abschnitte der Eingabe als P, G, E zu charakterisieren, z. B.: P P P E G E P P G P P G P E G E Zur Berechnung der Klassifikation eines Abschnitts benutzen wir die Operation ◦, die beschreibt, wie sich zwei benachbarte Abschnitte insgesamt verhalten. ◦ E P G E E E E P E P G G G G G Durch Inspektion überprüft man, daß ◦ assoziativ ist. Aufgrund der Kodierung von P, G und E gilt (u, v) ◦ (u , v ) = (u + u v, vv ). Wir können die Carry-Bits ci jetzt über (ci , di ) = (ui , vi ) ◦ (ui−1 , vi−1 ) ◦ · · · ◦ (u0 , v0 ) für (0 ≤ i ≤ n − 1) berechnen. Das ist sequentiell in n Schritten möglich. Wegen der Assoziativität ist auch eine parallele Berechnung möglich, die als Baum Tiefe O(log n) und Θ(n2 ) Gatter benötigt. Die Bestimmung der Carry-Bits auf diese Weise ist ein Spezialfall der sogenannten parallelen Präfixberechnung, die auch in anderen Anwendungen auftritt. Wir untersuchen diese jetzt allgemein und erhalten dadurch auch bessere Schaltkreise für (ADDn )n≥1 . 3.1.1 Parallele Präfixberechnung (Postfixberechnung) Unter dem Postfixproblem versteht man folgende allgemeine Aufgabenstellung: Gegeben sei eine assoziative Operation ∗ : A × A → A und eine Eingabe zn−1 , . . . , z0 ∈ A. Gesucht sind die Postfixe wi = zi ∗ · · · ∗ z0 , 1 ≤ i ≤ n − 1. Das Präfixproblem lautet analog. Durch die Assoziativität von ∗ ist wieder parallele Berechnung möglich. KAPITEL 3. SCHALTKREISKONSTRUKTIONEN 52 Divide-and-Conquer Wir konstruieren induktiv einen Schaltkreis Pn , der für n = 2k alle Postfixe wi berechnet. P1 : Es gilt w0 = z0 ; der Schaltkreis besteht also nur aus einer Leitung. Pn , n = 2k : Sei Pn/2 schon konstruiert. Wir teilen die Eingabe auf und nutzen Pn/2 : zn−1 zn/2 ... zn/2−1 ... Pn/2 wn−1 ∗ wn−1 Pn/2 ... ∗ z0 ... wn−2 w0 wn/2−1 ... w1 w0 ∗ wn/2 Die Analyse liefert: Tiefe D(Pn ) = k = log2 n Größe C(P1 ) = 0 C(Pn ) = 2C(Pn/2 ) + n 2 = 2(2C(Pn/4 ) + n4 ) + = 22 C(Pn/22 ) + 2 · .. . n 2 = 2k C(Pn/2k ) + k · n 2 n 2 = 12 n log2 n. Shrink-and-Expand Induktive Konstruktion von Qn zur Berechnung der wi : Q1 : wie oben: Schaltkreis besteht nur aus Leitung Qn , n = 2k : Sei Qn/2 schon konstruiert. Wir „verkleinern“ die Eingabe und nutzen Qn/2 : KAPITEL 3. SCHALTKREISKONSTRUKTIONEN zn−1 zn−2 zn−3 zn−4 ∗ z3 ∗ zn/2−1 53 z2 z1 ∗ ... zn/2−2 z0 ∗ z1 z0 w1 w0 Qn/2 wn/2−1 wn/2−2 zn−2 z4 ∗ z2 ∗ ... wn−1 wn−2 wn−3 ∗ w4 w3 w2 w1 w0 Es gelten die Beziehungen: w0 = z0 w2i+1 = wi = z2i+1 ∗ · · · ∗ z0 w2i+2 = z2i+2 ∗ wi . Analyse: Tiefe: D(Q1 ) = 0 D(Qn ) = D(Qn/2 ) + 2 ⇒ D(Qn ) = 2 log2 n Größe: C(Q1 ) = 0 C(Qn ) = C(Qn/2 ) + n − 1 = C(Qn/4 ) + .. . n 2 −1+n−1 = C(Q1 ) + (2 − 1) + (4 − 1) + · · · + (n − 1) = k −k i=1 = 2n − 2 − log2 n. Die durch Divide-and-Conquer konstruierte Schaltkreisfamilie hat Tiefe log2 n und Größe O(n log n), die Shrink-and-Expand-Familie Tiefe 2 log2 n und Größe O(n). Durch geschicktes Misches ist beides gleichzeitig erreichbar. Induktive Konstruktion von A0n und A1n : KAPITEL 3. SCHALTKREISKONSTRUKTIONEN 54 A0n : zn−1 zn/2 ... zn/2−1 ... A0n/2 A1n/2 wn/2−1 ∗ wn−1 ∗ z0 ... w1 w0 ∗ ... wn−2 wn/2 A1n : zn−1 zn−2 zn−3 zn−4 ∗ ∗ z3 z2 z1 ∗ ... z0 ∗ A0n/2 zn−2 z4 ∗ ... wn−1 wn−2 wn−3 z2 ∗ ∗ w4 w3 w2 w1 w0 Satz 3.1.1 A0n ist ein ∗-Schaltkreis für das parallele Postfixproblem mit Tiefe log2 n und Größe ≤ 4n − 1. Beweis. Betrachten wir zuerst die Tiefe. Sei Dnc die Tiefe von Acn . Es gilt D10 = D11 = 0 D20 = D21 = 1. Bezeichne Dn1∗ die Tiefe der ersten Ausgabe in A1n . Dann gilt für n ≥ 4 D01 = Dn0/2 + 2 Dn0 = max{Dn0/2 , Dn1∗ /2 } + 1 Dn1∗ = 1 + Dn0/2 . KAPITEL 3. SCHALTKREISKONSTRUKTIONEN 55 Die ersten Glieder sind n Dn0 Dn1∗ 1 0 0 2 1 1 4 2 2 8 3 3 16 4 . 4 Offenbar gilt Dn0 = Dn1∗ = log2 n. Für die Größe gelten die Beziehungen C10 = C11 = 0 C20 = C21 = 1 Cn0 = Cn0/2 + Cn1/2 + n 2 Cn1 = Cn0 + n − 1 Einsetzen der Rekursiongleichungen liefert für Cn0 Cn0 = Cn0/4 + ( n2 − 1) + Cn0/2 + n 2 = Cn0/2 + Cn0/4 + n − 1 Man zeigt leicht durch Induktion, daß Cn0 ≤ 4n − 1. Die Anzahl der Gatter für kleine n ist beispielsweise n Cn0 3.1.2 1 0 2 1 4 4 8 12 16 31 32 74 64 . 168 2 Fischer-Ladner-Addierer Jetzt können wir den Schaltkreis A0n benutzen, um schnell und billig die Carry-Bits auszurechnen. Der Fischer-Ladner-Addierer sieht wie folgt aus: Xn−1 Yn−1 Xn−2 Yn−2 HA HA X1 X0 Y1 ... un−1 vn−1 un−2 vn−2 Y0 HA HA u1 v1 u0 v0 c0 d0 A0n mit ◦-Schaltkreisen anstelle von ∗-Gattern cn−1 dn−1 cn−2 dn−2 c1 vn−2 ⊕ sn sn−1 d1 v1 ... ⊕ s1 s0 KAPITEL 3. SCHALTKREISKONSTRUKTIONEN 56 Für die Größe und Tiefe (B2 -Gatter) haben wir C(FLAn ) < 2n + 3 · 4n + n − 1 < 15n D(FLAn ) = 1 + 2 log2 n + 1 = 2 log2 n. Satz 3.1.2 Der Fischer-Ladner-Addierer für n-Bit-Zahlen hat Größe < 15n und Tiefe 2 + 2 log2 n. Kropchenko hat 1970 einen Additions-Schaltkreis angegeben mit Größe √ O(n) (> 15n) und Tiefe log n + O( log n). Subtraktionsschaltkreise erhält man, indem man das Zweierkomplement des Minuenden bildet und anschließend addiert. 3.2 Multiplikationsschaltkreise Gegeben seien zwei n-Bit-Zahlen a = an−1 . . . a0 und b = Bn−1 . . . b0 . Gesucht ist die 2n-Bit-Zahl c, die (c)2 = (a)2 · (b)2 erfüllt. Wie schon zuvor entsprechen a die Variablen Xn−1 , . . . , X0 bzw. b die Variablen Yn−1 , . . . , Y0 . Die Schulmethode besteht darin, n 2n-Bit-Zahlen Zn−1 , . . . Z0 wie folgt zu bilden und dann zu addieren. Zn−1 = 0 Zn−2 = 0 .. . Z0 = 0n Xn−1 Yn−1 Xn−2 Yn−1 ··· X0 Yn−1 0n−1 0 Xn−1 Yn−2 Xn−2 Yn−2 ··· X0 Yn−2 0n−2 .. .. . . Xn−1 Y0 ··· X0 Y0 Die Addition der Zi ist in Baumform möglich. In diesem Baum benötigt man n − 1 ADD2n -Schaltkreise (innere Knoten), z. B. Fischer-Ladner-Addierer. Es ergibt sich Tiefe O((log n)2 ) und Größe O(n2 ). 3.2.1 Wallace-Tree-Multiplizierer Eine andere Möglichkeit ist der sogenannte Wallace-Tree (der allerdings kein Baum ist). Dieser verwendet Carry-Safe-Adder -Bausteine (CSA). Ein CarrySafe-Adder löst dabei folgende Aufgabe: Eingabe: 3 n-Bit-Zahlen a = an−1 . . . a0 b = bn−1 . . . b0 c = cn−1 . . . c0 mit (a)2 + (b)2 + (c)2 < 2n . KAPITEL 3. SCHALTKREISKONSTRUKTIONEN 57 Ausgabe: 2 n-Bit-Zahlen e = en−1 . . . e0 f = fn−1 . . . f1 0 mit (e)2 + (f )2 = (a)2 + (b)2 + (c)2 . Ein CSAn kann leicht aus Volladdierern aufgebaut werden: cn−1 bn−1 an−1 c1 b1 a1 c0 b0 a0 VA VA ... VA fn en−1 f2 e1 f1 = c e0 = s Klar: Tiefe 3, Größe 5n. Man kann jetzt CSA-Schaltkreise nutzen, um zu 2 Zwischenergeb je 3 Zi 2n nissen zusammenzufassen. Wegen (a)2 ·(b)2 = i Zi < 2 ist die Bedingung an die Eingabe für einen CSA2n erfüllt. Zn−1 Zn−2 Zn−3 CSA2n ... ... Z8 Z7 Z6 Z5 Z4 Z3 Z2 Z1 Z0 CSA2n CSA2n CSA2n CSA2n CSA2n .. . CSA2n ADD2n Beispiel: Für n = 8 sieht der Wallace-Tree-Multiplizierer wie folgt aus: KAPITEL 3. SCHALTKREISKONSTRUKTIONEN Z7 Z6 Z4 Z4 Z3 Z2 CSA16 CSA16 CSA16 58 Z1 Z0 CSA16 CSA16 CSA16 ADD16 Analyse Wallace-Tree Da jeder CSA-Baustein die Anzahl der Zwischenergebnisse um 1 reduziert, benötigt man insgesamt n−2 CSA-Bausteine. Für die Gesamtgröße ergibt sich n2 + (n − 2) · 5 · 2n + C(CSAn ) = Xi Yj CSAs · 2n 14 ∈ O(n2 ). Fischer-Ladner Um die Tiefe zu bestimmen, überlegen wir uns, wieviel Zwischenergebnisse ni auf der Stufe i übrig sind: Stufe 0: Stufe i: Stufe l: n0 = n Zahlen n ni−1 benutzt i−1 3 CSA2n -Bausteine, um ni = 2 3 + (ni−1 mod 3) Zwischenergebnisse zu berechnen nl = 2 Zahlen Bevor wir l bestimmen, machen wir noch folgende Beobachtung: ⇒ ni = 2t = 23 ni−1 ni−1 = 3t 2 ni−1 = 3t + 1 ⇒ ni = 2t + 1 = 3 ni−1 ni−1 = 3t + 2 ⇒ ni = 2t + 2 = 23 ni−1 KAPITEL 3. SCHALTKREISKONSTRUKTIONEN 59 n0 = n n1 = 23 n0 ≤ 23 n0 + n2 = 23 n1 2 3 ≤ 23 n1 + 23 2 2 ≤ 23 n0 + 23 + .. . 2 t nt ≤ 3 n0 + 2 3 i 2 3 1≤i≤t t 1 − 23 = 3 n0 + · 1 − 23 t t 2 t = 23 n0 + 2 1 − 23 = 3 (n0 − 2) + 2 2 t 2 3 Wenn nun t > log3/2 n0 = log2/3 nt < 2 log2 3 1 /3 n0 1 n0 ist, gilt (n0 − 2) + 2 = 1 n0 (n0 − 2) + 2 = 2 − 2 n0 < 2, d.h. wir sind fertig. Satz 3.2.1 Wallace-Tree-Multiplizierer haben Größe O(n2 ) und Tiefe ≤ 1 + 3(1 + log3/2 n) ≤ 7.13 log 2 n + O(1). Wir haben jetzt zwar logarithmische Tiefe erreicht, die Schaltkreise haben aber immer noch quadratische Größe. Das kann man mit einem Divide-andConquer-Ansatz verbessern. 3.2.2 Karatsuba-Ofman-Multiplizierer Man zerlegt zunächst X und Y in zwei Teileingaben X , X bzw. Y , Y . X = Xn−1 Xn−2 · · · Xn/2 | Xn/2−1 · · · X0 X X Y = Yn−1 Yn−2 · · · Yn/2 | Yn/2−1 · · · Y0 Y Y KAPITEL 3. SCHALTKREISKONSTRUKTIONEN 60 Das Produkt (X)2 ·(Y )2 kann man durch diese Komponenten ausdrücken: (X)2 · (Y )2 n n = (X )2 · 2 /2 + (X )2 · (Y )2 · 2 /2 + (Y )2 n = (X )2 (Y )2 ·2n + (X )2 (Y )2 + (X )2 (X )2 ·2 /2 + (X )2 (Y )2 A n Bits C n Bits B n + 1 Bits Würde man A, B und C „naiv“ berechnen, so bedeutet dies 4 Multiplikationen und 3 Additionen. Es geht aber besser, indem man zur Berechnung von B die Hilfsgrößen E := (X )2 + (X )2 F := (Y )2 + (Y )2 benutzt, denn es gilt E · F = (X )2 (Y )2 + (X )2 (Y )2 + (X )2 (Y )2 + (X )2 (X )2 =A+C+B und daher B = E · F − (A + C), sodaß man mit insgesamt 3 Multiplikationen und 4 Additionen auskommt. Wieder konstruieren wir MULn rekursiv und benutzen dabei den Teilschaltkreis MULn/2+1 . n = 1: Ein einfaches ∧-Gatter ist ein 1-Bit-Multiplizierer. n = 2k > 1: Der Schaltkreis MULn ist zusammen mit dem darin verwendeten Teilschaltkreis MULn/2+1 in Abbildung 3.1 angegeben. Analyse Karatsuba-Ofman Sei n = 2k . D(MULn ) ≤ D(MULn/2 ) + O(log n) ≤ D(MULn/2 ) + c log2 n .. . n ≤ D(MULn/2k ) + c log k−1 + · · · + log n 2 ⎞ ⎛ log2 (2j )⎠ ≤ 1 + c ⎝k log n − 0≤j<k = 1 + ck log n − c 12 k(k − 1) = 1 + O(k2 ) ∈ O((log n)2 ). KAPITEL 3. SCHALTKREISKONSTRUKTIONEN X X n /2 E /2 MULn/2 Y n n /2 ADDn/2 n A Y n /2 61 /2 F ADDn/2 +1 n /2 +1 E·F MULn/2+1 MULn/2 C n n n+2 ADDn n+1 B 2n SUBn+2 0 n /2 −2 A+C 0 n+2 n /2 ADD2n (a) MULn für n = 2k > 1 E F n n /2 ∧ /2 AND MULn/2 AND n n /2 /2 ADDn/2 n /2 0 0 n n +1 /2 ADDn+1 ∨ n+1 (b) Teilschaltkreis MULn/2 , entspricht naivem Divide-and-ConquerAnsatz Abbildung 3.1: induktive Konstruktion Karatsuba-Ofman-Multiplizierer KAPITEL 3. SCHALTKREISKONSTRUKTIONEN 62 Diese Tiefe ist nicht so schön und wir werden sie später noch verbessern. Für die Größe ergibt sich C(MUL1 ) = 1 C(MULn ) ≤ 3C(MULn/2 ) + cn ≤ 3(3C(MULn/4 ) + c n2 ) + cn = 32 C(MULn/4 ) + c( 32 n + n) .. . i 3 ≤ 3k C(MULn/2k ) + cn 2 0≤i<k = 3k + c · ( 3 )k 2k 3 2 2 −1 = 3k (1 + 2c) − 2cn ∈ O(3k ) = O(2k log2 3 ) = O(nlog2 3 ). Tiefenreduktion durch Radix-4-Darstellung Um die Tiefe der Karatsuba-Ofman-Konstruktion zu verringern, bedient man sich eines Tricks: man benutzt eine redundante Zahlendarstellung, die sogenannte Radix-4-Darstellung (R4). Diese kennt 7 Ziffern, die wie folgt kodiert werden: −3 111 −2 110 −1 101 0 000 1 001 2 010 3 011 Das erste Bit dient als Vorzeichen. Einer Folge von Ziffern ck−1 , . . . , c0 entspricht die Zahl ci 4i . (ck−1 , . . . , c0 )R4 = 0≤i<k Die Darstellung ist nicht eindeutig, z.B. ist (3, −2, 1)R4 = (2, 2, 1)R4 = 41. Fakt 3.2.2 Man kann zwei R4-Zahlen in Tiefe O(1) und Größe O(k) addieren. Um die Summe (ck−1 , . . . , c0 )R4 + (dk−1 , . . . , d0 )R4 = (sk , . . . , s0 )R4 zu bestimmen, bildet man zunächst ti = ci + di ∈ {−6, . . . , 6} und zerlegt dies in ein ui und ein vi : ti ui vi −6 −5 −4 −3 −2 −1 0 1 2 3 4 5 6 −1 −1 −1 −1 0 0 0 0 0 1 1 1 1 −2 −1 0 1 −2 −1 0 1 2 −1 0 1 2 KAPITEL 3. SCHALTKREISKONSTRUKTIONEN 63 Nun gilt s0 = v0 si = vi + ui−1 , 1 ≤ i ≤ k. Wegen |ui | ≤ 1 und |vi | ≤ 2 gilt |si | ≤ 3. Fakt 3.2.3 Multiplikation mit 0,1,2,3 erfordert Größe O(k) und Tiefe O(1) (mehrfache Addition). Fakt 3.2.4 Multiplikation mit 4j ist „kostenlos“ (3j konstante 0-Gatter). Fakt 3.2.5 Die Umwandlung von Binärdarstellung in R4-Darstellung benötigt Tiefe 0 (führendes 0-Bit). Fakt 3.2.6 Die Umwandlung von R4-Darstellung in Binärdarstellung benötigt Tiefe O(k) und Größe O(k). Sei (ck−1 , . . . , c0 )R4 die zu konvertierende Zahl. Dann berechne ci ci ≥ 0, c+ i := 0 sonst −ci ci < 0, c− i := 0 sonst und wandle (kostenlos) diese in 2k-Bit-Binärzahlen c+ , c− um. Dann ist c+ − c− die gesuchte Binärdarstellung. Ein Problem ergibt sich aus der Nichteindeutigkeit der R4-Darstellung: Eine R4-Zahl kann sehr lang sein, obwohl ihr Wert sehr klein ist. Z.B. ist (1, −3, −3, −3)R4 = 1 = (1)R4 . Das folgende Lemma besagt, daß eine lokale Überprüfung das Zurückschneiden fast auf die notwendigen Ziffern erlaubt. Lemma 3.2.7 Sei c = (cn , . . . , c0 )R4 mit −(4n−1 − 1) ≤ c ≤ 4n−1 − 1, also c mit n − 1 Ziffern (bn−2 , . . . , b0 )R4 darstellbar. Dann ist cn = 0 oder cn ∈ {1, −1} ∧ cn cn−1 < 0, d.h. auch (0, cn−1 + 4cn , cn−2 , . . . , c0 )R4 stellt c dar. Beweis. Sei z.B. |cn | ≥ 2. ci 4 i | |a| = |cn 4n + 0≤i<n ≥ |cn |4 − n |ci |4i 0≤i<n n ≥ 2 · 4 − (4 − 1) > 4n im Widerspruch zur Voraussetzung. n Analog widerlegt man cn = 0 ∧ cn cn−1 ≥ 0. 2 KAPITEL 3. SCHALTKREISKONSTRUKTIONEN 64 Wir können jetzt einen Karatsuba-Ofman-Multiplizierer bauen, der R4Arithmetik verwendet. Es stellt sich heraus, daß darin außer MULn/2 nur O(n) Gatter mit Tiefe O(1) vorkommen. Als Tiefe ergibt sich insgesamt Tiefe O(log n) sowie Größe O(n1.57 ) wie vorher. x y x n/2 <4n/2 n/2 <4n/2 ADDn/2 n/2 <4n/2 n/2 <4n/2 ADDn/2 n/2+1 <2·4n/2 MULn/2 y n/2+1 <2·4n/2 MULn/2+1 MULn/2 n+1 <4n n+1 <4n n+2 <4n+1 ADDn+1 n+2 <2·4n SUBn+2 n+2 <4n+1 ADD2n+2 2n+1 <42n Satz 3.2.8 (Schönhage, Strassen) Es gibt Multiplikationsschaltkreise mit Größe O(n log n · log log n) und Tiefe O(log n). 3.3 Divisionsschaltkreise Geht man naiv, d.h. mit der Schulmethode, an die Berechung von (XN −1 , XN −2 , . . . , X0 )2 : (Yn−1 , Yn−2 , . . . , Y0 )2 heran (der Quotient sei ganzzahlig), so benötigt man N − n Runden aus Vergleich und Subtraktion, was auf eine Tiefe von O((N − n) log n) hinausläuft, was natürlich schlecht ist. KAPITEL 3. SCHALTKREISKONSTRUKTIONEN 3.3.1 65 Newtonmethode Als Eingabe sei eine Zahl durch ihre normalisierte Mantisse z, d.h. durch z = 0.1z2 · · · zn mit 1 2 ≤ (z)2 < 1 gegeben. Wir wollen nun mit Hilfe der Newtonmethode eine Approximation an 1z , 1 < 1z ≤ 2 gewinnen, d.h. die Nullstelle von f (x) = x1 − z im Intervall (1, 2]. Die Newton-Iteration hat dann die Form y0 := 1 yi+1 := yi − f (yi ) = 2yi − zyi2 . f (yi ) 2 z 1 1/x z 1 N 2 1/x − z Lemma 3.3.1 Die Iteration konvergiert monoton gegen die Nullstelle N , d.h. 1 ≤ y0 ≤ y1 ≤ · · · ≤ N und lim yi = N. i→∞ Beweis. Monotonie: 1 ≤ y0 < N . Induktion: Sei 1 ≤ yi < N . Aus yi < N = zyi < 1. Dann ist yi+1 = 2yi − zyi2 = yi (2 − zyi ) > yi . 1 z folgt >1 Konvergenz: Zunächst ist yi+1 < 1 z = N wegen zyi+1 = 2zyi − z 2 yi2 = 2X − X 2 mit X = zyi < 1 < 1, d.h. N ist eine obere Schranke für (yn )n≥1 . Aus der Analysis folgt dann, daß y = lim yi i→∞ existiert. Wegen y = 2y − zy 2 gilt y = 1 z = N. 2 KAPITEL 3. SCHALTKREISKONSTRUKTIONEN 66 Nun überliegen wir uns, wie schnell die Iteration konvergiert. Sei dazu der Fehler in der i-ten Runde 1 z i := − yi . Dann ergibt sich für die ersten Fehler 1 z 1 z 0 = 1 = −1>0 − (2 − z) = 1 z +z−2 ≤ 1 2 und für i+1 i+1 = = = = 1 z 1 z 1 z 1 z − yi+1 − 2yi + zyi2 − 2( 1z − i ) + z( 1z − i )2 − 2 z + 2i + 1 z − 2i + z2i = z2i < 2i . (3.1) ( Allgemein ist damit i < 2−2 i−1) , d.h. die Anzahl der korrekten Bits verdoppelt sich in jeder Runde. Für k := log2 n + 1 wird der Fehler in der k-ten Runde kleiner als 2−n : k < 2−2 k−1 ≤ 2−n , wir haben also n gültige Ziffern. Abschneiden nach der n-ten Ziffer liefert einen Fehler ≤ 2n−1 . Problematisch ist die Bitlänge der Zwischenergebnisse, die sich aufgrund des Quadrierens in der Iteration jede Runde annähernd verdoppelt. Runde Bitlänge 1 n 2 3n 3 7n ··· ··· (2k k − 1)n In der k-ten Runde sind dann ca. n2 Bits entstanden, sodaß Multiplizierer für n2 Bits verwendet werden müßten. Abhilfe bietet das Abrunden auf 2n Bits mittels der Funktion round2n . Neue Rekursion: ŷ0 := 1 ŷi := round2n (2ŷi − z ŷi2 ) In k Runden werden dann 2k Multiplikationen von 2n-Bit-Zahlen ausgeführt, was Größe O(kM (2n)) bedeutet, wobei M (n) die Multiplizierer-Größe ist. KAPITEL 3. SCHALTKREISKONSTRUKTIONEN 67 Fehlerbetrachtung ˆi := 1 z − ŷi , i ≥ 0. Man sieht sofort: 0 = ˆ 1 = ˆ 1 z 1 z − ŷ0 = − ŷ1 = 1 z 1 z −1>0 − (2 − z) ≤ 12 . Behauptung 3.3.2 Für 0 ≤ i ≤ log2 n gilt ˆ2i+1 ≤ 2−2 . i Beweis. Induktion über i: i = 0: ˆ1 ≤ 1 2 0 = 2−2 1 ≤ i ≤ log n − 1: 2 2(i+1)+1 < ˆ2(i+1) + 2−2n wegen (3.1) und Rundung ˆ 2 2 < (ˆ 2i+1 ) + 2−2n + 2−2n = (ˆ 2i+1 )4 + 2(ˆ 2i+1 )2 · 2−2n + 2−4n + 2−2n IV i 4 i 2 ≤ 2−2 + 2 2−2 · 2−2n + 2−4n + 2−2n Wegen i ≤ log n − 1 ist i ≤ log n und es folgt 2i ≤ n ⇒ 22 ≤ 2n ⇒ 2−2 ≥ 2−n . i i Damit gilt mit der letzten obigen Zeile i 4 i 2 ˆ2(i+1)+1 ≤ 2−2 + 2 2−2 · 2−2n + 2−4n + 2−2n i 4 i 2 i 2 i 4 i 2 ≤ 2−2 + 2 2−2 · 2−2 + 2−2 + 2−2 i i 3 i 3 i 3 i 2−2 + 2 2−2 + 2−2 + 2−2 = 2−2 1 2 Nach k = 2 log n + 1 Runden gilt: (k−1)/2 ˆk < 2−2 < 2−n , abrunden auf n Stellen liefert also einen guten Näherungswert. Der entsprechende Schaltkreis hat Größe O(M (2n) log n) und Tiefe O((log n)2 ). KAPITEL 3. SCHALTKREISKONSTRUKTIONEN 3.3.2 68 IBM-Dividierer Dem IBM-Dividierer liegt die Idee der „Division durch Multiplikation“ zugrunde. Zunächst sei x := 1 − z, 0 < x ≤ 12 . Dann gilt offenbar k 1 1 1 + x 1 + x2 1 + x2 1 = ·1= · · · · · · · z 1−x 1 − x 1 + x 1 + x2 1 + x2k k (1 + x)(1 + x2 ) · · · (1 + x2 ) = . 1 − x2k+1 Für großes k nähert sich der Nenner immer mehr der 1, sodaß 1 z k ≈ (1 + x)(1 + x2 ) · · · (1 + x2 ). Wir werden sehen, daß k ≈ log2 n genügt, um das Ergebnis auf n Stellen anzunähern. Dafür sind 2k Multiplikationen nötig. Wieder tritt das Problem auf, daß die Zahl der Binärstellen der Zwischenergebnisse zunimmt. Wir werden daher wieder mittels rounds runden (s wird später berechnet). Der folgende Algorithmus ist leicht als Schaltkreis mit 2k s-Bit-Multiplizierern zu realisieren. Algorithmus 3.1: IBM-Dividierer(z) Eingabe: normierte Mantisse z Ausgabe: Näherung Pk∗ für 1z (1) x∗ (0) := 1 − z; P0∗ := 1 + x∗ (0); (2) for j := 1 to k (3) x∗ (j) := rounds (x∗ (j − 1))2 ; ∗ · (1 + x∗ (j)) (4) Pj∗ := rounds Pj−1 (5) return Pk∗ Für die Fehlerbetrachtung sei δ := 2−s und x(j) := x2 . j Lemma 3.3.3 Für alle j, 0 ≤ j ≤ k, gilt x(j) − 2δ ≤ x∗ (j) ≤ x(j). Beweis. Die zweite Ungleichung hält, weil stets abgerundet wird. Die erste beweisen wir durch Induktion. j = 0, 1: x(0) − 2δ = x − 2δ ≤ x = x∗ (0) x(1) − 2δ = x2 − 2δ ≤ x2 − δ ≤ rounds (x2 ) = rounds ((x∗ (0))2 ) = x∗ (1). KAPITEL 3. SCHALTKREISKONSTRUKTIONEN 69 j ≥ 2: x∗ (j + 1) ≥ (x∗ (j))2 − δ IV 2 ≥ (x(j) − 2δ) − δ = x2 (j) − 4δx(j) + 4δ 2 − δ ≥ x2 (j) − δ + 4δ 2 − δ wegen x(j) ≤ ≥ x(j + 1) − 2δ. 1 4 für j ≥ 2 2 Lemma 3.3.4 Seien 1 − x(j) und 1−x Pj := (1 + x(0))(1 + x(1)) · · · (1 + x(j)). j := (3j + 1)δ Dann gilt für j ≥ 0 Pj − j ≤ Pj∗ ≤ Pj . Für den Gesamtfehler gilt 0 ≤ z −1 − Pk∗ = ( 1z − Pk ) + (Pk − Pk∗ ), wobei der erste Summand dem Fehler durch Ignorieren des Zählers und der zweite Summand dem Fehler durch Abrunden entspricht. Wegen 1 z − Pk = = 1 z k+1 − z1 (1 − x2 1 1−x ) 2k+1 x 1 2k+1 ≤2 ≤ 2 ≤ 2−2 k+1 +1 wird der Fehler durch Ignorieren des Zählers für k := log(n + 2) − 1 kleiner als 2−(n+1) . Mit dem letzten Lemma haben wir Pk − Pk∗ ≤ k ≤ (3k + 1)2−s · 2, sodaß für s := n + 4 + log k der Fehler Pk − Pk∗ durch Abrunden ebenfalls kleiner als 2−(n+1) wird. Der Gesamtfehler z1 − Pk∗ ist dann < 2n . Satz 3.3.5 Die IBM-Methode liefert Dividierer der Größe O(M (n) log n) und Tiefe O(log2 n). KAPITEL 3. SCHALTKREISKONSTRUKTIONEN 70 Der IBM-Dividierer ist der Ausgangspunkt für Dividierer-Schaltkreise der Tiefe O(log n) und Größe O(n1+ ) und damit des Nachweises, daß (DIVn )n≥1 in NC1 enthalten ist. Der Haupttrick bei dieser Verbesserung besteht in der Verwendung modularer Arithmetik. Um z.B. das Produkt x · y zu berechnen, ersetzt man x → (x mod p1 , x mod p2 , . . . , x mod pr ) y → (y mod p1 , y mod p2 , . . . , y mod pr ), wobei p1 , p2 , . . . , pr Primzahlen sind. Für q := p1 p2 · · · pr > x bzw. y ist diese Darstellung eindeutig. Wählt man q > xy =: z, so kann man das Produkt z (eindeutig) in dieser Darstellung berechnen: z1 = (x mod p1 )(y mod p1 ) mod p1 z2 = (x mod p2 )(y mod p2 ) mod p2 .. . zr = (x mod pr )(y mod pr ) mod pr . Über zj = z mod pj ist z = xy aus z1 , . . . , zr berechenbar. Der Übergang zur modularen Arithmetik lohnt sich besonders bei mehrfacher Multiplikation, wie sie z.B. bei dem IBM-Dividierer auftritt. 3.4 Schnelle Fourier-Transformation (FFT) Ziel dieses Abschnitts ist es, Schaltkreise zur schnellen Polynommultiplikation zu konstruieren. Definition 3.4.1 Für ein Polynom an−1 xn−1 + · · · + a1 x + a0 heißt der Vektor a = (a0 , a1 , . . . , an−1 ) Koeffizientendarstellung des Polynoms. Das Produkt zweier Polynome p, q mit Koeffizienten a = (a0 , . . . , an−1 ) bzw. b = (b0 , . . . , bn−1 ) ist das Polynom ⎛ ⎞ 2n−2 2n−2 ⎝ ai bj ⎠ xk = ck xk . p(x) · q(x) = k=0 i+j=k k=0 Definition 3.4.2 Der Vektor c = (c0 , . . . , c2n−2 ) heißt Konvolution von a und b, geschrieben c = conv(a, b). Die naive Berechnung der Konvolution benötigt Θ(n2 ) Operationen für die 2n Koeffizienten. Das ist sehr teuer. Anderer Ansatz: Wir stellen ein Polynom p durch n Punkte (xi , yi ) mit yi = p(xi ) dar. KAPITEL 3. SCHALTKREISKONSTRUKTIONEN 71 Lemma 3.4.3 Ein Polynom p ist durch n Punkte (xi , yi )1≤i≤n mit xi = xj für i = j und yi = p(xi ) eindeutig bestimmt. Beweis. Wir betrachten das lineare Gleichungssystem ⎞⎛ ⎞ ⎛ ⎞ ⎛ a0 1 x1 y0 x21 x31 · · · xn−1 1 ⎟ ⎜ a1 ⎟ ⎜ y 1 ⎟ ⎜1 x2 x22 x32 · · · xn−1 2 ⎟⎜ ⎟ ⎜ ⎟ ⎜ ⎟⎜ . ⎟ = ⎜ . ⎟. ⎜ .. .. ⎠ ⎝ .. ⎠ ⎝ .. ⎠ ⎝ . . 1 xn−1 x2n−1 x3n−1 · · · xn−1 an−1 yn−1 n−1 a M y Dieses Gleichungssystem ist genau dann eindeutig lösbar (es bestimmt eindeutig die Koeffizienten a eines Polynoms), wenn det M = 0 ist. Es gilt det M = (xj − xi ) = 0 ⇔ xi = xj ∀i = j. i>j 2 Damit haben wir ein Verfahren zum Berechnen von p · q, wenn p und q durch ihre Koeffizienten gegeben sind: 1. Berechne für 1 ≤ i ≤ 2n die Werte p(xi ) und q(xi ) 2. Berechne Produkte p(xi ) · q(xi ) 3. Berechne aus den Produkten den Koeffizientenvektor von pq Es ergeben sich folgende Fragen: 1. Wie berechnet man 2n Funktionswerte eines Polynoms effizient? 2. Wie erhalte ich aus Punkten Koeffizientenvektor? Wir wenden uns zuerst der Berechnung von 2n Werten zu und betrachten dazu komplexe n-te Einheitswurzeln, d.h. komplexe Lösungen der Gleichung ω n = 1. Eine n-te Einheitswurzel heißt primitiv, falls für alle 1 ≤ k ≤ n − 1 gilt: (ω k )j = 0. 0≤j≤n−1 Intuitiv ist die primitive n-te Einheitswurzel immer die „kleinste“ Einheitswurzel. n=6 i ω2 ω1 ω0 ω3 ω4 ω5 KAPITEL 3. SCHALTKREISKONSTRUKTIONEN 72 Definition 3.4.4 Die Diskrete Fourier-Transformation eines Polynoms p gegeben durch a = (a0 , . . . , an−1 ) ist der Vektor T DFTn (a) = (p(ω n−1 ), . . . , p(ω 1 ), p(ω 0 )) , wobei ω die primitive n-te Einheitswurzel ist. Offenbar: ⎛ 1 ⎜ ⎜1 ⎜ 1 DFTn (a) = ⎜ ⎜ ⎜ .. ⎝. 1 ω ω2 .. . 1 ω2 ω 2·2 .. . ··· ··· ··· 1 ω3 ω 2·3 .. . ⎞⎛ 1 ω n−1 ω 2(n−1) .. . 1 ω n−1 ω 2(n−1) ω 3(n−1) · · · ω (n−1)(n−1) i·j W = (ω )0≤i,j≤n−1 ⎟⎜ ⎟⎜ ⎟⎜ ⎟⎜ ⎟⎜ ⎟⎜ ⎠⎝ a0 a1 a2 .. . ⎞ ⎟ ⎟ ⎟ ⎟. ⎟ ⎟ ⎠ an−1 Satz 3.4.5 DFTn (a) kann durch einen Schaltkreis über {+, ·, −} in Größe O(n log n) und Tiefe O(log n) berechnet werden. Beweis. Wir konstruieren den Schaltkreis zur Berechnung von p(ω j ) induktiv. n = 2: Berechne p(ω j ) = a0 + a1 ω j für j = 0, 1. n = 2k > 2: Man kann p(ω j ) wie folgt umschreiben: p(ω j ) = a0 + a1 ω j + a2 (ω j )2 + · · · + an−1 (ω j )n−1 = a0 + a2 (ω 2 )j + a4 (ω 2 )2j + · · · + an−2 (ω 2 )( 2 −1)j n + ω j a1 + a3 (ω 2 )j + a5 (ω 2 )2j + · · · + an−1 (ω 2 )( 2 −1)j . n Da ω 2 eine wenden. n 2 -te primitive Einheitswurzel ist, können wir Divide&Conquer ver- an−1 . . . an−2 . . . a5 a3 a1 DFTjn/2 a4 a2 a0 DFTjn/2 ωj · + p(ω j ) Analyse zeigt: D(DFTn ) = D(DFTn/2 ) + 2 = 2 log n C(DFT2 ) = 2 C(DFTn ) = 2C(DFTn/2 ) + 2n = 4n log n. KAPITEL 3. SCHALTKREISKONSTRUKTIONEN 73 Analoge Schaltkreise können für allgemeine DFT verwendet werden, d.h. die Schaltkreise sind nicht davon abhängig, daß ω primitive Einheitswurzel ist. 2 Wie berechnen wir nun aus n Punkten die Koeffizienten des Polynoms? Wir haben schon in Lemma 3.4.3 gesehen, daß das Polynom eindeutig durch die n Punkte bestimmt ist. Dies liegt an der eindeutigen Lösbarkeit von W a = y, wobei W die „Stellen“ enthält, an denen das Polynom ausgewertet wird und y die entsprechen Werte. Wenn W nun (einfach!) invertierbar ist, kann man die Koeffizienten a über a = W −1 y berechnen. Satz 3.4.6 W −1 ist die folgende Matrix W −1 = n−1 w−ij 0≤i,j≤n−1 . Beweis. Wir zeigen I = W W −1 =: (zij )0≤i,j≤n−1 . Multiplikation der Matrizen liefert ω ik ω −kj . zij = n−1 0≤k≤n−1 Fallunterscheidung: i = j: zii = n−1 1 = n−1 n = 1 0≤k≤n−1 i = j, i > j: zij = n−1 0≤k≤n−1 k(i−j) ω =0 0 (primitive EW) i = j, i < j: ω −1 ist auch primitive Einheitswurzel ⇒ zij = 0 Damit ist gezeigt: W W −1 = I. 2 Nun gilt offenbar W −1 y = a ⇔ n1 (ω −ij )0≤i,j≤n−1y = a. Damit ist DFT−1 n (y) mit einem ähnlichen Schaltkreis berechenbar wie schon DFTn (a). KAPITEL 3. SCHALTKREISKONSTRUKTIONEN yn−1 ... y1 74 y0 DFTn (y) mit ω −1 als Einheitswurzel · n1 an−1 ... a1 a0 Fazit: Sind p, q Polynome, die durch (a0 , . . . , an−1 ) und (b0 , . . . , bn−1 ) gegeben sind, so erhalten wir: conv(a, b) = DFT−1 2n DFT2n (a0 , . . . , an−1 , 0, . . . , 0) DFT2n (b0 , . . . , bn−1 , 0, . . . , 0) wobei das komponentenweise Produkt bezeichnet. Bemerkung 1. Wir sind davon ausgegegangen, daß die Gatter mit komplexen Zahlen umgehen können. In Wirklichkeit treten Rundungsfehler auf. 2. Will man genau rechnen, z.B. bei ganzzahligen Koeffizienten, muß man Einheitswurzeln in geeignetem Zm finden. Fakt 3.4.7 Wenn n und ω = 1 Zweierpotenzen sind, dann ist ω prin mitive Einheitswurzel in Zm , m = ω /2 +1, und ω −1 und n−1 existieren. Satz 3.4.8 Polynommultiplikation ist mittels DFT mit O(n log n) Gattern und Tiefe O(log n) möglich. Kapitel 4 OBDDs: Eine effiziente Datenstruktur für Boolesche Funktionen 4.1 Ordered Binary Decision Diagrams Beispiel: binäres Entscheidungsdiagramm (BDD; synonym auch binärer Entscheidungsgraph, Branching Program) X1 X1 0 1 X2 0 0 1 0 1 0 X4 0 1 0 X2 1 1 X4 1 0 X3 X4 X2 1 1 X2 X3 1 0 1 0 0 0 X4 1 0 0 1 1 Weg ohne Eingabe Weg zur Eingabe 0110 Weg zur Eingabe 1000 Jedem Input entspricht ein Weg von einem Startknoten zu einer der beiden Senken (0 bzw. 1). Aber: Es gibt auch graphentheoretische Wege ohne Input. Dies ist eine prinzipielle Schwierigkeit bei BDDs. Definition 4.1.1 Ein Branching Program (BP) oder Binary Decision Diagram (BDD) ist ein gerichteter, azyklischer Graph mit Knoten- und Kanten75 KAPITEL 4. OBDDS 76 markierungen wie folgt: 1. Es gibt ein oder zwei Senken (Knoten vom Ausgrad 0). Sind zwei Senken vorhanden, so ist eine mit 0 und die andere mit 1 markiert. Bei nur einer Senke ist diese mit 0 oder 1 markiert. Der 0-Senke v0 ist die Nullfunktion fv0 ≡ 0 zugeordnet, der 1-Senke v1 die 1-Funktion fv1 ≡ 1. 2. Wenn v keine Senke ist, führen aus v genau 2 Kanten heraus, die mit 0 und 1 markiert sind (die Nachfolger heißen 0-Nachfolger bzw. 1Nachfolger ). Außerdem ist v mit einer Variable Xi markiert. Seien u der 0-Nachfolger und w der 1-Nachfolger von v. Dann gehört zu v die Funktion fv = Xi fu + Xi fw . 3. Ein oder mehrere Knoten sind mit Startmarkierungen s1 , . . . , st versehen. Vom Knoten v mit Markierung sv wird dann die Funktion fsv = fv berechnet. Ist ein konkretes BDD G und eine Eingabe a1 · · · an gegeben, so kann die Funktion fsv in G folgendermaßen ausgewertet werden: Algorithmus 4.1: EvalBDD(G,sr ,a1 · · · an ) Eingabe: BDD G, Startmarkierung sr , Eingabe a1 · · · an Ausgabe: fsr (a1 · · · an ) (1) vaktuell := sr (2) while vaktuell keine Senke (3) vaktuell sei mit Xi markiert (4) vaktuell := ai -Nachfolger von vaktuell (5) return Markierung c von vaktuell Beispiel: Im vorigen Beispiel werden an den einzelnen Knoten die folgenden Funktionen berechnet: fv0 ≡ 0, fv1 ≡ 1 fv2 = X4 fv1 + X4 fv0 = X4 fv3 = X4 fv4 = X2 fv2 = X2 X4 fv5 = X3 X2 X4 fv6 = X2 X4 + X2 X3 X4 fv7 = X1 (X2 X4 + X2 X3 X4 ) + X1 X2 X3 X4 = X1 X2 X4 + X1 X2 X3 X4 + X1 X2 X3 X4 = fStart . KAPITEL 4. OBDDS 77 Offenbar entspricht jeder Term einem Weg zur 1-Senke. Allgemein gilt Xiai , fs = w Weg von s zu 1-Senke w enthält ai -Kante aus Xi Knoten wobei Xi0 = Xi und Xi1 = Xi vereinbart seien. Bemerkung In der Darstellung von BDDs werden wir oft der Übersichtlichkeit wegen mehrere 0- bzw. 1-Senken benutzen. Alle 0- bzw. 1-Senken sind aber als identisch anzusehen. Ebenso werden wir Senken bei der Anzahl der Knoten eines BDD nicht berücksichtigen, da es stets höchstens zwei sind. Variablenordnungen Wir haben im Einführungsbeispiel gesehen, daß in BDDs Wege auftreten können, die keiner Eingabe entsprechen. Beim genaueren Hinsehen zeigt sich als Ursache dafür, daß es Wege gibt, die zwei mit X2 markierte Konten enthalten und man an beiden Knoten entgegengesetzte Werte für a2 wählen kann. Das ist bei einer Eingabe natürlich nicht möglich. Um solche Effekte zu vermeiden, führen wir Variablenordnungen ein. Eine Variablenordnung legt fest, in welcher Reihenfolge die auftretenden Variablen „befragt“ werden. Insbesondere darf eine Variable höchstens einmal auf einem Weg auftreten. Formal ist eine Variablenordnung eine Permutation π : {1, . . . , n} → {1, . . . , n}. Es gilt dann vereinbarungsgemäß: Xi wird vor Xj ausgewertet ⇔ π(i) < π(j). Das entspricht der Reihenfolge Xπ−1 (1) , . . . , Xπ−1 (n) . Beispiel: Zu der Permutation 1 2 3 4 5 2 4 5 3 1 π= gehört die Auswerte-Reihenfolge X5 , X1 , X4 , X2 , X3 . X5 0 X4 0 0 X2 0 1 0 0 1 X3 X1 0 X2 0 Weg X5 , X1 , X4 Weg X5 , X4 , X2 , X3 1 1 1 0 X4 1 1 1 1 0 1 X2 1 0 KAPITEL 4. OBDDS 78 Ein BDD muß zu einer Variablenordnung passen, damit die Auswertung gemäß der Variablenordnung möglich ist. Definition 4.1.2 1. Ein BDD G heißt π-OBDD (Ordered Binary Decision Diagram) zu einer Variablenordnung π, wenn es existiert eine Kante von einem Xi -Knoten zu einem Xj -Knoten ⇒ π(i) < π(j). 2. Ein BDD G heißt OBDD, wenn eine Variablenordnung π existiert, für die G ein π-OBDD ist. Bemerkung Sei G ein π-OBDD. 1. Auf jedem Weg in G kommt jede Variable höchstens einmal vor. Damit ist das Erfüllbarkeitsproblem in G einfach lösbar: ∃a ∈ {0, 1}n : G auf a liefert 1 ⇔ es existiert ein Weg in G von Start zur 1-Senke. 2. Man kann ein π-OBDD in n + 1 Schichten teilen, wobei in der Schicht i nur Knoten mit Markierung Xπ−1 (i) und nur Kanten von Schicht i in Schicht i > i auftreten. 3. Wir wählen meist die Anordnung bzw. Variablenordnung X1 , . . . , Xn . Satz 4.1.3 In einem π-OBDD G sei v ein Xi -Knoten und u bzw. w sein 0bzw. 1-Nachfolger. Dann gilt: fu = fv |Xi =0 fw = fv |Xi =1 , und d.h. fv = Xi fu + Xi fw ist die Shannon-Zerlegung. Beweis. Sei a = a1 · · · an eine beliebige Eingabe und ferner a0 := a1 · · · ai−1 0ai+1 · · · an a1 := a1 · · · ai−1 1ai+1 · · · an . Dann: fu (a) = fu (a0 ) 0 = fv (a ) = fv (a)|Xi =0 (a). Analog für fw . (unter u wird Xi nicht gefragt) (Auswertung OBDDs) 2 KAPITEL 4. OBDDS 79 Bemerkung Der letzte Satz gilt nicht notwendig in BDDs, die keine πOBDDs sind. v Xi 0 u 1 w fw hängt von Xi ab! Xi Beispiel: (π beeinflußt Größe) Betrachten wir die Funktion f (a1 a2 a3 b1 b2 b3 ) = 1 ai = bi 0 sonst. Die Variablen X1 , . . . , Xn gehören zu a, Y1 , . . . , Yn zu b. Variablenordnung X1 , X2 , X3 , Y1 , Y2 , Y3 : X1 0 X2 0 1 0 X3 0 Y1 0 0 Y2 0 1 Knotenzahl: allgemein: vollständiger Binärbaum 1 1 X3 0 0 0 Y3 X2 1 1 0 1 Y1 0 1 0 Y2 0 1 0 1 1 0 Y3 1 1 3·8+7 n2n + 2n − 1 (bei dieser Variablenordnung optimal!) 0 KAPITEL 4. OBDDS 80 Variablenordnung X1 , Y1 , X2 , Y2 , X3 , Y3 : X1 0 Y1 1 0 Y2 0 Y3 1 0 Knotenzahl: allgemein: X2 X3 1 0 Y2 0 0 1 1 0 0 1 1 0 0 Y1 1 0 0 1 1 Y3 0 0 9 3n Satz 4.1.4 Sei f ∈ Bn beliebige Boolesche Funktion und π eine beliebige Variablenordnung. Dann existiert ein π-OBDD für f . Beweis. Wir konstruieren das π-OBDD als vollständigen Binärbaum, in dem ein Weg für jeden Input vorkommt und in jeder Schicht i die Variable Xπ−1 (i) befragt wird: Xπ−1 (1) a1 Xπ−1 (2) Xπ−1 (2) vollständiger Binärbaum a = a1 · · · an f (a) 2 Definition 4.1.5 Eine Funktion f ∈ Bn heißt symmetrisch, wenn sie sich schreiben läßt als f (a1 , . . . , an ) = g(a1 + · · · + an ). Bei symmetrischen Funktionen spielt die Variablenreihenfolge keine Rolle. Z.B. kann jede symmetrische Funktion f ∈ B4 mit folgendem „StandardOBDD“ dargestellt werden, wobei die Indexreihenfolge der Variablen offenbar egal ist: KAPITEL 4. OBDDS 81 X1 0 X2 0 X3 0 0 X4 1 g(0) 1 0 1 1 1 g(1) X2 0 X3 0 X4 1 0 1 X3 0 X4 1 g(2) 1 0 g(3) X4 1 g(4) a1 + a2 + a3 = 1 Als Beispiel für eine symmetrische Funktion betrachten wir die in der Praxis wichtige Majority-Funktion (Mehrheitsentscheid): 1 a1 + · · · an ≥ n2 MAJn (a1 · · · an ) = 0 sonst. X1 0 X2 0 0 X3 0 0 0 4.2 1 1 X4 X2 0 X3 0 1 1 1 1 1 1 1 Minimierung und Reduktion Wir werden in diesem Abschnitt einen Algorithmus erarbeiten, der ein gegebenes π-OBDD vereinfacht und ein äquivalentes, kleineres π-OBDD berechnet. Formal: Eingabe: π-OBDD G, das Funktion fG (oder auch mehrere) berechnet Ausgabe: π-OBDD G mit möglichst kleiner Knotenzahl für dieselbe(n) Funktion(en) Zur Vereinfachung der Notation setzen wir π = id. Reduktionsregeln R0 Erreichbarkeitsregel Unerreichbare (von keinem Startknoten erreichbare) Knoten werden weggelassen (leicht per Breitensuche von Startknoten zu erreichen). Wir können also annehmen, daß alle Knoten erreichbar sind. KAPITEL 4. OBDDS 82 R1 Eliminationsregel k 1 ··· 0 k 1 sj Xi v ··· ⇒ 1 sj u u=w Wenn für einen Knoten v der 0-Nachfolger u und 1-Nachfolger w identisch sind, dann 1. lenke Kanten auf v auf u = w um 2. übertrage Startmarkierungen von v auf u 3. lösche v. R2 Verschmelzungsregel k1 1 ··· sj1 Xi v1 0 u 1 k1 + 1 k2 ··· sj2 Xi v2 0 1 1 ··· sj1 , sj2 Xi v 0 ⇒ w k2 u 1 w Wenn v1 , v2 dieselbe Markierung Xi haben und jeweils 0-Nachfolger von v1 und 0-Nachfolger von v2 bzw. 1-Nachfolger von v1 und 1-Nachfolger von v2 identisch sind, dann verschmelze v1 , v2 zu einem neuen Knoten v und übertrage auf diesen die Kanten und Startmarkierungen von v1 und v2 . Klar: R0, R1, R2 ändern die berechnete Funktion nicht. Beispiel: In Abbildung 4.1 ist die Wirkung der Regeln an einem BesipielOBDD gezeigt. Im letzten OBDD ist keine Regel anwendbar und es stellt sich die Frage, ob dieses OBDD minimal ist. KAPITEL 4. OBDDS 83 s X1 0 X2 0 0 X3 1 1 0 0 1 0 1 X2 0 X3 1 0 0 0 R2 X3 1 1 0 0 1 X3 1 0 R2 (a) ursprüngliches OBDD R2 0 s X1 s X1 1 0 X2 1 R1 X2 0 1 1 0 X2 1 0 0 0 1 X3 0 1 0 0 0 1 (b) erster Reduktionsschritt (c) zweiter onsschritt s X 2 X3 1 0 Redukti- 1 0 0 0 1 X3 1 0 (d) reduziertes OBDD Abbildung 4.1: Aus dem ursprünglichen OBDD ensteht durch Anwendung der Regel R2 an den beiden markierten Stellen das OBDD in 4.1(b). Weitere Reduktion führt zu 4.1(c) und schließlich zu einem OBDD, das nicht mehr reduzierbar ist (keine Regel anwendbar). KAPITEL 4. OBDDS 84 Ab hier betrachten wir nur π-OBDDs, die nur eine Funktion berechnen, d.h. nur einen Startknoten haben (mehrere Startknoten analog). Unser Ziel ist es, zu zeigen, daß die Regeln ein π-OBDD mit minimaler Knotenzahl liefern. Im folgenden sei G ein festes π-OBDD. Wir konstruieren ein abstraktes, zu G äquivalentes π-OBDD, von dem wir zeigen, daß es eindeutig bestimmt und minimal ist. Wir wollen ein π-OBDD für f := fG ∈ Bn erhalten. Die Idee ist nun, f variablenweise gemäß π auszuwerten. Dabei entstehen Subfunktionen, die von den bereits ausgewerteten Variablen nicht mehr abhängen. f hat die Subfunktionen (bzgl. π = id) fa1 ···ai (c1 · · · cn ) := f (a1 · · · ai ci+1 · · · cn ) für 0 ≤ i ≤ n, a1 · · · ai ∈ {0, 1}i . Wir betrachten die Menge F := {fa1 ···ai | 0 ≤ i ≤ n, a1 · · · ai ∈ {0, 1}i } ⊆ Bn , die uns als Knotenmenge für unser abstraktes π-OBDD dienen wird. Dazu müssen natürlich auch die „Senken“ (konstante Subfunktionen) in F enthalten sein; es gilt 0-Funktion ∈ F ⇔ f ≡ 1, wegen fa1 ···an ≡ f (a1 · · · an ) (analog für die 1-Funktion). Außerdem ist der „Startknoten“ f() = fa1 ···a0 = f in F. Wir können jetzt die Knotenbeschriftung angeben. 0-Funktion 1-Funktion g ∈ F, g ≡ c 0-Senke 1-Senke kleinstes i (bzgl. π), sodaß g von Xi abhängt Außerdem erhält f die Startmarkierung s. Nun benötigen wir noch die Kantenmenge EF . Betrachten wir die Subfunktion g = fa1 ···ai−1 , die mit Xj markiert sei. Dann ist der 0-Nachfolger von g fa1 ···ai−1 0···0 0 j−i und der 1-Nachfolger fa1 ···ai−1 0···0 1 , j−i wobei die j − i Nullen die Variablen „überspringen“, von denen g nicht abhängt. (Ebenso kann man natürlich beliebige j − i Bits benutzen, weil alle diese Funktionen identisch sind.) Lemma 4.2.1 Das π-OBDD GF = (F, EF ) berechnet dieselbe Funktion f wie das ursprüngliche π-OBDD G. KAPITEL 4. OBDDS 85 Beweis. Man zeigt mittels vollständiger Induktion über die Schichten n + 1, n, n − 1, . . . , 1, daß jeder Knoten g ∈ F die Funktion g berechnet. 2 Das folgende Lemma ermöglicht es, die Größe des abstrakten π-OBDD mit anderen π-OBDD für fG zu vergleichen. Lemma 4.2.2 Sei G = (V, E) ein beliebiges π-OBDD für f . Dann existiert eine Abbildung φ : F → V, g → φ(g) mit 1. g ist nicht konstant: g und φ(g) sind mit derselben Variable beschriftet; φ(g) hat zwei verschiedene Nachfolger und φ(g) berechnet g 2. g ≡ c ist konstant: φ(g) ist eine c-Senke 3. φ ist injektiv. Beweis. Sei g = fa1 ···ai−1 . OBdA hängt g von Xi ab oder es ist i = n + 1 und g ist konstant. 1. Fall: g nicht konstant In G führt der Pfad a1 · · · ai−1 zu dem Knoten v, der mit Xj markiert ist. Weil G ein π-OBDD ist, gilt j ≥ i. Dann gilt für beliebige Eingabe c1 · · · cn fv (c1 · · · cn ) = f (a1 · · · ai−1 ci · · · cn ) erreicht v = fa1 ···ai−1 (c1 · · · cn ) = g(c1 · · · cn ). Also hängt fv = g von Xi ab, d.h. j > i ist unmöglich. Der Knoten v ist daher mit Xi beschriftet und hat verschiedene 0- und 1-Nachfolger, womit 1. gezeigt ist. 2. Fall: g ≡ c ∈ {0, 1} Wegen g = fa1 ···an und weil G f berechnet, führt der Weg a1 · · · an in G zu einer c-Senke. Wir können setzen: φ(g) := c-Senke. Noch zu zeigen ist 3.: Sei v := φ(fa1 ···ai ) = φ(fa1 ···ak ) =: v . Wir wissen aus 1. und 2., daß v fa1 ···ai und v fa1 ···ak berechnet. Da die beiden Knoten gleich sind, folgt fa1 ···ai = fa1 ···ak und damit die Injektivität. 2 Satz 4.2.3 Zu jedem π-OBDD G existiert ein eindeutig bestimmtes π-OBDD G mit minimaler Knotenzahl und fG = fG . KAPITEL 4. OBDDS 86 Beweis. Zunächst folgt aus Lemma 4.2.2, daß für jedes π-OBDD G = (E , V ) mit fG = fG gilt: |F | ≤ |E | (Injektivität von φ), d.h. jedes π-OBDD für fG hat mindestens |F | Knoten. Betrachte nun G := GF . Da G wegen Lemma 4.2.1 äquivalent zu G ist und außerdem minimale Knotenzahl hat, ist G ein minimales π-OBDD für fG . Für ein minimales π-OBDD ist φ eine Bijektion, ja sogar ein Isomorphismus. Alle minimalen π-OBDDs sind isomorph, das minmale π-OBDD ist also bis auf Isomorphie eindeutig. 2 Wird nun durch wiederholtes Anwenden der Regeln R1 und R2 ein minimales π-OBDD konstruiert? Satz 4.2.4 Ist in π-OBDD G mit Startknoten s keine der Regeln R0, R1 oder R2 anwendbar, dann ist G isomorph zu kleinstem π-OBDD für fG . Beweis. Sei G = (V, E). Der Beweis beruht auf der „Induktionsbehauptung“ v, w Knoten in G, fv = fg ⇒ v = w (4.1) (in einem reduzierten π-OBDD berechnen verschiedene Knoten verschiedene Funktionen). Zunächst überlegen wir uns, daß aus (4.1) |V | = |F | folgt. Die Abbildung φ aus Lemma 4.2.2 soll also nicht nur injektiv, sondern auch surjektiv sein. Sei v ∈ V beliebiger Knoten, mit Xj markiert. Dann führt ein Weg in G zu v mit Variablenbelegung a1 , . . . , aj−1 für X1 , . . . , Xj−1 . Sei g := fa1 ···aj−1 ∈ F und w := φ(g) das Bild von g in G. Dann ist wegen Lemma 4.2.2 fw = g. Andererseits berechnet v die Funktion fv = fa1 ···aj−1 = g, sodaß fv = fw folgt. Mit (4.1) ist w = v und dann v ∈ Bild(φ). Aus (4.1) folgt also die Surjektivität von φ. Wir beweisen nun (4.1) durch Induktion über r = min{k, l} mit k = level(v), l = level(w), wobei level(v) := n+1 j≤n v Senke v mit Xj markiert. Induktionsanfang: r = n + 1, k = l = n + 1 v und w sind Senken. Aus fv = fw ≡ c folgt v = w, da die beiden Knoten dann identische Senken sind. Induktionsannahme: Induktionsbehauptung (4.1) gilt für alle v , w mit min{level(v ), level(w )} ≥ r + 1. Induktionsschritt: Es ist zu zeigen: fv = fw und r = min{level(v), level(w)} ⇒ v = w. OBdA können wir r = k ≤ l, r ≤ n annehmen. KAPITEL 4. OBDDS 87 Wir wissen, daß der 0-Nachfolger v0 und der 1-Nachfolger v1 von v verschieden sein müssen, da sonst R1 anwendbar wäre. Wegen level(v0 ), level(v1 ) ≥ k + 1 ist auf v0 , v1 die Induktionsbehauptung anwendbar, d.h. fv0 ≡ fv1 . Also hängt fv von Xk ab, wegen fv = fw ist w daher keine Senke. Dieselbe Überlegung für w liefert fw0 ≡ fw1 und fw hängt von Xl ab. Wir können folgern fv = fw , k ≤ l, fv hängt von Xk ab ⇒ fw hängt auch von Xk ab ⇒l≤k ⇒ l = k, außerdem gilt fv0 = fv |Xk =0 = fw |Xk =0 = fw0 , level(v0 ), level(w0 ) ≥ k + 1, d.h. die Induktionsvoraussetzung liefert v0 = w0 . Analog: v1 = w1 . Da R2 nach Voraussetzung nicht anwendbar ist, muß v = w gelten. 2 Wir haben also mit den Reduktionsregeln ein Verfahren, mit dem man π-OBDDs in äquivalente minimale π-OBDDs überführen kann. 4.3 4.3.1 Effiziente Algorithmen für OBDD-Operationen OBDD-Minimierung Satz 4.3.1 Es existiert ein Algorithmus, der zu einem π-OBDD G in Zeit O(|G|) das reduzierte π-OBDD G minimaler Größe berechnet. Beweisskizze. Zunächst benötigen wir eine passende Datenstruktur; wir repräsentieren einen Knoten v ∈ V gemäß dem Schema: 0-Vorgänger v2 v1 Xj p: lfdNr j 1-Vorgänger-Liste u 0-Nachfolger w 1-Nachfolger Die Senken haben dann den Aufbau Senke 0-Vorgänger-Liste n+1 c ∈ {0, 1} 1-Vorgänger-Liste KAPITEL 4. OBDDS 88 Der Algorithmus arbeitet nun wie folgt: 1. Aufbau der Vorgängerlisten: O(|G|) (Kernidee: in Schichten von unten nach oben arbeiten) 2. Bilde Listen L1 , . . . , Ln der Knoten auf Level j; Ln+1 enthält die beiden Senken 3. Für j = n, n − 1, . . . , 2, 1 wiederhole: (a) Für v in Lj mit w = 0-Nachfolger = 1-Nachfolger von v: Streiche v, hänge alle 0-/1-Zeiger von 0-/1-Vorgängern von v auf w (Zeitaufwand: Anzahl der Kanten auf v. Diese Kanten werden nie mehr betrachtet.) (b) Finde alle Teilmengen von Xj -Knoten (in Lj ), die identische 0- und 1-Nachfolger enthalten. Aus jeder Teilmenge behalte nur einen Repräsentanten (Anwendung R2). Xj Xj 0 0 Xj 0 1 0 Xj 1 Menge von Knoten mit identischen 0bzw. 1-Nachfolgern 1 1 Umbau: O(|Lj | + #eingehender Kanten). Es bleibt zu klären, wie man die Teilmengen effizient finden kann. Enthalte Lj die Knoten v1 , . . . , vr , jeweils mit den 0- bzw. 1-Nachfolgern (u1 , w1 ), . . . , (ur , wr ). Dann kann man Gruppen bilden, indem man zuerst nach den 0-Nachfolgern und dann nach den 1-Nachfolgern sortiert. Mit QuickSort ergäbe sich eine Laufzeit von O(r log r), so daß theoretisch als Gesamtschranke O(|G| log|G|) möglich ist. BucketSort benötigt in jeder Schicht O(r + |V |) Schritte, zusammen sind das O(n|G|). Man muß aber nicht sortieren: 1. Verteile die Elemente von Lj auf „Buckets“: Element (ui , wi ) kommt in Bucket ui , führe dabei Liste benutzter Buckets 2. Arbeite Buckets gemäß Liste ab und verteile die Elemente gemäß wi erneut, führe wieder Liste In jedem benutzten Bucket befinden sich nun Knoten einer Gruppe direkt hintereinander. Aufwand: O(r). Jede (ursprüngliche) Kante wird ≤ 1-mal umgehängt. 2 4.3.2 Weitere Operationen Auswertung Eingabe: OBDD G, Eingabe a = a1 · · · an ∈ {0, 1}n Ausgabe: fG (a) Folge dem durch a beschriebenen Pfad in G. Aufwand: O(n). KAPITEL 4. OBDDS 89 Erfüllbarkeit Eingabe: OBDD G Ausgabe: Ja ⇔ fg ≡ 0 Wenn G reduziert ist, teste ob G eine 1-Senke besitzt (O(1)). Sonst: Teste, ob ein Weg von Quelle zu 1-Senke existiert (O(|G|)). Äquivalenztest Eingabe: OBDDs G, G Ausgabe: Gilt fG = fG ? 1. Führe eine gemeinsame Reduktion auf disjunkter Vereinigung G + G von G und G aus, wobei vorher die jeweiligen Senken miteinander identifiziert werden. G + G G s 0 1 0 G s 0 1 1 2. Teste, ob s = s gilt. Aufwand: O(|G| + |G |). Sat-Count Eingabe: OBDD G mit Startknoten s Ausgabe: |fG −1 (1)| = |{a | fG (a) = 1}| = Anzahl erfüllender Eingaben (Diese Aufgabenstellung schließt Sat mit ein.) Für den Xi -Knoten v definieren wir av := |{ai · · · an | startend in v landet man mit ai · · · an in 1-Senke}|. Wir berechnen nun alle av per Induktion über i = n + 1, n, . . . , 1. i = n + 1: v ist eine c-Senke: av = c. i ≤ n: Seien u und w 0- bzw. 1-Nachfolger von v, u ein Xk - und v ein Xl -Knoten mit k, l > i. Dann sind au und aw bereits bekannt. KAPITEL 4. OBDDS 90 X1 8 0 1 X2 2 1 0 X3 3 0 0 0 1 X4 1 0 0 0 1 1 1 1 1 Abbildung 4.2: Beispiel für das Zählen aller erfüllenden Belegungen: Von den 0 Senken führt kein Weg zu einer 1-Senke, von den 1-Senken hingegen einer (der leere Weg). Von dem X3 -Knoten führt 1 Weg über den X4 -Knoten und 2 Wege (a4 beliebig) zur 1-Senke, zusammen also 3. 0 Xk u Xi v 1 Xl w Durch Ergänzen der Wege von u (bzw. w) zur 1-Senke erhalten wir alle Wege von v zur 1-Senke: ai bi+1 · · · bk−1 ak · · · an =0 bzw. 2k−i−1 ai bi+1 · · · bl−1 al · · · an . =1 2l−i−1 Damit ergibt sich: av = au 2k−i−1 + aw 2l−i−1 . Ist s ein Xi -Knoten, dann ist |fG −1 (1)| = 2i−1 as . Da alle auftretenden Zahlen höchstens n Bit lang sind, ist der Zeitaufwand polynomiell. Sat-All Eingabe: OBDD G Ausgabe: Liste aller Elemente von f −1 (1) Reduziere zunächst das OBDD, liste alle Eingaben auf, die in reduziertem OBDD Weg vom Startknoten s zur 1-Senke bilden. Synthese Eingabe: OBDDs G1 , G2 mit Startknoten s1 , s2 ; Operation ⊗ ∈ B2 Ausgabe: reduziertes OBDD für fG1 ⊗ fG2 siehe Abschnitt 4.3.3 KAPITEL 4. OBDDS 91 ITE-Synthese (if-then-else) Eingabe: OBDDs G1 , G2 , G3 Ausgabe: reduziertes OBDD für f (a) = fG2 (a) fG1 (a) = 1 fG3 (a) fG1 (a) = 0 siehe Abschnitt 4.3.3 Redundanztest Eingabe: reduziertes OBDD G, Variable Xj Ausgabe: Hängt fG von Xj ab? Enthält G einen Xj -Knoten? Einsetzen von Konstanten Eingabe: reduziertes OBDD G, Variable Xj , Wert a ∈ {0, 1} Ausgabe: reduziertes OBDD G mit fG = fG |Xj =a 1. für jeden Xj -Knoten: a-Nachfolger := a-Nachfolger; entferne durch Anwenden von R0 unerreichbare Knoten 2. bottom-up-Reduktion, startend auf Level j Einsetzen von Funktionen Eingabe: OBDDs G1 , G2 , Index i Ausgabe: reduziertes OBDD für f (a1 , . . . , an ) = fG1 (a1 , . . . , ai−1 , fG2 (a1 , . . . , an ), ai+1 , . . . , an ) 1. Berechne mittels „Einsetzen von Konstanten“ OBDDs G0 , G1 für die Funktionen f0 := fG1 |Xi =0 bzw. f1 := fG1 |Xi =1 2. Bestimme reduziertes OBDD für f (a) = if fG2 (a) then f1 (a) else f0 (a) mittels „If-then-else-Synthese“ 4.3.3 Synthese Seien G1 = (V1 , E1 ) und G2 = (V2 , E2 ) zwei π-OBDDs und ⊗ ∈ B2 eine zweistellige Operation. Gesucht ist ein reduziertes π-OBDD G = (V, E) für f G1 ⊗ f G2 . KAPITEL 4. OBDDS G1 92 s1 G2 s2 v2 u2 v1 u1 0 Xi 1 0 Xj 1 w2 w1 Abbildung 4.3: Die Idee für die ⊗-Synthese ist, die gleichzeitige Auswertung beider OBDDs zu simulieren. Ist man in G1 im Knoten v1 und in G2 im Knoten v2 , so bewegt man sich in dem OBDD weiter, dessen momentaner Variablenindex kleiner ist (also z.B. in G2 , falls j < i). Falls beide Knoten Senken sind, kann man das Auswerteergebnis mittels ⊗ direkt bestimmen. Ähnlich wie in der Vorlesung „Automaten und formale Sprachen“ bei endlichen Automaten arbeitet man auch hier mit einer Kreuzprodukt-Konstruktion und simuliert „gleichzeitige Abarbeitung“. Zunächst ist V := V1 × V2 und (s1 , s2 ) der Startknoten in G (s1 und s2 stehen hier für die entsprechend markierten Knoten). Sei (v1 , v2 ) ∈ V1 × V2 beliebig. Dann ist G wie folgt markiert: • v1 c1 -Senke, v2 c2 -Senke: (v1 , v2 ) := c1 ⊗ c2 -Senke • v1 c1 -Senke, v2 keine Senke: falls c1 ⊗ 0 = c1 ⊗ 1 = c, dann (v1 , v2 ) := c-Senke • sonst: Sei v1 ein Xi - und v2 ein Xj Knoten. (Wir behandeln der Übersicht halber Senken als Xn+1 -Knoten.) Setze k := min{i, j} ≤ n und markiere den Knoten (v1 , v2 ) mit Xk . Bezeichne u1 und w1 den 0- bzw. 1-Nachfolger von v1 und u2 und w2 den 0- bzw. 1-Nachfolger von v2 . KAPITEL 4. OBDDS 93 1. Fall: i = j = k 0-Nachfolger von (v1 , v2 ): (u1 , u2 ) 1-Nachfolger von (v1 , v2 ): (w1 , w2 ) 2. Fall: k = i < j 0-Nachfolger von (v1 , v2 ): (u1 , v2 ) 1-Nachfolger von (v1 , v2 ): (w1 , v2 ) 3. Fall: k = j < i 0-Nachfolger von (v1 , v2 ): (v1 , u2 ) 1-Nachfolger von (v1 , v2 ): (v1 , w2 ) Das so konstruierte OBDD berechnet fG1 ⊗ fG2 , ist allerdings noch nicht reduziert. Wichtig ist, daß R0 vermutlich viele Knoten eliminiert, die nicht erreichbar sind. Satz 4.3.2 Der beschriebene (naive) Synthese-Algorithmus konstruiert ein π-OBDD für fG1 ⊗ fG2 in Zeit und Platz O(|G1 ||G2 |). In praktischen Anwendungen treten Synthese-Probleme auf, bei denen G1 und G2 z.B. 106 Knoten haben. Dann ist |G1 ||G2 | = 1012 , obwohl das reduzierte OBDD eventuell viel kleiner ist. Noch extremer ist die Situation bei ITE-Synthese mit Platzbedarf O(|G1 ||G2 ||G3 |). Verbesserung 1: Erzeuge nur die erreichbaren Knoten von V1 × V2 . V̂ := {(v1 , v2 ) | (v1 , v2 ) in G von (s1 , s2 ) erreichbar} Zeit, Platz: O(V̂ ). (Methode: Tiefensuche, rekursiv.) Dafür benötigt man eine Datenstruktur, in der die schon erreichten Knoten (v1 , v2 ) (als Paare laufender Nummern) gespeichert sind, eine sogenannte Computed Table. Computed Table Einträge: (v1 , v2 ) ∈ V1 × V2 Operationen: Insert LookUp Eine solche Computed Table kann z.B. über eine dynamische Hashtabelle mit erwarteter Zugriffszeit O(1) realisiert werden. KAPITEL 4. OBDDS 94 Verbesserung 2: Erzeugung von V̂ und die Reduktion integrieren. Problematisch ist dabei, daß V̂ top-down erzeugt wird, während die Reduktion bottom-up arbeitet. Wir benötigen also eine Möglichkeit zur top-downReduktion. Eingabe: OBDDs G mit Startknoten s Ausgabe: reduziertes OBDD, Teil von G Wir benötigen eine Datenstruktur, mit der wir zu einem Knoten v äquivalente Knoten finden können, eine Unique-Table. Anfangs ist diese Tabelle leer. Wir suchen in der Tabelle mit dem Schlüssel (i, u, w) (Variable, 0-Nachfolger, 1-Nachfolger) nach einem zu diesem äquivalenten Knoten. Wir wollen also eine Funktion r : V → V berechnen (r: „reduzierte Version“) mit den Eigenschaften fr(v) = fv fv = fv ⇒ r(v) = r(v ). Der Knoten r(v) ist eine Senke oder mit der ersten Variable markiert, von der fv abhängt. Die folgende rekursive Prozedur verwaltet die Unique Table. Algorithmus 4.2: Get_r(v : node) Eingabe: Knoten v Ausgabe: zu v äquivalenter Knoten r(v) (1) falls r(v) definiert: return r(v) (2) 1. Fall: v ist c-Senke (3) if c-Senke (n + 1, c, −) nicht im Unique Table vorhanden (4) erzeuge c-Senke v = (n + 1, c, −); (5) r(v) := v); (6) return v (7) 2. Fall: sonst (v ist ein innerer Knoten mit Markierung Xi und 0-Nachfolger u und 1-Nachfolger w) (8) u∗ := Get_r(u); w∗ := Get_r(w); (Gegebenenfalls werden u∗ bzw. w∗ erzeugt.) (9) if u∗ = w∗ (v redundant; R1-Regel) (10) r(v) := u∗ ; return u∗ (11) else (12) if v ∗ = (i, u∗ , w∗ ) in Unique Table vorhanden (13) r(v) := v ∗ ; return v ∗ (14) else (15) Knoten v unter Schlüssel (i, u∗ , w∗ ) in Unique Table erzeugen; (16) r(v) := v; 0-Nachfolger(v) := u∗ ; 1-Nachfolger(v) := w∗ ; (17) return v KAPITEL 4. OBDDS 95 Jetzt haben wir ein reduziertes OBDD als „Skelett“ in G. Eine Möglichkeit, r(v) zu speichern, ist, in jedem Knoten v einen Zeiger r auf den jeweiligen äquivalenten Knoten zu setzen. Nebenbei muß noch ein Referenzzähler für jedes v verwaltet werden und bei Erreichen von 0 ist der entsprechende Spiecherplatz freizugeben (manche Programmiersprachen unterstützen automatische garbage collection). Der Aufwand für die top-down-Reduktion ist O(|G|) erwartete Zeit (für bottom-up-Reduktion: O(|G|) worst-case). Top-down-Synthese mit integrierter Reduktion Jetzt integrieren wir die beiden Verbesserungen Computed Table und Unique Table in einer Prozedur, die dann direkt in der top-down-Synthese aufgerufen wird. Algorithmus 4.3: R(v1 , v2 ) Eingabe: (v1 , v2 ) – Knotenpaar in V1 × V2 Ausgabe: v ∗ = (v1∗ , v2∗ ) – zu (v1 , v2 ) äquivalenter Knoten (1) 1. Fall: v1 und/oder v2 ist Senke; Wert von fv1 ⊗ fv2 = c (2) erzeuge ggf. c-Senke; return c-Senke (3) 2. Fall: sonst (v1 , v2 nicht beides Senken, fv1 ⊗fv2 nicht konstant) (4) i := min{level(v1 ), level(v2 )}; (5) if Eintrag (v1 , v2 ) in Computed Table vorhanden (6) Eintrag enthält Verweis auf Knoten v ∗ in Unique Table; (7) return v ∗ (8) else (9) Erzeuge Eintrag (v1 , v2 ) in Computed Table (10) (u1 , u2 ) := 0-Nachfolger von (v1 , v2 ) (11) (w1 , w2 ) := 1-Nachfolger von (v1 , v2 ) (12) u∗ := R(u1 , u2 ); w∗ := R(w1 , w2 ) (13) if u∗ = w∗ (14) u∗ wird Repräsentant von (v1 , v2 ) und in Computed Table eingetragen (15) return u∗ (16) else (17) if Eintrag v ∗ für (i, u∗ , w∗ ) in Unique Table vorhanden (18) trage v ∗ zu (v1 , v2 ) in Computed Table ein (19) return v ∗ (20) else (21) erzeuge neuen Knoten v ∗ ; trage v ∗ unter (i, u∗ , w∗ ) in Unique Table ein (22) 0-Nachfolger von v ∗ wird u∗ (23) 1-Nachfolger von v ∗ wird w∗ (24) return v ∗ KAPITEL 4. OBDDS 96 d = 4 Einträge 1: |V̂ | .. . h v1 , v2 (v1 , v2 ) .. . m: m |V̂ | Abbildung 4.4: Die Computed Table als Cache ist eine Hashtabelle, bei der jeder Slot nur eine begrenzte Tiefe d hat. Sind alle d Einträge eines Slotes belegt, muß ein bestehender Eintrag zugunsten eines neuen verdrängt werden. Die Funktion R(·) wird in der Synthese direkt verwendet. Platzbedarf: O(|V̂ |), erwartete Zeit O(|V̂ |). In der Praxis kann sich bei großen OBDDs ein Speicherplatzproblem ergeben, da oft |V̂ | viel größer ist als das reduzierte OBDD. Daher wird die Computed Table als Cache realisiert. Das kann man z.B. erreichen, indem man mit einer Hashfunktion h : V̂ → {1, . . . , m} OBDD-Knoten auf m „Fächer“ abbildet, die eine bestimmte Tiefe d (Anzahl an aufnehmbaren Einträgen) wie z.B. d = 4 haben. Irgendwann kommt es zum Überlauf und es müssen Einträge aus dem Cache verdrängt werden. Dazu können z.B. Regeln wie LRU (last-recentlyused) oder RR (round robin) verwendet werden. Das macht ggf. ein erneutes Bearbeiten des gestrichenen Knotens notwendig, was wegen der Unique Table aber nicht falsch ist. Der Rechenaufwand ist allerdings höher. 4.4 4.4.1 Beispiele für reduzierte (minimierte) OBDDs Binäre Addition Funktion ADDn : (sn · · · s0 )2 = (an−1 · · · a0 )2 + (bn−1 · · · b0 )2 Das entsprechende OBDD besitzt die n Startknoten sn , . . . , s0 für die Summenbits. Günstig ist die Variablenordnung Xn−1 , Yn−1 , . . . , X0 , Y0 , wobei die Xi für die a-Inputs und die Yi für die b-Inputs stehen. Das OBDD besteht aus den Schichten n − 1, n − 2, . . . , 0, die in Abbildung 4.5 dargestellt sind. Die Schichten i, 1 ≤ i ≤ n − 2, enthalten je 9 Knoten; die Schicht 0 enthält 5 und Schicht n − 1 6 Knoten, das sind zusammen 9n − 7. KAPITEL 4. OBDDS 97 c0 s0 X0 0 0 1 X0 0 Y0 0 c0 1 0 1 Y0 0 X0 1 0 1 1 1 0 (a) Schicht 0 des reduzierten ADDn -OBDD si ci Xi 0 0 Yi 1 Xi 0 Yi 1 0 0 1 0 Yi ci 1 1 1 0 Yi 0 0 1 Xi Yi 1 1 0 1 Yi 1 0 Schicht i − 1 ci−1 Xi−1 ci−1 Xi−1 (b) Schicht i, 1 ≤ 1 ≤ n − 2, des reduzierten ADDn -OBDD sn = cn−1 0 Yn−1 0 Xn−1 sn−1 1 0 Yn−1 1 0 0 1 0 Yn−1 Xn−1 1 1 1 Yn−1 0 1 Schicht n − 2 cn−2 Xn−2 cn−2 Xn−2 (c) Schicht n − 1 des reduzierten ADDn -OBDD Abbildung 4.5: Aufbau der Schichten im reduzierten ADDn -OBDD KAPITEL 4. OBDDS 4.4.2 98 Schwellwertfunktionen, symmetrische Funktionen Die Schwellwertfunktion mit Schwellwert k und n Variablen ist 1 1≤i≤n ai ≥ k Thnk (a1 · · · an ) = 0 sonst. In einem reduzierten OBDD enthält jeder Knoten in Schicht j die Information, wieviele Einsen s bzw. wieviele Nullen t bisher gelesen wurden, wobei deren Reihenfolge egal ist. Behauptung 4.4.1 (s, t) = (s , t ) ⇒ Knoten berechnen unterschiedliche Subfunktionen Beweis. Die Funktion fs,t , die ein Knoten in der Schicht j = s + t + 1 berechnet, hängt von s und t ab: 1 l≥j al + s ≥ k fs,t (a1 · · · as+t as+t+1 · · · an ) = 0 sonst irrelevant aj = Thn−j+1 (aj · · · an ) k−s = Thn−s−t+1 (aj · · · an ). k−s Daher gilt fs,t = fs ,t für (s, t) = (s , t ). 2 Damit hat das reduzierte OBDD die Form X1 0 0 X2 .. . 0 Xn−k+1 0 .. . 0 1 X3 0 X4 1 .. . .. . .. . 0 1 1 .. . Xn−k+2 0 1 0 s = 2, t = 1 X2 0 X3 0 0 1 1 1 1 0 1 Xk 0 Xk+1 1 1 .. . 1 1 Betrachten wir noch die symmetrischen Funktionen PARITYn . Die letzte Schicht des allgemeinen OBDDs für symmetrische Funktionen hat dann die Gestalt R2 0 0 Xn 1 0 1 Xn R2 1 0 0 Xn 1 0 1 Xn ··· 1 0 KAPITEL 4. OBDDS 99 und Anwendung von Regel R2 liefert Xn Xn Xn Xn 1 1 0 0 0 1 Das allgemeine PARITYn -OBDD sieht also wie folgt aus: X1 0 1 X2 X2 .. . .. . Xn−1 ⊕ Xn Xn−1 1 1 Xn−1 Xn−1 ⊕ Xn ⊕ 1 0 0 Xn 1 1 Xn 0 0 0 4.4.3 1 Speicheradressierungsfunktion Die Funktion SAk (ak−1 · · · a0 , bn−1 · · · b0 ) = b(ak−1 ···a0 )2 Adresse Speicher modelliert einen Speicherzugriff mit einer k-Bit-Adresse auf einen n = 2k -BitSpeicher. Die günstigste Variablenordnung liest erst die Adreßbits Xk−1 , . . . , X0 und dann die Datenbits Yn−1 , . . . , Y0 . Xk−1 0 0 .. . 0 Xk−2 1 1 0 .. . Xk−2 vollständiger Binärbaum 1 .. . .. . 1 X0 X0 0 1 Y0 0 1 Yn−2 Y1 Yn−1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 KAPITEL 4. OBDDS 100 Das OBDD besitzt 2n − 1 Knoten. Diese Größe kann nicht verbessert werden. In der letzten Schicht muß nämlich jedes Yi gelesen werden können, d.h. in der letzten Schicht sind in jedem Fall n Knoten. Die Subfunktionen fak−1 ···a0 = Y(ak−1 ···a0 )2 sind alle verschieden; zu deren Auswertung sind n − 1 Knoten notwendig (Binärbaum). ∧-Synthese kann OBDD-Größe multiplizieren Die folgende Adreßfunktion liest die Bits an zwei Adressen und verknüpft sie mittels ∧: f (ak−1 · · · a0 , ck−1 · · · c0 , bn−1 · · · b0 ) = b(ak−1 ···a0 )2 · b(ck−1 ···c0 )2 . Wir wählen als Variablenordnung π die Reihenfolge Xk−1 , . . . , X0 , Zk−1 , . . . , Z0 , Yn−1 , . . . , Y0 , d.h. wir lesen zuerst die beiden Adressen und dann die Daten. Wir können ein π-OBDD für f durch ∧-Synthese aus den OBDDs der Funktionen g(a, b) = b(a)2 = SAk (a, b) f (c, b) = b(c)2 = SAk (c, b) erzeugen, die beide Größe 2n − 1 besitzen. Behauptung 4.4.2 Jedes π-OBDD für f hat Ω(n2 ) Knoten. Beweis. Betrachten wir die Subfunktionen fa,c (a, c, b) = b(a)2 · b(c)2 . Diese Subfunktionen sind Yi Yj Yi und das sind 4.4.4 n 2 für 0 ≤ i < j ≤ n − 1 für 0 ≤ i ≤ n − 1, + n ∈ Ω(n2 ) viele. 2 Multiple Addition Addition von m n-Bit-Zahlen: + a1,n−1 a2,n−1 .. . ··· ··· a1,0 a2,0 .. . + am,n−1 · · · am,0 sn+log2 m · · · sn−1 · · · s0 KAPITEL 4. OBDDS 101 Schicht j m−1 Xj,1 1 m Xj,2 .. . 2m − 2 Xj,m .. . 2m − 3 Xj,m Schicht j + 1 0,1 m−1 Xj,m+1 m−1 0 Xj,2 1 m−2 Xj,1 ··· m−2 0 Xj,2 .. . .. . 1 k ··· 1 k+1 2 ··· k2 Xj,m+1 Xj,1 1 ··· Xj,2 .. . .. . Xj,m+1 0 Xj,m 0 0 ··· 0 0 Xj,2 1 Xj,m 1 0 1 .. . cj 0 Xj,1 Xj,m 0,1 0 cj+1 Xj,m+1 Abbildung 4.6: Schicht j des OBDDs für multiple Addition. Jeder Knoten repräsentiert eine Anzahl bereits gesehener Einsen, die links oberhalb des Knotens steht. Beim Übergang in die nächste Schicht (= Übertrag) wird die Anzahl der Einsen halbiert. Wir wählen als Variablenreihenfolge X1,0 , X2,0 , . . . , Xm,0 , X1,1 , . . . , Xm,1 , . . . , X1,n−1 , . . . , Xm,n−1 und verwenden die Schulmethode. Für den Übertrag cj aus Spalte j in Spalte j + 1 gilt c0 ≤ m 2 cj+1 ≤ m+cj 2 , was man leicht durch Betrachtung des worst case (alle m Summanden gleich 2n − 1) sieht. Es folgt sofort cj < m ⇒ cj+1 < m und wegen c0 < m gilt cj < m ∀j. Das OBDD für die multiple Addition kann schichtenweise angegeben werden, wobei eine Schicht einer Spalte entspricht. Die ersten Knoten Xj+1,1 der j+1-Schicht repräsentieren den Übertrag cj aus Schicht j, also aus der Spalte rechts daneben. Es ergibt sich das Teil-OBDD in Abbildung 4.6. Das Gesamt-OBDD für das Ergebnis-Bit si hat dann die Struktur Spalte 0 Spalte 1 .. . Spalte i k m 1 1 0 0 0 k gerade, sonst Senken vertauscht KAPITEL 4. OBDDS 102 Jede Schicht enthält m + (m + 1) + · · · + (2m − 1) = m−1 (m + i) i=0 2 =m + = m2 + m−1 i i=0 1 2 m(m − 1) = 32 m2 − 12 m ∈ O(m2 ) Knoten; insgesamt hat das OBDD für si die Größe (i + 1)O(m2 ) = O(nm2 ). 4.4.5 Multiplikation Die Multiplikation zweier n-Bit-Zahlen (c2n−1 · · · c0 )2 = (an−1 · · · a0 )2 · (bn−1 · · · b0 )2 X Y entspricht der Addition von n Zahlen à la Schulmethode: Yn−1 Xn−1 Y1 Xn−1 .. .. . . · · · Yn−1 X1 · · · Y0 X1 Y0 X0 Y0 Xn−1 ··· Y1 X1 Y1 X0 .. .. . . Yn−1 X0 Es handelt sich also eigentlich um multiple Addition, aber: Jedes Bit wird im Unterschied zur multiplen Addition n-fach benutzt und muß gespeichert werden. Um an−1 , . . . , a0 zu speichern, benötigt das OBDD 2n Knoten. Die Funktion MULTn−1,n berechnet das n-te Bit des Produktes zweier n-Bit-Zahlen: MULTn−1,n (an−1 · · · a0 , bn−1 · · · b0 ) = cn−1 . Satz 4.4.3 (Woelfel 2001) Es existiert ein OBDD für cn−1 der Größe ≤ 7 4n/3 . 3 ·2 Beweis. Wie bisher stehen die Xi für die ai und die Yi für die bi . Als Variablenreihenfolge wählen wir Xn−1 , · · · , X0 , Y0 , . . . , Yn−1 . Betrachte die folgenden Subfunktionen von f (a, b) = cn−1 : fan−1 ···a0 b0 ···bi−1 für k = n3 und k ≤ i ≤ n. Diese entsprechen den Knoten in den letzten n − k Schichten eines OBDD, das grob folgende Struktur hat: KAPITEL 4. OBDDS 103 Xn−1 weniger als 24n/3 Knoten X0 Y0 Yk−1 Yk Yn−1 Der oberere Teil hat jedenfalls weniger Knoten als ein vollständiger Binärbaum für n + k Variable, d.h. höchstens 2n+k − 1 ≤ 2n+n/3+2/3−1 ≤ 24n/3 Knoten. Jetzt überlegen wir uns, daß es nicht zuviele Subfunktionen fa,b0 ···bi−1 gibt. Es gilt fa,b0 ···bi−1 (c, dn−1 · · · di di−1 · · · d0 ) echte Variable = n-tes Bit von (a)2 · (dn−1 · · · di bi−1 · · · b0 )2 = n-tes Bit von (a)2 · (dn−1 · · · di )2 · 2i + (a)2 · (bi−1 · · · b0 )2 . variabel fest Schematisch dargestellt: 2n i a · (dn−1 · · · di )2 a · (bi−1 · · · b0 )2 2n − 1 irrelevant 0 n-tes Bit keine Überträge Aus dem Teil (a)2 · (bi−1 · · · b0 )2 haben nur die Bits an den Stellen n − 1, . . . , i Einfluß auf das Resultat. Seien diese n − i Bits mit ind(a, bi−1 · · · b0 ) (Index) bezeichnet. Nur die letzten n − i Bits von (a)2 · (dn−1 · · · di )2 beeinflussen cn−1 . Deshalb sind nur diese n − i Bits von a relevant: an−1 di+1 an−1 di an−2 di+1 .. . an−1 dn1 ··· ←−−−−−−−−−−−−−−−−−−−−−→ irrelevant ··· ··· a1 di+1 .. . a1 di a0 di+1 a0 di a0 dn−1 ←−−−−−−−−−−−−−−−−−−−−−−→ n−i Wir wissen jetzt, daß fa,b0 ···bi−1 fest ist, sobald ind(a, bi−1 · · · b0 ) und von a der Teil an−i−1 · · · a0 bekannt sind. Es gibt höchstens so viele Subfunktionen wie KAPITEL 4. OBDDS 104 Kombinationen, also ≤ 2n−i · 2n−i = 22(n−i) für festes i. Dann ist die Anzahl aller Subfunktionen 22(n−i) ≤ 43 22(n−k) ≤ 43 24n/3 . ≤ k≤i≤n Zusammen mit den Knoten im Binärbaum sind das höchstens 7 3 · 24n/3 . 2 Beispiel: Die Tabelle veranschaulicht das Wachstum der OBDDs mit n: n Schranke 4 94 8 2845 16 4.6 × 106 32 1.2 × 1013 Als nächstes wollen wir zeigen, daß OBDDs für cn−1 mindestens 2n/8 Knoten haben müssen; dafür brauchen wir das folgende Lemma. Lemma 4.4.4 Betrachte in ADDn (a, b) das 2. Bit sn−1 des Resultates. Jedes π-OBDD für sn−1 und einer Variablenordnung π mit Xi ist unter den ersten n Variablen ⇔ Yi ist unter den letzten n Variablen ∀i hat mindestens 2n Knoten. Beweis. OBdA können wir annehmen, daß zuerst alle X-, danach alle Y -Variablen gelesen werden, denn Austauschen der Bits an Position i von a und b ändert die Summe nicht (“13 + 25 = 15 + 23“). Dann sind die Subfunktionen fX0 =a0 ,X1 =a1 ,...,Xn−1 =an−1 , an−1 · · · a1 a0 ∈ {0, 1}n alle verschieden: Seien fa und fa zwei gleiche Subfunktionen mit a = a . 1. Fall: an−1 = an−1 Widerspruch: fa (0 · · · 0) = an−1 = an−1 = fa (0 · · · 0). 2. Fall: an−1 = an−1 Betrachte einen zweiten Summanden b mit bn−1 = 0. Dann gilt fa (b), fa (b) = Carry aus Stelle n − 2 (an−1 = 0) oder Carry aus Stelle n − 2 (an−1 = 1) Das Carry-Bit an Stelle n − 2 hängt von allen rechteren Stellen ab, so daß folgt an−2 · · · a0 = an−2 · · · a0 , also a = a im Widerspruch zur Annahme. Jede dieser Subfunktionen entspricht einem Knoten; die erste Hälfte des πOBDD hat also bereits ≥ 2n Knoten. 2 Satz 4.4.5 Für jede Variablenordnung π hat ein π-OBDD für cn−1 ≥ 2n/8 Knoten. KAPITEL 4. OBDDS 105 Beweis. Sei π eine beliebige feste Variablenordnung. Wir führen die Mengen U (upper indices) und L (lower indices) U := {Xn , . . . , Xn/2 } L := {Xn/2−1 , . . . , X0 } sowie T (top) und B (bottom) T := {Xπ−1 (0),...,Xπ−1 (n/ −1) } 2 B := {Xπ−1 (n/2,...,Xπ−1 (n) ) } ein. Die Mengen U und L beziehen sich auf den Index der Variablen, T und B auf die Auswertungsreihenfolge (die Variablen in T werden im oberen Teil des OBDDs ausgewertet). Ein Zwischenziel ist nun, ein d so zu finden, daß möglichst viele Paare Xi , Xi+d existieren mit Xi ∈ T ⇔ Xi+d ∈ B und Xi ∈ L und Xi+d ∈ U. (4.2) Xi soll sich also unter den ersten Variablen und in der rechten Hälfte des ersten Faktors befinden, Xi+d unter den letzten Variablen und in der linken Hälfte. Bei einer Verschiebung von d liegen Xi und Xi+d jeweils übereinander; das entspricht der Situation des vorigen Lemmas. Später wird der andere Faktor so gewählt, das tatsächlich nur zwei verschobene Kopien des ersten Faktors addiert werden. Lemma 4.4.6 Es existiert ein Offset d∗ mit |{i | Xi ∈ T ⇔ Xi+d∗ ∈ B, Xi ∈ L, Xi+d∗ ∈ U }| ≥ n 8. Beweis. Betrachte die Menge A := {(i, d) | Xi ∈ T ⇔ Xi+d ∈ B, Xi ∈ L, Xi+d ∈ U, 0 ≤ d ≤ n} aller Index-Offset-Paare mit Eigenschaft (4.2). Dann liefern (Xi , Xj ) ∈ (L ∩ T ) × (U ∩ B) und (Xi , Xj ) ∈ (L ∩ B) × (U ∩ T ) je ein Paar (i, j − i) in A. Daraus folgt |A| ≥ |L ∩ T ||U ∩ B| + |L ∩ B||U ∩ T |. Mit k := |L ∩ T | ergibt sich |L ∩ B| = n 2 − k, |U ∩ B| = n 2 − ( n2 − k) = k, |U ∩ T | = n 2 −k und schließlich (z.B. mit Differentialrechnung) 2 |A| ≥ k 2 + ( n2 − k) ≥ n2 8 . Da es nur n verschiedene ds gibt, gehört mindestens ein d zu ≥ n 8. 2 KAPITEL 4. OBDDS 106 Wähle nun ein passendes d∗ und setze I := {i | (i, i + d∗ ) erfüllen (4.2) }, min := min I, max := max I. Seien weiter B der Block der Eingabe(variablen), der zu I gehört, sowie A der entsprechende Block zu I + d∗ . n−1 n n 2 2 −1 A max +d∗ min +d∗ B max 0 min Unser Ziel ist es nun, b = bn−1 · · · b0 mit 2 Einsen so zu wählen, daß Multiplikation zur Addition zweier verschobener Kopien von a = an−1 · · · a0 wird, d.h. die Frage ist, welche beiden Bits auf 1 gesetzt werden müssen. n−1−i a= A B a= A B .. . bi .. b . bj .. . n−1 Zunächst wollen wir bi so setzen, daß das Element mit Index max an die Position n − 1 gelangt, d.h. max +i = n − 1 ⇒ i = n − 1 − max . Dann soll auch bj so sein, daß das Element max +d∗ an diese Stelle gelangt, also j = n − 1 − max −d∗ . Der zweite Faktor b ist nun 1 i = n − 1 − max oder i = n − 1 − max −d∗ bi := 0 sonst. Außerhalb der beiden Blöcke A und B werden alle Bits zu 0 gewählt. Offenbar haben nur die Bits in den Blöcken A und B Einfluß auf cn−1 . Belegen wir jetzt die Bits in den Blöcken A und B, die nicht zu I bzw. I + d∗ gehören, mit PropagateStellen, so entspricht cn−1 dem vorletzten Bit der Summe der Zahlen an den Ibzw. I + d∗ -Positionen. B 00000000000 00 0 00 0000 A 000 11 1 11 000000 n−1 Propagate KAPITEL 4. OBDDS 107 Man erhält also durch Reduktion aus dem OBDD für die Multiplikation ein OBDD für das vorletzte Bit einer Summe von zwei |I|-Bit-Zahlen. Wegen Lemma 4.4.4 hat das resultierende OBDD mindestens 2|I| Knoten. Daher hat jedes OBDD 2 für n-Bit-Multiplikation mindestens 2|I| ≥ 2n/8 Knoten. 4.5 Schaltkreisverifikation In der Praxis hat man oft eine Spezifikation in Form eines Schaltkreises S1 und eine Implementierung als Schaltkreis S2 gegeben und möchte wissen, ob sie äquivalent sind, d.h. ob fS1 = fS2 ist. Ein Ansatz ist z.B., S1 in ein π-OBDD G1 und S2 in ein π-OBDD G2 zu transformieren und dann einen Äquivalenztest zwischen G1 und G2 durchzuführen. Man kann –korrekte Transformation vorausgesetzt– damit erkennen, ob fS1 = fS2 gilt. Die Transformation S → π-OBDD kann man wie folgt vornehmen: Sei Schaltkreis S gegeben, z.B. als Graph (technisch: SLP). ··· Xn X1 u w v ⊗ ⊗ ∈ B2 t Dann kann man ein OBBD Gv zu einem Knoten v in S induktiv konstruieren. Basisschritt: OBDDs für Xi Induktionsschritt: Aus den bereits bekannten π-OBDDs Gu für fu und Gw für fw bilde mittels Synthese Gv = Gu ⊗ Gw . Wenn v mit t beschrifteter Ausgangsknoten ist, setze Gt := Gv . Problem: Gt könnte klein sein, Gv für inneren Knoten v viel größer. Ein möglicher Trick ist, unterwegs die Variablenordnung „möglichst gut“ zu wählen, d.h. zu wechseln. Dann ist die Variablenordnung nicht von vornherein bestimmt. 4.6 Variablenordnungen Die Variablenordnung kann einen großen Einfluß auf die OBDD-Größe haben. KAPITEL 4. OBDDS 108 Beispiel: ADDn (an−1 · · · a0 , bn−1 · · · b0 ) Xi gut: mittel: schlecht: Yi Variablenordnung Xn−1 , Yn−1 , . . . , X0 , Y0 X0 , Y0 , . . . , Xn−1 , Yn−1 X0 , . . . , Xn−1 , Y0 , . . . , Yn−1 OBDD-Größe O(n) O(n2 ) ≥ 2n Man kann drei Kategorien von Funktionen unterscheiden. gutmütig alle π liefern kleine OBDDs behandelbar manche π liefern kleine OBDDs, manche nicht schlecht alle π liefern (exponentiell) große OBDDs ADDn MULTn−1,n ORn , ADDn , symmetrische Funktionen Kann man vielleicht gute Variablenordnungen effizient finden? Satz 4.6.1 Folgendes Problem ist NP-vollständig: Eingabe: π-OBDD G, k ∈ N Ausgabe: Gibt es π , so daß reduziertes π -OBDD für fG ≤ k Kanten hat? Man kann sogar zeigen, daß dieses Problem schlecht approximierbar ist. Positiv ist allerdings, daß verschiedene Variablenordnungen beim Äquivalenztest nicht entscheidend stören. Satz 4.6.2 Es gibt einen Polynomialzeit-Algorithmus für Eingabe: π1 -OBDD G1 , π2 -OBDD G2 Ausgabe: Ist fG1 = fG2 ? Beweis. Wir setzen über G2 nur voraus, daß es ein read-once-Branching-Programm ist, d.h. jede Variable nur einmal „fragt“. Es muß also nicht unbedingt eine Variablenordnung für G2 geben. Konstruiere induktiv für jeden Knoten v von G2 ein π1 -OBDD für fv (bottomup). Basis: Senken Induktionsschritt: Seien u und w 0- bzw. 1-Nachfolger von v. Wir haben dann bereits π1 -OBDDs Gv , Gw für fu , fw und benötigen ein π1 -OBDD für fv . Wegen fv = Xi fu ∨ Xi fw können wir dieses mithilfe zweier (vereinfachter) ∧-Synthesen und einer ∨-Synthese konstruieren. Die Zeit dafür ist O(|Gu ||Gw |), was auf den ersten Blick ziemlich schlecht ist. KAPITEL 4. OBDDS 109 Entscheidende Beobachtung: Wenn fG1 = fG2 , ist jedes fv eine Subfunktion von fG1 , die durch die Variablen Xi1 , . . . , Xir auf dem Weg vom Startknoten zu v bestimmt ist. Wegen der read-once-Eigenschaft ist Xi ∈ / {Xi1 , . . . , Xir }, d.h. fu und fw haben die Form fu = fG1 |Xi 1 ,...,Xir ,Xi =0 bzw. fw = fG1 |Xi 1 ,...,Xir ,Xi =1 . Es gilt also |Gu |, |Gw | ≤ |G1 |, da Gu und Gw durch Konstantsetzen und Reduktion aus G1 entstehen. Die obige Synthese benötigt also Zeit O(|G1 |2 ). Der Test fG1 = fG2 läuft insgesamt in Zeit O(|G1 |2 |G2 |) (wenn Gleichheit vorliegt). Modifiziert man den Algorithmus so, daß er mit dem Ergebnis fG1 = fG2 abbricht, sobald ein Gv entsteht mit |Gv | > |G1 |, so gilt obige Abschätzung für alle Inputs. 2 Leider lassen sich nicht alle Operationen so gutartig behandeln, z.B. erschweren verschiedene Variablenordnungen die Synthese erheblich. Satz 4.6.3 Das folgende Problem Common-1-Path ist NP-vollständig: Eingabe: π1 -OBDD G1 , π2 -OBDD G2 Ausgabe: Existiert ein a ∈ {0, 1}n mit fG1 (a) = fG2 (a) = 1? Folgerung Wenn P = NP dann existiert kein Polynomialzeit-Algorithmus für die gemischte ∧-Synthese Eingabe: π1 -OBDD G1 , π2 -OBDD G2 Ausgabe: π-OBDD G mit fG = fG1 ∧ fG2 . Mit leichten Modifikationen gilt das auch für ∨-Synthese und ⊕-Synthese. Die Beweisidee für Satz 4.6.3 ist eine Reduktion 3SAT(3) ≤p Common-1-Path. Dabei ist 3SAT(3) eine 3SAT-Variante, bei der jede Variable höchstens 3mal vorkommt. Auch 3SAT(3) ist NP-vollständig. Die Reduktion geschieht wie folgt: φ = C1 ∧ · · · ∧ Cr → (π1 -OBDD Gφ1 , π2 -OBDD Gφ2 ). Enthalte φ die Variablen X1 , . . . , Xn . Wir bilden von jeder Variable Xi drei (1) (2) (3) Kopien Xi , Xi , Xi . Das OBDD Gφ1 prüft, ob jedes Ci mindestens einen wahren Literal besitzt; Wiederholungen einer Variable werden durch entsprechende Kopien ersetzt. Gφ2 prüft, ob die drei Kopien einer Variable denselben (1) (2) (3) Wert haben, d.h. ob Xi = Xi = Xi gilt. Gibt es einen gemeinsamen 1-Input, so liefert dieser eine erfüllende Belegung für φ und umgekehrt. KAPITEL 4. OBDDS 4.7 110 Analyse sequentieller Systeme Wir stellen uns ein Schaltwerk als Mealy-Automat vor. k alter Zustand Z1 neuer Zustand Z1 Register (k FlipFlops) Zk Primäreingabe X1 Schaltwerk (δ, μ) Zk Y1 .. . .. . Xn Primärausgabe Ym Ein Mealy-Automat M = (Q, Σ, Γ, q0 /S0 , δ, λ) besteht aus folgenden Komponenten: Q = {0, 1}k Σ = {0, 1}n Γ = {0, 1}m q0 ∈ Q S0 ⊆ Q, S0 = ∅ δ: Q × Σ → Q λ: Q × Σ → Γ Zustände Eingabealphabet Ausgabealphabet Anfangszustnd (Resetzustand) Menge der Anfangszustände Zustandsüberführungsfunktion Ausgabefunktion Der Automat arbeitet taktweise und bestimmt (vom Resetzustand ausgehend) seinen neuen Zustand bzw. seine Ausgabe aus dem aktuellen Zustand und der Eingabe über Zustandsüberführungsfunktion bzw. Ausgabefunktion. Wir betrachten δ und λ als durch einen Schaltkreis gegeben; dieser ist in ein OBDD überführbar. Äquivalenzproblem für Mealy-Automaten: (1) Eingabe: Mealy-Automaten M1 = (Q1 , Σ, Γ, q0 , δ1 , λ1 ), (2) M2 = (Q2 , Σ, Γ, q0 , δ2 , λ1 ) Ausgabe: Sind M1 und M2 äquivalent, d.h. besitzen sie für jede (unendliche) Eingabefolge dasselbe Ausgabeverhalten? In der Vorlesung „Automaten und formale Sprachen“ wurde ein ähnliches Problem, die Äquivalenz von DFAs, behandelt. Dabei konstruierte man zu KAPITEL 4. OBDDS 111 zwei DFAs M1 , M2 die Minimalautomaten M̃1 , M̃2 und überprüfte diese dann auf Gleichheit. Alternativ kann man auch mit einer Kreuzproduktkonstruktion vorgehen. Zu zwei Mealy-Automaten M1 ,M2 konstruiert man einen Mealy-Automat M: (1) (2) M := M1 × M2 := Q1 × Q2 , Σ, {0, 1}, (q0 , q0 ), δ1 × δ2 , τ mit δ((q1 , q2 ), a) := (δ1 (q1 , a), δ2 (q2 , a)) 1 λ1 (q1 , a) = λ2 (q2 , a) τ ((q1 , q2 ), a) := 0 sonst. Das Äquivalenzproblem ist jetzt die Frage, ob M auf allen Eingaben stets eine 1 ausgibt. Die neue Zustandsmenge ist aber oft viel zu groß, so daß man sie nicht speichern kann. Eine gute Idee ist es, nicht die Menge selbst, sondern ihre charakteristische Funktion zu speichern. Sei R ⊆ Q = {0, 1}k die Menge R := {q ∈ Q | q ist von q0 aus mit einer Eingabefolge erreichbar}, die charakteristische Funktion cR ist dann 1 q∈R cR (q) = 0 sonst. Kodiert man die Zustände in den Variablen z1 , . . . , zk binär, so ist cR (q) = cR (z1 · · · zk ) eine Boolesche Funktion und deshalb als OBDD darstellbar. Angenommen, wir kennen ein OBDD für cR und auch eines für τ ∈ Bk+n . M1 und M2 sind genau dann äquivalent, wenn sie in den erreichbaren Zuständen q ∈ R die gleiche Ausgabe produzieren; in den nicht erreichbaren Zuständen kann das Verhalten beliebig sein. Äquivalenz liegt also vor, wenn cR (z1 · · · zk ) ∨ τ (z1 · · · zk , x1 · · · xn ) ≡ 1 erfüllt ist. Auf der Basis der OBDDs kann das mittels ∨-Synthese geprüft werden. Offen ist noch das Finden eines OBDDs für cR . Wir können R über folgende Rekursion konstruieren: R0 := {q0 } (oder S0 ) R1 := R0 ∪ {δ(q, x1 · · · xn ) | q ∈ R0 , x1 · · · xn ∈ {0, 1}n } N1 := R1 \ R0 Rt+1 := Rt ∪ {δ(q, x1 · · · xn ) | q ∈ Nt , x1 · · · xn ∈ {0, 1}n } Nt+1 := Rt+1 \ Rt . KAPITEL 4. OBDDS 112 Die Mengen Ri enthalten die schon erreichten Zustände, die Mengen Ni die im letzten Schritt neu hinzugekommenen Zustände. Es gibt ein (hoffentlich nicht zu großes) t0 mit Rt0 +1 = Rt0 , also Nt0 = ∅. Dann gilt R = Rt0 . Man erhält ein OBDD für cR , indem man sukzessiv R0 , R1 , N1 , R2 , N2 , . . . berechnet. Die Hoffnung ist, daß die OBDDs für diese Mengen handhabbar sind, obwohl |Rt | viel zu groß für den Rechner ist. Bei der Berechnung der Rt tritt als ein Kernproblem die Bildberechnung auf. Eingabe: OBDD für f ∈ Bn (hier: δ : {0, 1}n+k → {0, 1}k ), OBDD für D ⊆ {0, 1}n (hier: D = Nt × {0, 1}n ) Ausgabe: OBDD für Bild(f ) mit Bild(f ) := {y | ∃x ∈ D : f (x) = y} (hier: Bild(δ) := {q | ∃(q, x) ∈ D : δ(q, x) = q }) Dieses Problem ist sogar für D = {0, 1}n+k schwer; man setzt daher zu seiner Lösung komplexe Heuristiken ein. 4.8 Minimalpolynome mit OBDDs Mit ähnlichen Ideen wie im letzten Abschnitt kann man OBDDs einsetzen, um zweistufige Schaltungen zu minimieren. Wir kodieren ein Monom als Binärvektor, z.B. das Monom X1 X2 X4 X5 X7 als X7 − X5 X4 − X2 X1 − 01 00 11 10 00 11 01 00. Die Idee für den Einsatz von OBDDs ist, die Primimplikantenmenge PI(f ) der Funktion f : {0, 1}n → {0, 1} wie oben als Menge von Binärvektoren PI(f )! zu kodieren und über ihre charakteristische Funktion cPI(f ) = f ∗ : {0, 1}2n → {0, 1} als OBDD zu speichern. Der Algorithmus arbeitet dann im Prinzip wie folgt: 1. Berechne aus OBDD für f ein OBDD für I(f )! 2. Berechne daraus OBDD für PI(f )! 3. Berechne OBDD für Kernimplikantenmenge 4. z.B. Branch & Bound-Verfahren mit OBDDs für Inputmengen und Monommengen In der Praxis sind damit Geschwindigkeitssteigerungen um den Faktor 1000 erzielt worden.