Scheiding
Scheiding
Scheiding
Sie wollen auch ein ePaper? Erhöhen Sie die Reichweite Ihrer Titel.
YUMPU macht aus Druck-PDFs automatisch weboptimierte ePaper, die Google liebt.
Seminar Logik SS2005<br />
Ilka <strong>Scheiding</strong><br />
Thema: ROBDDs - Reduced Ordered Binary Decision Diagrams<br />
Modelchecking kann man mit verschiedenen Datenstrukturen durchführen. Vorraussetzung<br />
ist, dass mit der verwendeten Datenstruktur Mengen eindeutig dargestellt werden können. Seit<br />
1990 werden Reduced Ordered Binary Decision Diagrams (ROBDDs), eine spezielle Form<br />
von binären Entscheidungsdiagrammen, als Datenstruktur für Modelchecking verwendet.<br />
Nutzt man ROBDDs als Datenstruktur für Modelchecking, so spricht man von Symbolic<br />
Modelchecking.<br />
Welche Vorteile es bringt, beim Modelchecking ROBDDs zu nutzen, möchte ich im<br />
Folgenden erklären.<br />
Boolsche Formeln sind eine uns bekannte Repräsentation von Mengen. Eine entscheidende<br />
Frage beim Umgang mit boolschen Formeln ist die, in welcher Datenstruktur sie abgelegt<br />
werden sollen. Einige Datenstrukturen, wie zum Beispiel Truth Tables, sind exponentiell in<br />
der Anzahl der Variablen. Dies führt schon bei wenigen Variablen dazu, dass der<br />
Speicherplatzbedarf unverhältnismäßig groß wird. Diesen Effekt nennt man „State Explosion<br />
Problem“. Andere Datenstrukturen, zum Beispiel Disjunktive Normalform, lassen sich<br />
kompakt speichern, haben aber bei manchen Operationen und Anwendungen, zum Beispiel<br />
bei Überprüfung von Erfüllbarkeit (SAT), einen sehr hohen Rechenaufwand. Operationen und<br />
Anwendungen, die für Modelchecking von Bedeutung sind, lassen sich sehr zeiteffizient auf<br />
ROBDDs durchführen. Hierauf werde ich später näher eingehen. Auch benötigen ROBDDs<br />
so wenig Speicherplatz, dass das State Explosion Problem erst bei sehr viel mehr Variablen<br />
als bei Truth Tables auftritt.<br />
Binäres Entscheidungsdiagramm (Engl.: Binary Decision Diagramm, kurz: BDD) ist ein sehr<br />
allgemeiner Begriff, unter den viele Datenstrukturen fallen, die sehr unterschiedlich sein<br />
können. Es gibt viele verschiedene Arten von BDDs. Die optimale Datenstruktur kann für<br />
verschiedene Mengen (boolsche Formeln) unterschiedlich sein. Da die Ermittlung der<br />
optimalen Datenstruktur sehr zeitaufwendig ist, suchen wir eine Datenstruktur, die im Mittel<br />
sehr gut geeignet ist. ROBDDs sind für sehr viele Mengen eine gute Repräsentation.<br />
Im Folgenden möchte ich erklären, wie ein ROBDD aufgebaut ist und welche Regeln für<br />
ROBDDs gelten.<br />
Zunächst möchte ich jedoch eine andere Form von BDDs, die Binary Decision Trees (BDTs)<br />
einführen. Anhand von Veränderungen dieses BDTs und weiteren Regeln, die wir nach und<br />
nach hinzunehmen werden, möchte ich mich schrittweise dem Aufbau von ROBDDs nähern.
Aufbau von Binary Decision Trees (BDTs)<br />
Es gibt mehrere Arten, eine Boolsche Formel durch Binarbäume darzustellen. Für unsere<br />
Zwecke ist folgende Art der Repräsentation nötig:<br />
Graphisch ist unser BDT ein Binärbaum mit je einer soliden und einer gestrichelten<br />
ausgehenden Kante von jedem Non Terminal Node. Jeder innere Knoten repräsentiert eine<br />
Variable und trägt sowohl den Namen (=Label) dieser Variable als auch den boolschen Wert<br />
(1 oder 0), welcher dem Wahrheitswert seiner Variable entspricht. Die Blattknoten (Terminal<br />
Nodes) entsprechen nicht Variablen, sondern Wahrheitswerten. Wir benennen sie daher<br />
schlicht „0“ oder „1“, entsprechend ihrer boolschen Belegung. Im Gegensatz zu anderen<br />
gängigen Repräsentationen werden Operatoren (Λ, V, etc.) nicht durch Knoten dargestellt.<br />
Operatoren nehmen Einfluss darauf, wie der Graph aufgebaut wird. Hierzu kommen wir<br />
jedoch später.<br />
BDT für Formel f(x,y,z) = -y Λ (x V -z)<br />
Zu einer boolschen Formel gibt es meist viele Möglichkeiten, ein BDT dieser Art aufzubauen.<br />
Reihenfolge und Anzahl der Vorkommnisse der Variablen sind beliebig.<br />
Um den Wahrheitswert einer Funktion f bei einer bestimmten Belegung der in f verwendeten<br />
Variablen zu ermitteln, beginnen wir mit der Betrachtung an der Wurzel. Dem Wurzelknoten<br />
ist eine Variable zugeordnet, in diesem Fall die Variable x. x hat nun die Belegung 1 oder 0.<br />
Ist die Belegung 0, folgen wir dem gestrichelten Pfad zu einem der Kinderknoten von x.<br />
Diesen nennt man auch lo(x). Ist die Belegung von x = 1, so bewegen wir uns zu dem Kind<br />
von x, zu dem man über die solide Kante gelangt (hi(x)).<br />
Als nächstes betrachten wir das Kind von x, zu dem wir gelangt sind. Wir tun dies auf die<br />
selbe Weise wie bei x: Ist die Variablenbelegung dieses Kindes von x = 0, so folgen wir der<br />
gestrichelten Kante, ist sie 1, der soliden Kante. Auf diese Weise bewegen wir uns stetig<br />
abwärts in unserem BDT, bis wir zu einem Blattknoten gelangen. Am Blattknoten können wir<br />
den Wahrheitswert für f mit der benutzten Variablenbelegung ablesen. Sind wir bei einem<br />
Blattknoten „0“ angelangt, so ist der Wahrheitswert der Boolschen Formel mit dieser<br />
benutzen Variablenbelegung „0“ (false), sind wir bei einem Blattknoten „1“ angelangt, so ist<br />
er ebenfalls „1“ (true). Es ist nicht möglich, dass wir zwei Knoten, die mit der selben Variable<br />
gelabelt sind, einmal über die solide und einmal über die gestrichelte Kante verlassen, da eine<br />
Variable nicht sowohl =1 als auch =0 sein kann.<br />
In obigem Beispiel wäre die Formel für die Belegung f( x = 0, y = 0, z = 0) = 1 (true) ,<br />
ebenso wäre sie = 1 (true) für (x = 1, y = 0), hierbei beeinflusst z den Wert des Ergebnisses<br />
nicht, z kann also sowohl = 1 als auch = 0 sein, um die Belegung wahr zu machen. Für alle<br />
anderen Belegungen wird f = 0 (false).
Aufbau von RBDDs<br />
BDTs haben nicht unbedingt einen geringeren Speicherplatzbedarf als Truth Tables, die<br />
Anzahl der Knoten kann ebenfalls exponentiell werden. Um den Speicherplatz zu optimieren<br />
überführen wir den BDT nun in ein Reduced Binary Decision Diagram (RBDD), indem wir<br />
drei Optimierungen vornehmen.<br />
Diese drei Optimierungen sind:<br />
C1: Redundante Terminale entfernen<br />
Alle Pfade die in Blattknoten mit der Belegung 0 führen, werden in einem einzigen<br />
Blattknoten „0“ zusammengeführt. Mit Pfaden zu Blattknoten 1 wird analog<br />
verfahren. Blattknoten, in die nun kein Pfad mehr führt, werden gelöscht. Hatten schon<br />
im BDT alle Blattknoten den selben boolschen Wert, werden alle Pfade in einem<br />
einzigen Knoten mit diesem Wert zusammengeführt.<br />
Redundante Terminale entfernen<br />
C2: Redundante Entscheidungsknoten löschen<br />
Enden beide von einem beliebigen Knoten x ausgehenden Pfade (der solide und der<br />
gestrichelte) im selben Knoten (hi(x) = lo(x)), so wird x gelöscht, da die Belegung von<br />
x keinen Einfluss auf den weiteren Verlauf des Pfades und somit der Überprüfung, hat.<br />
Alle Pfade, die vorher in x reinführten, führen nun in das Kind von x. Hierbei ist es<br />
unerheblich, ob das Kind von x ein innerer Knoten oder ein Blattknoten ist.<br />
Redundante Entscheidungsknoten löschen
C3: Gleiche Teilgraphen löschen<br />
Gibt es in einem BDD zwei exakt identische Teilgraphen deren Wurzelknoten wir x<br />
und y nennen, so werden alle eingehenden Pfade in den Knoten x auf den Knoten y<br />
umgeleitet, x und der gesamte Untergraph von x werden gelöscht.<br />
Gleiche Teilgraphen löschen<br />
Die Reihenfolge in der wir die Optimierungen durchführen spielt keine Rolle. Sie können<br />
auch beliebig oft hintereinander durchgeführt werden, denn es kann passieren, dass z.B. durch<br />
Anwendung von C3 und der daraus folgenden Umleitung eines Pfades ein redundanter<br />
Blattknoten entsteht, der erst danach (durch C2) gelöscht werden kann.<br />
Ein BDD ist reduziert (= RBDD), wenn C1, C2 oder C3 nicht mehr angewendet werden<br />
können.<br />
Ein reduzierter BDD ist auch wieder ein BDD, d.h. alle Eigenschaften eines BDD bleiben bei<br />
der Reduzierung erhalten. Da es nun vorkommen kann, dass ein Knoten mehr als einen<br />
Eingangspfad hat, sprechen wir von nun an nicht mehr über einen Binärbaum, sondern über<br />
ein Diagramm oder Graph.<br />
Die Reduzierungen dienen hier nur der Veranschaulichung. In guten Implementierungen wird<br />
durch dynamisches Programmieren ein nicht reduziertes BDD gar nicht erzeugt. Alle Knoten<br />
werden bei ihrer Erzeugung in einer Hash Table abgespeichert. Dabei wird auch überprüft, ob<br />
der gerade zu erzeugende Knoten sich bereits in der Hash Table befindet (unerheblich wo im<br />
Diagramm er sich befindet). Ist ein identischer Knoten bereits vorhanden, so wird der aktuelle<br />
Knoten nicht erzeugt, sondern seine eingehenden Pfade werden auf den bereits vorhandenen<br />
umgelenkt. Auf diese Weise entstehen nur reduzierte BDDs, also RBDDs.<br />
Durch die Reduzierungen kann es passieren, dass ein ganzes Diagramm auf einen einzigen<br />
Blattknoten reduziert wird. Ist dies der Fall und der Blattknoten ist ein Knoten mit dem Wert<br />
„0“, so nennen wir das Diagramm „B 0 “. Analog nennen wir es „B 1 “, wenn es nur aus dem<br />
Knoten mit dem Wert „1“ besteht.<br />
Ordnung und Größe von RBBDs<br />
Wie anfangs erwähnt gibt es viele Möglichkeiten ein BDD, so auch ein RBDD, aufzubauen.<br />
Ein wichtiger Aspekt hierbei ist die Anordnung von Variablen.<br />
Eine „Variablenordnung“ ist die Reihenfolge von Variablen, wie sie von der Wurzel zu den<br />
Blättern hin in ein (R)BDD eingefügt werden.
ROBDDs<br />
ROBDDs sind RBDDs für die eine Variablenordnung gilt. Hierbei gelten folgende Regeln:<br />
- Jede Variable darf in der Variablenordnung genau einmal vorkommen.<br />
- Jede Variable, die in einem ROBDD vorkommt, muss (!) in die Variablenordnung<br />
aufgenommen werden.<br />
- Nicht jede Variable der Variablenordnung muss in jedem ROBDD einen Knoten<br />
bekommen.<br />
Alle ROBDDs, die in einem Kontext miteinander stehen, müssen sich einer gemeinsamen<br />
Variablenordnung bedienen. Dies gilt insbesondere für ROBDDs, die miteinander verglichen<br />
oder durch Operatoren (V, Λ, XOR) miteinander verknüpft werden sollen.<br />
Bauen wir einen RBDD auf, so ist die Variablenordnung entscheidend für die Größe des<br />
RBDDs. Die optimale Variablenordnung zu finden ist ein komplexes Problem und hat einen<br />
hohen Rechenaufwand, es gibt jedoch Heuristiken, die zeiteffizient recht gute<br />
Variablenordnungen berechnen. Einen wichtigen Ansatz für die heuristische Betrachtung<br />
dieses Problems möchte ich im Folgenden nennen und an einem Beispiel verdeutlichen.<br />
Ansatz: Was in logischem Zusammenhang steht, sollte auch zusammen betrachtet werden<br />
Beispiel:<br />
f = ((a1=b1) Λ (a2=b2) Λ (a3=b3))<br />
Der Wahrheitswert des gesamten Ausdrucks f, hängt davon ab, ob die geklammerten<br />
Teilausdrücke wahr sind. Diese Teilausdrücke können aber erst einen Wahrheitswert<br />
zugeordnet bekommen, wenn alle darin vorkommenden Variablen betrachtet wurden. Daher<br />
ist es sinnvoll, jeweils die Variablen eines Teilausdrucks im ROBDD in räumlicher Nähe<br />
anzuordnen, z.B. auf einem Pfad direkt untereinander, wie im Beispiel links, um sie somit<br />
beim Durchlaufen des Graphen auch kurz nacheinander zu betrachten. Dadurch kann<br />
gegebenenfalls recht schnell entschieden werden, ob ein Ausdruck noch wahr (oder falsch)<br />
werden kann.
Variablenordnung:<br />
a1, b1, a2, b2 , a3 , b3<br />
Variablenordnung: a1, a2 , a3, b1 , b2 , b3<br />
Eine Variablenordnung in der jede Variable nur einmal vorkommen darf, wie es bei ROBDDs<br />
der Fall ist, hat den positiven Effekt, dass auf einem Pfad von der Wurzel zu einem<br />
Blattknoten keine Variable mehrmals betrachtet wird.<br />
Folgendes Beispiel soll verdeutlichen, warum dies so ist:<br />
Haben wir einen Ausschnitt aus einem Graphen wie links zu sehen, so<br />
ist die zugehörige Variablenordnung „..a…b...a…“ , da es einen Pfad<br />
gibt, auf dem a sowohl vor b als auch nach b betrachtet wird. Dies ist<br />
jedoch nach der Definition von ROBDDs nicht zulässig. Hierbei ist<br />
unerheblich, ob zwischen a und b bzw. b und a noch andere Variablen<br />
liegen.<br />
Eine Struktur dieser Art ist in einem ROBDD ebenfalls nicht möglich,<br />
da einer der beiden Knoten als redundanter Entscheidungsknoten<br />
gelöscht bzw. nicht erstellt werden würde.<br />
Dies führt zu folgender Beobachtung: Betrachten wir zwei beliebige aber feste Variablen x<br />
und y. Steht x in der Variablenordnung vor y, so kommen x und y im RBDD entweder nicht<br />
auf dem selben Pfad vor oder x steht vor (= näher an der Wurzel als) y.
Gibt es keine Variablenordnung, so kann man für die selbe boolsche Formel viele BDDs mit<br />
verschiedenen Strukturen erzeugen. Durch die Variablenordnung aber haben ROBDDs eine<br />
eindeutige (kanonische) Repräsentation. Das heißt wenn zwei ROBDDs R 1 und R 2 die selbe<br />
boolsche Funktion repräsentieren, dann ist ihre Struktur identisch. Zu einer Boolschen Formel<br />
kann man also unter Berücksichtigung einer bestimmten Variablenordnung genau ein<br />
ROBDD aufbauen.<br />
Die kanonische Repräsentation ist einer der größten Vorteile von ROBDDs. Hierdurch<br />
können für boolsche Formeln folgende Tests sehr schnell durchgeführt werden:<br />
• Test auf redundante Variablen : Hängt das Ergebnis nicht von Variable x i ab, enthält<br />
das ROBDDs x i nicht.<br />
• Test auf Tautologie: Eine Formel ist immer = 1(true), wenn das zugehörige ROBDDs<br />
= B 1 ist. Besteht das zugehörige ROBDD nicht nur aus dem Blattknoten „1“, so ist es<br />
falsifizierbar.<br />
• Test auf Erfüllbarkeit (SAT) : Ist ein ROBDD = B 0, so ist es nicht erfüllbar, es wird<br />
immer 0 (false). Ist es nicht = B 0, dann gibt es mindestens eine Variablenbelegung, die<br />
diese Formel wahr macht, sie ist also erfüllbar.<br />
Anmerkung zur Laufzeit:<br />
Der Test auf Erfüllbarkeit kann in konstanter Zeit durchgeführt werden. Trotzdem ist SAT<br />
auch mit ROBDDs ein NP-vollständiges Problem, da der Aufbau eines ROBDDs im<br />
Worst Case NP-vollständig ist.<br />
Im Average Case erfolgt die Umwandlung jedoch recht effizient, wodurch ROBDDs in<br />
der Praxis oft vorteilhaft sind.<br />
• Test auf semantische Äquivalenz zweier ROBDDs: Haben zwei oder mehrere<br />
ROBDDs die selbe Struktur, so sind sie semantisch äquivalent. Haben sie<br />
verschiedene Strukturen, sind sie nicht semantisch äquivalent.<br />
Wie viele Belegungen gibt es, die ein ROBDD wahr machen?<br />
Die Anzahl der Belegungen, die ein ROBDD wahr machen, muss für jedes ROBDD einzeln<br />
berechnet werden. Man beginnt die Rechnung von den Blattknoten aus und arbeitet sich zur<br />
Wurzel hin vor. Dabei wird sich für jeden besuchten Knoten gemerkt, wie viele Belegungen<br />
von ihm ausgehend einen Weg zum Blattknoten „1“ ermöglichen. Diese Anzahl kann größer<br />
sein, als die Anzahl der Pfade, die von dem jeweiligen Knoten zum Blattknoten „1“ führen, da<br />
nicht auf jedem Pfad jede Variable der boolschen Formel vorkommt, jedoch auch diese<br />
Variablen berücksichtigt werden.<br />
Beispiel:<br />
Der Knoten „0“ bekommt den Wert 0 zugeordnet, der<br />
Knoten „1“ den Wert 1.<br />
e : 0 + 1 =1<br />
1, da der Knoten „1“ Kinderknoten von e ist<br />
0, da der Knoten „0“ Kinderknoten von e ist<br />
e ist die letzte Variable in dieser Variablenordnung, die in<br />
der Formel vorkommt, daher gibt es keine<br />
Multiplikationen.
d : 0 + 1*2 1 = 2<br />
0, da der Knoten „0“ Kinderknoten von d ist<br />
1, da der Knoten „1“ Kinderknoten von d ist<br />
2 1 , denn genau eine Variable, die in der Formel vorkommt liegt in der Ordnung hinter d,<br />
wurde aber auf diesem Pfad nicht betrachtet.<br />
*2 1 , denn dieser Pfad führt bei e=1 und auch bei e=0 zu einer erfüllenden Belegung.<br />
c : 2*2 0 + 1*2 1 = 4<br />
2*2 0 : die erste 2 wird von d übernommen, *2 0 denn es liegen keine, also 0, Variablen<br />
zwischen c und d.<br />
1*2 1 : 1 wird von e übernommen, *2 1 denn zwischen c und e liegt d, d wurde aber nicht<br />
betrachtet. Dieser Pfad führt also für d = 1 und d = 0 zur 1.<br />
b : 0 + 1*2 3 = 8<br />
0, da der Knoten „0“ Kinderknoten von b ist<br />
1, da der Knoten „1“ ein Kinderknoten von b ist,<br />
*2 3 , denn in diesem Pfad haben wir 3 Variablen der Formel (c,d,e,) nicht betrachtet. Für jede<br />
Kombination aus c=0/1, d=0/1 und e=0/1 führt dieser Pfad also zur 1.<br />
a : 8 + 4 *2 1 = 16<br />
8 wird von b übernommen, es gibt keine Variablen zwischen a und b, daher wird nicht<br />
multipliziert,<br />
4 wird von c übernommen und *2 1 , da wir auf diesem Pfad b, also genau eine Variable, nicht<br />
betrachtet haben.<br />
Da a der Wurzelknoten ist und es von a aus 16 Belegungen gibt, die die Formel wahr machen,<br />
wissen wir, dass es insgesamt 16 Belegungen gibt, die die Formel wahr machen.<br />
Zur Erinnerung:<br />
lo(x) ist der Kinderknoten von x, zu dem wir gelangen, wenn x = 0 ist.<br />
hi(x) ist der Kinderknoten von x, zu dem wir gelangen, wenn x = 1 ist.<br />
Allgemein:<br />
Sei x der Knoten, den wir aktuell betrachten.<br />
Sei A(x) die Anzahl der Belegungen, die die Formel für Variablen ab x wahr macht.<br />
Sei j = A(lo(x)).<br />
Sei h = A(hi(x)).<br />
Sei dl die Anzahl der Variablen, die in der boolschen Formel vorkommen und in der<br />
Variablenordnung zwischen x und lo(x) liegen.<br />
Sei dh die Anzahl der Variablen, die in der boolschen Formel vorkommen und in der<br />
Variablenordnung zwischen x und hi(x) liegen.<br />
Für die Blattknoten gilt A(„0“)=0 , A(„1“)=1<br />
Dann ist A(x) = j * 2 dl + h * 2 dh
Algorithmus apply zur Verknüpfung durch Operatoren<br />
Wollen wir zwei ROBDDs durch einen Operator verknüpfen, wenden wir den Algorithmus<br />
apply an. Dieser Algorithmus bekommt als Input die beiden ROBDDs R1 und R2 und den<br />
Operator und liefert ein ROBDD zurück, welches der Variablenordnung entspricht und genau<br />
für (R1 Op R2) den Wahrheitswert 1 zurückliefert und sonst den Wahrheitswert 0.<br />
Die beiden bisherigen Diagramme werden nicht verändert, sondern ein drittes Diagramm<br />
B f_Op_g wird erstellt.<br />
Der Algorithmus ist rekursiv und beginnt bei dem Wurzelknoten. Er arbeitet wie an<br />
folgendem Beispiel demonstriert:<br />
Zunächst Labeln wir jeden Knoten. Die Blattknoten bekommen nach ihrer Belegung dabei die<br />
selben Werte, da wir einen Blattknoten „0“ („1“) als den selben Knoten betrachten, ganz<br />
gleich in welchem Diagramm er vorkommt. Alle anderen Knotenbezeichnungen vergeben<br />
wir nur ein Mal. Hierdurch entsteht nun dieses Diagramm:<br />
Wie oben schon erwähnt wird auch das neue Diagramm B f_Op_g in der Regel durch Hashing<br />
als ROBDD erzeugt. Im Folgenden wird jedoch nur der Basisalgorithmus erklärt, so dass das<br />
Ergebnis zunächst ein nicht reduziertes Diagramm sein wird.<br />
Wir beginnen bei beiden Diagrammen B f und B g mit der Betrachtung bei den Wurzelknoten<br />
(S2 und S5). Wir bilden einen neuen Wurzelknoten (S2,S5) und labeln ihn mit a. Könnten wir<br />
einem Knoten theoretisch zwei Variablen zuordnen (wie hier a und b), so wählen wir immer<br />
die Variable, die in der Variablenordnung weiter vorne steht. Nun fügen wir zwei Kanten<br />
hinzu, grafisch eine solide und eine gestrichelte. Von (S2,S5) gehen nun zwei Kanten aus, die<br />
zu je einem weiteren Knoten führen sollen. Verfolgen wir zunächst die solide Kante: Von S2<br />
im Diagramm f ausgehend führt die solide Kante zu S1. In g bleiben wir zunächst in S5, da<br />
(S2,S5) mit a gelabelt wurde und a in g nicht vorkommt. In g befinden wir uns daher noch im<br />
Wurzelknoten S5. Daher erzeugen wir als Kind von (S2,S5) einen Knoten (S1,S5), diesen
labeln wir mit b. Solange es möglich ist, einen Knoten mit einer Variable zu labeln, tun wir<br />
dies (auch wenn ein Teil des Tupels S1 oder S0 ist). Auch in B f_Op_g gilt, dass nur Blattknoten<br />
keiner Variable zugeordnet sind.<br />
Von hier aus wird der Graph nach selbem Prinzip rekursiv weiter aufgebaut, ebenso die<br />
andere Hälfte des Graphen ausgehend von der gestrichelten Kante der Wurzelknoten.<br />
Erreicht ein Pfad in f oder g S1 oder S0, so bleiben wir in diesem Blattknoten stehen.<br />
Aus (S1,S5) ausgehend führt die solide Kante zu (S1,S1). Da wir bei beiden Graphen f und g<br />
in Blattknoten angekommen sind, wird auch der Knoten (S1,S1) zu einem Blattknoten.<br />
Daher erstellen wir nun den Kinderknoten an der gestrichelten Kante von (S1,S5).<br />
Folgen wir von S5 aus der gestrichelten Kante, so gelangen wir zu S6. In f bleiben wir in S1.<br />
Daher wird als zweites Kind von (S1,S5) der Knoten (S1,S6) erstellt.<br />
Bisher haben wir folgenden Graphen für B f_ Op_g erstellt:<br />
Verfahren wir wie oben weiter bis wir auf jedem Pfad in f und g einen Blattknoten erreicht<br />
haben, also bis der Algorithmus terminiert, erhalten wir folgenden Graphen:<br />
Von nun an sind die Bezeichnungen der inneren Knoten irrelevant. Sie dienten nur dem<br />
Aufbau des Graphen.<br />
Bis zu diesem Punkt hatte der Operator, mit dem die beiden Graphen f und g verknüpft<br />
werden, keinen Einfluss auf den Aufbau des neuen Graphen. Mit dem Operator wird jetzt<br />
lediglich festgelegt, welche Werte die Blattknoten bekommen.
Hierzu ersetzen wir alle S0 wieder mit 0 und alle S1 mit 1. Auf diese 0en und 1en wenden wir<br />
nun den Operator an. Da wir in diesem Beispiel Und-verknüpfen, werden alle Paare (1,1)<br />
durch einen Knoten „1“ ersetzt, alle anderen Paare durch einen Knoten „0“.<br />
Würden wir Oder-verknüpfen, würden wir alle Paare (1,1), (1,0) und (0,1) durch einen<br />
Knoten „1“ ersetzen und nur (0,0) durch einen Knoten „0“. Mit Xor würde entsprechend<br />
verfahren.<br />
Um den Graphen B f_ Op_g als ROBDD zu erhalten, müssen wir ihn noch reduzieren:<br />
Shannon Expansion – Hintergrund zum Algorithmus apply<br />
Einschub: Restriktion einer Formel:<br />
Die Schreibweise f[1/x] bedeutet, dass alle in einer Formel f auftretenden Variablen x<br />
durch 1 (true) ersetzt werden. Analog bedeutet f[0/x], dass alle in f auftretenden<br />
Variablen x durch 0 (false) ersetzt werden. Dies nennt man Restriktion von f.<br />
Die Shannon Expansion besagt: Für alle boolschen Formeln und boolschen Variablen, selbst<br />
die, welche nicht in f vorkommen, gilt f ≡ -x Λ f[0/x] V x Λ f[1/x].<br />
Die Shannon Expansion für (f op g) lautet:<br />
f op g ≡ -x i Λ ( f[0/x i ] Λ g[0/x i ] ) V x Λ ( f[1/x i ] Λ g[1/x i ] )
Für den Algorithmus apply wird die Shannon Expansion für f op g als Kontrollfunktion<br />
genutzt. Sei x i jeweils die aktuell betrachtete Variable. Dann werden aus x i heraus zwei<br />
Unterbäume erzeugt, je einer für ([0/x i ] Λ g[0/x i ]) und einer für ( f[1/x i ] Λ g[1/x i ] ).