Main Skript: Boolesche Function: Algorirthmen und

Werbung
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.
Herunterladen