Diplomarbeit Automatisches Layout von UML-Klassendiagrammen vorgelegt von Martin Siebenhaller Juni 2003 Betreuer: Prof. Dr. M. Kaufmann Arbeitsbereich Paralleles Rechnen Wilhelm-Schickard-Institut für Informatik Fakultät für Informations- und Kognitionswissenschaften Eberhard-Karls-Universität Tübingen ii Inhaltsverzeichnis 1 Einführung 1.1 Motivation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.2 Überblick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 Grundlagen 2.1 Graphen . . . . . . . . . . . . . . . . . 2.2 Planarität . . . . . . . . . . . . . . . . 2.3 Orthogonale Zeichnungen von planaren 2.4 Min-Cost-Flow . . . . . . . . . . . . . . . . . . . . . . . . . Graphen . . . . . . 3 Notation von UML-Klassendiagrammen 3.1 Klassen . . . . . . . . . . . . . . . . . . . 3.2 Beziehungen . . . . . . . . . . . . . . . . . 3.2.1 Vererbung (inheritance) . . . . . . 3.2.2 Assoziation (association) . . . . . . 3.2.3 Abhängigkeit (dependency) . . . . 3.3 Pakete (packages) . . . . . . . . . . . . . . 3.4 Erweiterungsmechanismen . . . . . . . . . 3.4.1 Zusicherungen (constraints) . . . . 3.4.2 Eigenschaften (properties) . . . . . 3.4.3 Stereotypen (stereotypes) . . . . . 3.4.4 Notizen (notes) . . . . . . . . . . . 3.5 Konsequenzen für den Layoutalgorithmus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1 4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 5 6 9 12 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 15 17 17 19 20 20 21 21 22 22 23 24 4 Ästhetikkriterien 25 4.1 Syntaktische Ästhetikkriterien . . . . . . . . . . . . . . . . . 25 4.2 Semantische Ästhetikkriterien . . . . . . . . . . . . . . . . . 28 4.3 Auswahl geeigneter Ästhetikkriterien . . . . . . . . . . . . . 29 5 Der Topology-Shape-Metrics Ansatz 5.1 Definition . . . . . . . . . . . . . . . 5.2 Einbettung . . . . . . . . . . . . . . 5.2.1 GT-Heuristik . . . . . . . . . 5.2.2 Routen von Kanten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33 33 35 35 38 iv INHALTSVERZEICHNIS 5.3 5.4 5.2.3 Rerouting von Kanten . Orthogonalisierung . . . . . . . 5.3.1 Tamassias Algorithmus . 5.3.2 Das Kandinsky-Modell . Kompaktierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 43 43 46 50 6 Ein Layoutalgorithmus für UML-Klassendiagramme 53 6.1 Hyperkanten und Vererbungsgabeln . . . . . . . . . . . . . . . 55 6.2 Der Basisalgorithmus . . . . . . . . . . . . . . . . . . . . . . . 57 6.2.1 Formzuweisung für die aufwärtsgerichteten Kanten . . 57 6.2.2 Knickreduzierung . . . . . . . . . . . . . . . . . . . . . 61 6.2.3 Umsetzung der vorgegebenen Form durch das KandinskyNetzwerk . . . . . . . . . . . . . . . . . . . . . . . . . 64 6.2.4 Einheitliche Ausrichtung der aufwärtsgerichteten Kanten 68 6.3 Verbesserungen des Basisalgorithmus . . . . . . . . . . . . . . 71 6.3.1 Einbettung . . . . . . . . . . . . . . . . . . . . . . . . 71 6.3.2 Höhenkanten . . . . . . . . . . . . . . . . . . . . . . . 77 6.3.3 Behandlung von Selbstschleifen . . . . . . . . . . . . . 81 6.4 Der gesamte Algorithmus . . . . . . . . . . . . . . . . . . . . 84 6.4.1 Überblick . . . . . . . . . . . . . . . . . . . . . . . . . 84 6.4.2 Laufzeit . . . . . . . . . . . . . . . . . . . . . . . . . . 85 7 Implementierung 87 7.1 Design des Layoutalgorithmus . . . . . . . . . . . . . . . . . . 87 7.2 Anwendung des Layoutalgorithmus . . . . . . . . . . . . . . . 90 8 Zusammenfassung und Bewertung 93 A Beispieldiagramme 99 Abbildungsverzeichnis 1.1 Ein kleines UML-Klassendiagramm. . . . . . . . . . . . . . . 2.1 2.2 2.3 2.4 2.5 Planare Repräsentation eines Graphen. . . . . Planarer Graph, der nicht Aufwärtsplanar ist. Orthogonale Gittereinbettung eines Graphen. Orthogonale Repräsentation eines Graphen. . Zusammenhang der Zeichenketten. . . . . . . 3.1 3.2 3.3 3.4 Darstellung Darstellung Darstellung Darstellung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 9 10 11 12 einer Klasse in UML-Klassendiagrammen. . . . von Beziehungen in UML-Klassendiagrammen. . von Paketen in UML-Klassendiagrammen. . . . einer Notiz in UML-Klassendiagrammen. . . . . . . . . 17 18 21 24 4.1 Semantische Ästhetikkriterien. . . . . . . . . . . . . . . . . . . 29 5.1 5.2 5.3 5.4 35 36 40 5.5 5.6 5.7 5.8 5.9 Ersetzung einer Kantenkreuzung durch einen Knoten. . . . . Darstellung der GT-Heuristik . . . . . . . . . . . . . . . . . . Darstellung eines st-Graphen und dessen Routinggraph. . . . Darstellung eines Graphen und dem dazugehörigen dualen Graph. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Konstruktion des orthogonalen Netzwerks. . . . . . . . . . . . Beispiel leerer Faces. . . . . . . . . . . . . . . . . . . . . . . . Verbotene Flüsse im Kandinsky-Modell. . . . . . . . . . . . . Das Kandinsky-Netzwerk. . . . . . . . . . . . . . . . . . . . . Ersetzung eines Knotens durch viele kleine Knoten. . . . . . . 42 45 47 48 49 51 6.1 6.2 6.3 6.4 6.5 6.6 6.7 6.8 Ersetzung von Hyperkanten. . . . . . . . . . . . . . Mögliche Erweiterungen des Hyperkantenkonzepts. Vom Algorithmus zugewiesene Formen. . . . . . . . Beispiel zur Knickreduzierung. . . . . . . . . . . . Unregelmäßige Vereinfachungen . . . . . . . . . . . Entfernen von Knicken bei Kreuzungsknoten. . . . Weitere Transformationen bei Kreuzungsknoten. . Änderungen am Kandinsky-Netzwerks. . . . . . . . 55 57 60 62 62 63 63 65 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 . . . . . . . . . . . . . . . . . . . . . . . . vi ABBILDUNGSVERZEICHNIS 6.9 6.10 6.11 6.12 6.13 6.14 6.15 Behandlung von ungerichteten Kanten bei der Abbildung auf das Netzwerk. . . . . . . . . . . . . . . . . . . . . . . . . . . . Bestimmung der zu richtenden Kanten. . . . . . . . . . . . . . Zwei Kanten die sich bezüglich der Knotenfolge überschneiden. Erzeugen von Höhenkanten zwischen Geschwisterknoten. . . . Verschiedene Fälle, die beim Einfügen von Höhenkanten auftreten. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Zwei alternative Platzierungen einer Selbstschleife. . . . . . . Aufteilung der Kanten auf die Ports und mögliche Anordnung der Selbstschleifen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88 89 90 91 8.1 8.2 Schwächen der Einbettung. . . . . . . . . . . . . . . . . . . . Entstandene Schneckenform. . . . . . . . . . . . . . . . . . . . 95 96 A.1 A.2 A.3 A.4 A.5 A.6 Beispieldiagramm Beispieldiagramm Beispieldiagramm Beispieldiagramm Beispieldiagramm Beispieldiagramm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82 Grafische Oberfläche des Jar-Inspectors. UML-Klassendiagramm der verwendeten Bedienung des Jar-Inspectors. . . . . . . Nicht ausgerichtete Vererbungsgabeln. . . . . . . . . . . . 79 81 7.1 7.2 7.3 7.4 1 2 3 4 5 6 . . . . . Klassen. . . . . . . . . . . 67 70 72 77 . . . . . . . . . . . . 99 100 101 102 103 104 Tabellenverzeichnis 3.1 3.2 3.3 Vordefinierte Zusicherungen der UML. . . . . . . . . . . . . . Vordefinierte Eigenschaften der UML. . . . . . . . . . . . . . Vordefinierte Stereotypen der UML. . . . . . . . . . . . . . . 22 23 23 4.1 Ästhetikpräferenzen für Klassendiagramme. . . . . . . . . . . 30 6.1 Vereinfachung der Form von Kanten . . . . . . . . . . . . . . 61 viii TABELLENVERZEICHNIS Kapitel 1 Einführung 1.1 Motivation In der Softwareentwicklung hat sich seit Anfang der 90er Jahre immer mehr das objektorientierte Paradigma durchgesetzt. Der Trend zur Objektorientierung wird durch die große Beliebtheit objektorientierter Programmiersprachen wie C++ und Java unterstützt. Bei der objektorientierten Modellierung werden Objekte der realen Welt wie Personen, Dinge oder Gegenstände auf Objekte eines Softwaresystems abgebildet. Die Abbildung erfolgt durch geeignete Abstraktion, d.h. es werden nur relevante Eigenschaften der realen Objekte modelliert. Ein Objekt besitzt einen bestimmten Zustand und ein bestimmtes Verhalten. Im Objektmodell existiert also keine Trennung zwischen Daten und Funktionalität. Die objektorientierte Softwareentwicklung zeichnet sich besonders durch hohe Flexibilität, Erweiterbarkeit und Wiederverwendbarkeit aus. Sie erlaubt auch für komplexe Systeme eine sehr natürliche Beschreibung. Ein weiterer Vorteil zu bisherigen Verfahren ist, dass die Objektorientierung ein durchgängiges Konzept durch die Phasen Analyse, Entwurf und Implementierung bietet und somit den Entwicklungsprozess vereinfacht und die semantischen Lücken zwischen diesen Phasen schließt. Zu Beginn der 90er Jahre entstanden viele unterschiedliche Methoden zur objektorientierten Modellierung mit unterschiedlichen Notationen [19]. Es fehlte ein einheitlicher Standard. Deswegen entwickelten Booch, Rumbaugh und Jacobson (die „drei Amigos“) ihre unterschiedlichen Modellierungsansätze zur Unified Modelling Language (UML) weiter. Es handelt sich bei der UML lediglich um eine grafische Notation, nicht um eine Methode, die den Entwicklungsprozess der Software vorgibt. Die UML bietet verschiedene Diagrammtypen mit unterschiedlichem Abstraktionsgrad zur Beschreibung eines Informationssystems an. Im November 1997 erklärte die Object Management Group (OMG) UML 1.1 zum OMG-Standard für die objektorientierte Modellierung. Durch die hohe Akzeptanz in der Industrie hat sich die 2 KAPITEL 1. EINFÜHRUNG UML inzwischen als Standardmodellierungssprache für die objektorientierte Softwareentwicklung etabliert und andere Ansätze nahezu verdrängt. Klassendiagramme sind ein Diagrammtyp der UML und dienen der Modellierung der statischen Struktur eines Systems [1]. Eine Klasse ist eine Art Schablone für gleichartige Objekte. Die Objekte einer Klasse werden auch als deren Instanzen oder Ausprägungen bezeichnet. Die Klasse legt Struktur und Verhalten der Objekte sowie deren Beziehungen zu anderen Objekten fest. Eine Klasse wird deshalb auch als abstrakter Datentyp bezeichnet. Klassendiagramme stellen Klassen und deren statische Beziehung untereinander dar. Oft beinhaltet die Darstellung einer Klasse auch deren Attribut- und Methodennamen (vgl. Abb. 1.1). In der Softwareentwicklung sind Klassendiagramme der wohl am häufigsten eingesetzte Diagrammtyp. MidiMessage − data:byte[] − length:int + <init> + setMessage + getMessage + getStatus + getLength + clone MidiEvent + message:javax.sound.midi.MidiMessage + tick:long +message + <init> + getMessage + setTick + getTick ShortMessage # # # # # # # # # # # # # # # # # # MIDI_TIME_CODE:int SONG_POSITION_POINTER:int SONG_SELECT:int TUNE_REQUEST:int END_OF_EXCLUSIVE:int TIMING_CLOCK:int START:int CONTINUE:int STOP:int ACTIVE_SENSING:int SYSTEM_RESET:int SysexMessage NOTE_OFF:int NOTE_ON:int # SYSTEM_EXCLUSIVE:int # SPECIAL_SYSTEM_EXCLUSIVE:int CONTROL_CHANGE:int PROGRAM_CHANGE:int + <init> + <init> + setMessage + setMessage + getData + clone POLY_PRESSURE:int CHANNEL_PRESSURE:int PITCH_BEND:int + <init> + <init> + setMessage + setMessage + setMessage + getChannel + getCommand + getData1 + getData2 + clone + getDataLength MetaMessage # META:int + defaultMessage:byte[] + dataLength:int + <init> + <init> + setMessage + getType + getData + clone + writeVarInt + <clinit> Abbildung 1.1: Ein kleines UML-Klassendiagramm. Die Zahl von Werkzeugen zur Softwareentwicklung, sogenannte CASEWerkzeuge (Computer Aided Software Engineering), steigt ständig. Eine Hauptaufgabe dieser Werkzeuge ist es, aus Daten automatisch Diagramme zu generieren, um den Entwickler im Entwicklungsprozess zu unterstützen. Ein typisches Beispiel dafür ist die Erzeugung von Klassendiagrammen aus bereits bestehendem Programmcode, was unter den Begriff ReverseEngineering fällt. Der Wissenschaftbereich automatisches Graphenzeichnen befasst sich mit der Entwicklung von Algorithmen zur Informationsvisualisierung. Dabei werden die Elemente von Graphen so geometrisch angeordnet, dass eine mög- 1.1. MOTIVATION 3 lichst „schöne“ und verständliche Zeichnung entsteht. Ein Graph ist ein Konstrukt der diskreten Mathematik, das aus einer Menge von Knoten und einer Menge von Kanten besteht [4]. Eine Kante verbindet jeweils zwei (nicht notwendigerweise verschiedene) Knoten miteinander. Graphen werden verwendet, um Beziehungen zwischen Objekten zu beschreiben, wobei die Objekte durch Knoten und die Beziehungen durch Kanten repräsentiert werden. Beim automatischen Graphenzeichnen geht es also darum, Objekte und deren Beziehungen möglichst verständlich darzustellen. Automatisch bedeutet dabei, dass der Benutzer nicht in den Layoutprozess eingreifen muss. Die Positionierung der Knoten und Kanten wird allein vom Layoutalgorithmus bestimmt. Dies ermöglicht eine schnelle und einfache grafische Darstellung von großen Graphen, die manuell nur mit hohem Aufwand „schön“ dargestellt werden können. Die Positionierung der Elemente und somit die Nützlichkeit der Zeichnung wird durch Ästhetikkriterien wie z.B. die Minimierung der Anzahl der Kantenkreuzungen beeinflusst. Die Wahl der verwendeten Ästhetikkriterien sowie deren Priorität hängt vom jeweiligen Anwendungsgebiet ab. Da der Layoutalgorithmus für die Realisierung der Ästhetikkriterien verantwortlich ist, besitzen unterschiedliche Anwendungsgebiete auch meist unterschiedliche bzw. modifizierte Layoutalgorithmen. Viele Probleme, die beim automatischen Graphenzeichnen auftreten, wie das Finden eines maximalen planaren Subgraphen sind NP-vollständig, d.h. die Probleme sind nicht in polynomieller Zeit lösbar. Die Lösung solcher Probleme wird deshalb durch Heuristiken möglichst gut abgeschätzt. Durch den steigenden Gebrauch von Diagrammen in Wissenschaft und Wirtschaft, hat das automatische Zeichnen von Graphen stark an Bedeutung gewonnen. Diagramme unterstützen die Aussagekraft des zugrundeliegenden Modelles und erleichtern das Verständnis des dargestellten Sachverhaltes. Gerade in der Informatik werden sehr häufig Diagramme eingesetzt, z.B. • Entity-Relationship-Diagramme (ERM) bei der Modellierung eines Datenbanksystems, • UML-Diagramme bei der Softwareentwicklung, • Syntaxdiagramme beim Compilerbau • und Schaltpläne beim Entwurf von VLSI-Schaltungen (Very Large Scale Integration). Nahezu alle Diagrammtypen lassen sich durch Graphen repräsentieren und somit auch automatisch zeichnen. Dazu bildet man die Symbole eines Diagrammes auf Knoten und die Verbindungen auf Kanten eines Graphen ab und entwickelt dann einen geeigneten Layoutalgorithmus. Bei der Entwicklung muss neben der Qualität der Zeichnung auch auf die Laufzeit geachtet werden, da die Benutzer oft direkt auf die Ausgabe warten. Eine höhere 4 KAPITEL 1. EINFÜHRUNG Qualität verursacht oft auch eine höhere Laufzeit, es muss also das richtige Verhältnis zwischen Qualität und Laufzeit gefunden werden. Ziel dieser Diplomarbeit ist die Entwicklung und Implementierung eines Algorithmus zum automatischen Layout von UML-Klassendiagrammen. Dazu werden die spezifischen Ästhetikanforderungen von UML-Klassendia– grammen ermittelt und dann in den Layoutalgorithmus mit einbezogen. Im Gegensatz zu den meisten bisherigen Ansätzen, die auf einem hierarchischen Layoutalgorithmus basieren, dient hier ein orthogonaler Layoutalgorithmus als Basis. Die wesentlichen Modifikationen, die in dieser Diplomarbeit behandelt werden, sind das Aufwärtszeichnen von Kanten und die Verwendung von Vererbungsgabeln zur Darstellung von Vererbungsbeziehungen. Die Implementierung des Layoutalgorithmus erfolgt in der Programmiersprache Java unter Verwendung der yfiles-Klassenbibliothek. Als Ausgangspunkt dient das bestehende Kandinsky-Framework. 1.2 Überblick Im nächsten Kapitel werden die grundlegenden graphentheoretischen Begriffe erläutert, die in den folgenden Kapiteln vorausgesetzt werden. Kapitel 3 gibt einen Überblick über die UML-Notation und die sich daraus ergebenden Anforderungen an den Layoutalgorithmus. Die Beschreibung verschiedener Ästhetikkriterien sowie die Untersuchung deren Relevanz in Bezug auf UML-Klassendiagramme erfolgt in Kapitel 4. In Kapitel 5 werden bestehende Algorithmen zum Erzeugen orthogonaler Zeichnungen vorgestellt, die als Basis für den zu entwickelnden Algorithmus dienen. Die Anpassungen und Modifikationen, die zum Zeichnen von UML-Klassendiagrammen erforderlich sind, werden in Kapitel 6 beschrieben. Implementierungsspezifische Designentscheidungen liefert Kapitel 7. Schließlich werden die ermittelten Ergebnisse im 8. Kapitel nochmals zusammengefasst bevor eine Bewertung des entwickelten Layoutalgorithmus erfolgt. Anhang A enthält einige Beispieldiagramme, die mit dem entwickelten Layoutalgorithmus gezeichnet wurden. Es wurden Beispieldiagramme gewählt, die die Wirkung der einzelnen Modifikationen verdeutlichen. Kapitel 2 Grundlagen In diesem Kapitel werden einige grundlegende Begriffe erläutert, die im Laufe dieser Arbeit verwendet werden. 2.1 Graphen Die in diesem Abschnitt verwendeten Definitionen stammen im wesentlichen aus [4] und [7]. Ein Graph G ist ein geordnetes Paar (V, E) zweier Mengen, wobei V die Menge der Knoten und E die Menge der Kanten ist. Die Kantenmenge E setzt sich aus gerichteten Kanten ED und ungerichteten Kanten EU zusammen. Es gilt: E = ED ∪ EU . Eine gerichtete Kante e ∈ ED ist ein geordnetes Paar (v, w) und eine ungerichtete Kante e ∈ EU ist ein ungeordnetes Paar (v, w), wobei v, w ∈ V . Bei ungerichteten Kanten spielt die Angabe der Reihenfolge der Knoten keine Rolle, d.h. die ungerichtete Kante (v, w) kann auch durch (w, v) angegeben werden. Die Knoten v und w einer Kante e = (v, w) werden als Endpunkte der Kante bezeichnet. Sind die beiden Endpunkte einer Kante identisch, dann nennt man diese Kante eine Selbstschleife (Selfloop). Existieren mehrere Kanten mit denselben Endpunkten, so nennt man diese Mehrfachkanten. Eine Kante e ist inzident zu einem Knoten v, wenn v ein Endpunkt der Kante ist. Ein Knoten v ist adjazent zum Knoten w falls (w, v) ∈ E. Ein Knoten v ist benachbart zum Knoten w falls (v, w) ∈ E oder (w, v) ∈ E. Ein zu v adjazenter Knoten ist also immer auch ein Nachbar von v, die Umkehrung gilt nur bei ungerichteten Kanten. Ein Graph G = (V, E) wird gerichteter Graph genannt, falls gilt E = ED . Gilt E = EU so nennt man G einen ungerichteten Graph. Ist der Graph G weder gerichtet noch ungerichtet, so nennt man ihn teilgerichtet. Ein Graph G0 = (V 0 , E 0 ) ist ein Subgraph von G = (V, E) falls gilt: V 0 ⊆ V und E 0 ⊆ E. Ist dabei V 0 = V , dann wird G0 als Teilgraph von G bezeichnet. Der Graph G0 ist der von V 0 ⊆ V induzierte Subgraph von G, falls E 0 alle Kanten aus E enthält, die Knoten aus V 0 verbinden (v, w ∈ V 0 ∧(v, w) ∈ E ⇒ (v, w) ∈ E 0 ). 6 KAPITEL 2. GRUNDLAGEN Ein Graph G = (V, E) wird als bipartit bezeichnet, falls die Knotenmenge V in zwei disjunkte Knotenmengen V1 und V2 aufgeteilt werden kann, so dass gilt V = V1 ∪ V2 , V1 ∩ V2 = ∅ und für alle Kanten (v, w) ∈ E gilt: (v ∈ V1 ∧ w ∈ V2 ) oder (v ∈ V2 ∧ w ∈ V1 ). Der Grad δ(v) eines Knotens v gibt die Anzahl der zu v inzidenten Kanten an. Eine Selbstschleife wird dabei doppelt gezählt. Bei gerichteten Graphen G unterscheidet man zusätzlich zwischen dem Ausgangsgrad δout (v) = |{w : (v, w) ∈ E}| und dem Eingangsgrad δin (v) = |{w : (w, v) ∈ E}|. Es gilt dann δ(v) = δin (v) + δout (v). Der Grad eines Knotens v bezüglich der Kantenmenge E 0 wird mit δE 0 (v) bezeichnet und gibt die Anzahl der zu v inzidenten Kanten e an, für die gilt e ∈ E 0 . Ein Graph G wird als k-Graph bezeichnet falls gilt: maxv∈V δ(v) ≤ k. Ein Graph G = (V, E) ist zum Graphen G0 = (V 0 , E 0 ) isomorph, falls eine bijektive Funktion f : V → V 0 existiert, so dass (u, v) ∈ E ⇔ (f (u), f (v)) ∈ E 0 . Ein Pfad p von einem Knoten v zu einem Knoten w im Graphen G = (V, E), besteht aus einer Knotenfolge (v0 , .., vk ), wobei gilt: v0 , .., vk ∈ V , v0 = v, vk = w und (vi , vi+1 ) ∈ E für alle i = 0, .., k − 1. Die Länge des Pfades p ist gleich der Anzahl der abgelaufenen Kanten. Sind die Knoten v0 , .., vk paarweise verschieden, dann nennt man P einen einfachen Pfad. Ist v0 = vk dann bildet der Pfad einen Zyklus. Ein Graph G ist azyklisch, falls kein Knotenpaar (v, w) in G existiert, dass durch einen einfachen zyklischen Pfad verbunden ist. Ein ungerichteter Graph G ist zusammenhängend, falls für jedes Knotenpaar v, w ∈ V, v 6= w ein Pfad von v nach w in G existiert. Ein zusammenhängender, azyklischer und ungerichteter Graph wird auch als Baum1 bezeichnet. Ein Spannbaum (spanning tree) von G ist ein Baum, der Teilgraph von G ist und (|V | − 1) Kanten enthält. Ein gewurzelter Baum (rooted tree) ist ein Baum mit einem ausgezeichneten Knoten r, der als Wurzel des Baumes bezeichnet wird. Sei r die Wurzel eines Baumes T = (V, E) und v ∈ V ein Knoten. Alle Knoten w ∈ V auf dem Pfad von r nach v werden als Vorgänger von v bezeichnet. Ist w ein Vorgängerknoten von v, dann ist v ein Nachfolger von w. Der Subbaum von v, ist der Baum, der durch die Nachfolgerknoten von v induziert wird, wobei v die Wurzel des Baumes ist. Ist w ein Vorgänger von v und gilt (w, v) ∈ E, dann ist w der Vater von v und v das Kind von w. Besitzen zwei Knoten den gleichen Vater, dann sind sie Geschwister. Ein Knoten ohne Kind ist ein Blatt. Jeder Knoten außer der Wurzel besitzt genau einen Vater. 2.2 Planarität Eine ebene Einbettung eines Graphen G = (V, E) ist eine Abbildung von G in den R2 , für die gilt [30]: 1 Der Graph kann auch gerichtete Kanten besitzen, diese werden aber wie ungerichtete Kanten behandelt. 2.2. PLANARITÄT 7 • Die Knotenmenge V wird auf verschiedene Punkte der Fläche abgebildet. • Die Kantenmenge E wird auf offene Jordan-Kurven abgebildet, wobei jede Kurve die zwei Punkte der Fläche verbindet, auf die die Endpunkte der entsprechenden Kante abgebildet werden. • Es existiert kein Paar von Kurven, das sich überschneidet. Ein Graph für den eine ebene Einbettung existiert, kann also überkreuzungsfrei gezeichnet werden. Definition 1 (Planarität) Ein Graph ist planar, wenn für ihn eine ebene Einbettung existiert. Bei der Definition der Planarität spielt es keine Rolle, ob es sich bei dem Graphen um einen gerichteten oder ungerichteten Graphen handelt. Für jeden planaren Graphen existiert eine kreuzungsfreie Zeichnung. Der Begriff der Planarität ist allerdings unabhängig von der Zeichnung eines Graphen. Ein Graph, der in einer Zeichnung Kreuzungen besitzt, kann also trotzdem planar sein. Eine ebene Einbettung eines Graphen G = (V, E) teilt die Ebene in verschiedene Regionen auf. Diese Regionen werden Faces genannt. Es existiert dabei genau ein unbeschränktes Face, dass sogenannte äußere Face. Jede Kante grenzt zwei, nicht notwendigerweise verschiedene Faces voneinander ab. Sind die beiden Faces identisch, dann nennt man die Kante eine Brücke. Ein Face kann niemals von einem anderen Face geschnitten werden, es kann aber in einem anderen Face enthalten sein. Die planare Repräsentation P eines eben eingebetteten Graphen G beschreibt dessen Topologie. Für jedes Face f von G besitzt die planare Repräsentation P eine Liste P (f ), die die Kanten enthält, die das Face f begrenzen. Ist f ein inneres Face, dann entspricht die Reihenfolge der Kanten der zyklischen Reihenfolge, die entsteht, wenn die Kanten von f im Uhrzeigersinn durchlaufen werden. Ist f das äußere Face, entspricht die Reihenfolge der Kanten der zyklischen Reihenfolge, die entsteht, wenn die Kanten von f gegen den Uhrzeigersinn durchlaufen werden. Dadurch kann die Repräsentation des äußeren Faces von der des inneren Faces unterschieden werden, falls beide Faces die gleiche begrenzende Kantenmenge besitzen. Da nicht festgelegt wird, mit welcher Kante eine Liste P (f ) beginnen muss, ist die planare Repräsentation nicht eindeutig. Enthält ein Face f eine Brücke e, so ist e zweimal in der Kantenmenge der Liste P (f ) enthalten (die Kante e wird dabei in unterschiedliche Richtungen abgelaufen). Jede Kante erscheint also genau zweimal in den Listen. Es gilt demnach: X |P (f )| = 2 · |E|. (2.1) f ∈F 8 KAPITEL 2. GRUNDLAGEN Der Grad eines Faces f wird mit δ(f ) bezeichnet und gibt die Anzahl der Kanten an, die das Face begrenzen. Es gilt also δ(f ) = |P (f )|. Damit das äußere Face eindeutig bestimmt ist, wird es in der planaren Repräsentation entsprechend gekennzeichnet. Die Angabe der Listen P (f ) ist äquivalent zur Angabe der zyklischen Ordnung der Kanten um die Knoten. Ein Beispiel für eine planare Repräsentation zeigt Abb. 2.1. v3 e7 v6 e2 v1 e1 v2 e3 f3 e4 v4 f2 e5 e6 f1 =äußeres Face P(f1 )=(e2 , e3 , e5 , e6 , e7 ) P(f2 )=(e6 , e5 , e4 , e7 ) P(f3 )=(e1 , e1 , e2 , e4 , e3 ) v5 f1 Abbildung 2.1: Beispiel einer planaren Repräsentation. Die Kante e1 ist eine Brücke, das Face f1 ist das äußere Face. Eine wichtige Eigenschaft von planaren Graphen zeigt die Eulersche Formel. Satz 1 (Eulersche Formel) Sei G = (V, E) ein zusammenhängender, eben eingebetteter Graph und F die Menge der Faces von G. Dann gilt: |V | − |E| + |F | = 2. Ein Beweis zu diesem Satz befindet sich in [20]. Aus der Eulerschen Formel ergibt sich u.a., dass sich die Anzahl der Kanten in einem zusammenhängenden, planaren Graphen linear zur Anzahl der Knoten verhält, denn unter Nichtberücksichtigung von Selbstschleifen und Mehrfachkanten gilt: |P (f )| ≥ 3 für alle f ∈ F und wegen Formel 2.1 gilt damit |F | ≥ 32 |E|. Nach Einsetzen in die eulersche Formel ergibt sich |E| ≤ 3 · |V | − 6. Falls sich die Anzahl der Mehrfachkanten linear zu der Anzahl der Knoten verhält, gilt also: |E| = O(|V |). Diese Eigenschaft wird häufig für die Laufzeitabschätzung von Algorithmen auf zusammenhängenden, planaren Graphen verwendet. Für azyklische, gerichtete Graphen wird der Begriff der Planarität oft zum Begriff der Aufwärtsplanarität verfeinert. Definition 2 (Aufwärtsplanarität) Ein gerichteter Graph G ist aufwärtsplanar, wenn er so eben eingebettet werden kann, dass alle Kanten monoton steigend in eine Richtung zeigen. Die Richtung der Kanten muss dabei nicht unbedingt aufwärts sein, sie müssen lediglich in dieselbe Richtung zeigen. Die Richtung selbst ist beliebig, da 2.3. ORTHOGONALE ZEICHNUNGEN VON PLANAREN GRAPHEN 9 die Zeichnung entsprechend gedreht werden kann. Aus der Definition ergibt sich direkt, dass ein aufwärtsplanarer Graph G auch immer planar und azyklisch sein muss. Die Umkehrung gilt nicht (vgl. Abb. 2.2). Ein teilgerichteter Graph G = (V, ED ∪ EU ) ist aufwärtsplanar, wenn der durch die Kanten ED induzierte Subgraph von G aufwärtsplanar ist. 6 6 4 5 2 3 1 (a) 4 5 2 3 1 (b) Abbildung 2.2: Der dargestellte Graph ist zwar planar (a) aber nicht aufwärtsplanar, da die aufwärtsgerichtete Zeichnung (b) eine Kreuzung besitzt. 2.3 Orthogonale Zeichnungen von planaren Graphen Ein orthogonales Gitter ist eine ebene Einbettung eines unendlichen 4-Graphs, dessen Knoten ganzzahlige Koordinaten besitzen und dessen Kanten Knotenpaare mit einer Einheitsdistanz verbinden [30]. Eine orthogonale Gittereinbettung eines Graphen G = (V, E) ist eine Abbildung Q von G in das orthogonale Gitter, für die gilt: • Jeder Knoten von G wird auf einen unterschiedlichen Punkt des Gitters abgebildet. Für zwei Knoten v, w ∈ V , v 6= w gilt also: Q(v) 6= Q(w). • Jede Kante e = (v, w) von G wird auf einen Pfad Q(e) des Gitters abgebildet, dessen Endpunkte Q(v) und Q(w) sind. • Die Pfade Q(e1 ) und Q(e2 ) eines beliebigen Kantenpaares e1 , e2 ∈ E besitzen keine gemeinsamen Punkte, außer gegebenenfalls gemeinsame Endpunkte. Ein eben eingebetteter Graph Q(G), der von Q beschrieben wird, ist isomorph zu G. Die horizontalen und vertikalen Abschnitte, aus denen sich 10 KAPITEL 2. GRUNDLAGEN eine Kante zusammensetzt, werden Segmente der Kante genannt. Alle Winkel einer orthogonalen Gitterzeichnung sind ein Vielfaches von 90 Grad. Ein Endpunkt eines Segments, auf den kein Knoten abgebildet wird, wird als Knick bezeichnet. Eine Gittereinbettung Q wird als regionerhaltend bezüglich P bezeichnet, wenn die planare Repräsentation von Q(G) isomorph zu P ist. Abb. 2.3 zeigt eine orthogonale Gittereinbettung eines vollständigen Graphen mit vier Knoten. Abbildung 2.3: Orthogonale Gittereinbettung eines Graphen. Die Form eines orthogonalen Graphen G wird durch die orthogonale Repräsentation H beschrieben. Diese erweitert die planare Repräsentation um Informationen über Winkel zwischen Kanten sowie über Kantenknicke. Die orthogonale Repräsentation H eines planaren 4-Graphen G mit der planaren Repräsentation P enthält für jedes Face f von G eine Liste H(f ). Ein Listenelement enthält folgende Einträge: 1. eine Kante e von G, 2. eine binäre Zeichenkette s (Bitvektor), 3. und eine Zahl a aus der Menge {90, 180, 270, 360}. Die Liste H(f ) erhält man, indem man die Liste P (f ) um die Punkte 2) und 3) erweitert. Die Kanten e von H(f ) entsprechen also den Kanten von P (f ). Die binäre Zeichenkette s beschreibt die Form der Kante e. Eine 0 kodiert einen Winkel von 90 Grad, eine 1 einen Winkel von 270 Grad. Das k-te Bit von s gibt den Winkel des k-ten Knickes der Kante e an, auf den man trifft, wenn man e im Face f im Uhrzeigersinn bzw. gegen den Uhrzeigersinn, falls f das äußere Face ist, abläuft. Besitzt die Kante e keinen Knick, wird dies durch ein ε symbolisiert. Die Zahl a gibt den Winkel zwischen der Kante e und der Kante des in H(f ) folgenden Listenelements an. Abb. 2.4 zeigt ein Beispiel einer orthogonalen Repräsentation. Die orthogonale Repräsentation H eines orthogonalen Graphs besitzt die folgenden Eigenschaften: 2.3. ORTHOGONALE ZEICHNUNGEN VON PLANAREN GRAPHEN11 v3 e2 v2 f3 e4 e7 f2 v6 e6 e1 v1 v4 e3 e5 v5 f1 f1 =äußeres Face H(f1 )=((e2 , 11, 180), (e3 , , 180), (e5 , , 270), (e6 , , 270), (e7 , , 180)) H(f2 )=((e6 , , 90), (e5 , , 90), (e4 , , 90), (e7 , , 90)) H(f3 )=((e1 , , 360), (e1 , , 90), (e2 , 00, 90), (e4 , , 90), (e3 , , 90)) Abbildung 2.4: Beispiel einer orthogonalen Repräsentation. Die Knicke werden der Kante e2 zugewiesen. 1. Es existiert ein planarer 4-Graph, dessen planare Repräsentation durch die e-Felder von H(f ) gegeben ist. 2. Seien r1 ∈ H(fi ) und r2 ∈ H(fj ) zwei unterschiedliche Listenelemente und r1 .e = r2 .e (e trennt die Faces fi und fj ). Dann entspricht die binäre Zeichenkette r1 .s der binären Zeichenkette die man erhält, wenn man r2 .s umkehrt und dann negiert (vgl. Abb. 2.5). 3. Für jedes Listenelement r sei Rotation(r) = Zeros(r.s) − Ones(r.s) + (2 − r.a 90 ), wobei Zeros die Anzahl der Nullen und Ones die Anzahl der Einsen in der binären Zeichenkette s angibt. Da jedes von H beschriebene Face ein rektilineares Polygon bildet, gilt: X Rotation(r) = r∈H(f ) ( −4 f ist äußeres Face, +4 sonst. 4. Sei Lv die Menge der Listenelemente r für die v ein Endpunkt der Kante r.e ist und r.e bezüglich der entsprechenden Liste H(f ) in Richtung des Knotens v durchlaufen wird. Für jeden Knoten v gilt dann: X r∈Lv r.a = 360 12 KAPITEL 2. GRUNDLAGEN Die Summe der Winkel von benachbarten Kanten um einen Knoten v ist also 360 Grad. Um aus einer orthogonalen Repräsentation eine orthogonale Gittereinbettung zu erhalten, muss noch die Länge der Kantensegmente berechnet werden. 1 0 fi 1 1 0 fj e 2 0 1 Abbildung 2.5: Zusammenhang der Zeichenketten. Durchläuft man die Kante e im Face fj , so entsteht die Zeichenkette „110“. Durchläuft man e im Face fi , so entsteht die Zeichenkette „100“. Mit der orthogonalen Repräsentation lassen sich bis jetzt nur 4-Graphen beschreiben. Ein Knoten v mit δ(v) > 4, besitzt in einer orthogonalen Zeichnung mindestens eine Seite an der sich mehrere Kanten befinden. Der von diesen Kanten eingeschlossene Winkel ist somit ein 0 Grad Winkel. Um 0 Grad Winkel in die orthogonale Repräsentation mit aufzunehmen, erlaubt man für die Zahl a, die den Winkel angibt, auch einen Wert von 0. Eine orthogonale Repräsentation, die 0 Grad Winkel zulässt, wird quasi-orthogonale Repräsentation genannt. 2.4 Min-Cost-Flow Das Finden einer knickminimalen orthogonalen Repräsentation erfolgt durch das Lösen eines Min-Cost-Flow-Problems, welches ein Netzwerkflussproblem darstellt. Ein Netzwerk N = (V, E) ist ein gerichteter Graph mit zwei ausgezeichneten Knoten, einer Quelle s und einer Senke t, wobei gilt: δin (s) = 0 und δout (t) = 0. Auf der Menge der Kanten wird eine nichtnegative Funktion cap : E → R≥0 definiert, welche die Kapazität der Kanten angibt. Für alle Knoten v, w ∈ V ∧ (v, w) ∈ / E gilt: cap(v, w) = 0. Ein Fluss im Netzwerk N ist eine Funktion f : V × V → R, die folgende Eigenschaften besitzt: (1) f (v, w) = −f (w, v) für alle Knoten v, w ∈ V , (2) f (v, w) ≤ cap(v, w) für alle Knoten v, w ∈ V , 2.4. MIN-COST-FLOW (3) X 13 für alle Knoten v ∈ V \ {s, t}. f (v, w) = 0 w∈V Eigenschaft (1) wird als Schiefsymmetrie bezeichnet. Durch die Kapazitätsbedingung (2) wird der Fluss, der über eine Kante fließen kann, durch deren Kapazität beschränkt. Die Flusserhaltungsbedingung (3) sagt aus, dass für jeden Knoten v ∈ V \ {s, t} der gesamte Fluss in den Knoten hinein gleich dem gesamten Fluss aus dem Knoten heraus ist. Der Wert |f | eines Flusses f entspricht dem Fluss aus dem Quellknoten heraus. Es gilt also: X |f | = f (s, v). v∈V Ein Fluss f ist maximal, wenn sein Wert |f | mindestens so groß ist, wie der Wert jedes anderen Flusses. Bei einem Min-Cost-Flow-Problem wird zusätzlich eine Kostenfunktion cost : E → R auf den Kanten des Netzwerkes N definiert, welche die Kosten angibt, die beim Transport einer Flusseinheit über die Kante anfallen. Die Kosten eines Flusses f sind wie folgt definiert: X cost(f ) = f (e) · cost(e). e∈E Ein Min-Cost-Flow ist ein maximaler Fluss minimaler Kosten. 14 KAPITEL 2. GRUNDLAGEN Kapitel 3 Notation von UML-Klassendiagrammen Dieses Kapitel bietet einen Überblick über die wichtigsten Notationselemente von UML-Klassendiagrammen und basiert im wesentlichen auf [19] und [24]. Es existieren Elemente für Klassen, verschiedene Beziehungen und Pakete. Für die genauere Spezifizierung von Elementen besitzt die UML außerdem verschiedene eingebaute Erweiterungsmechanismen, wie Zusicherungen, Eigenschaften, Stereotypen und Notizen. Bei den genannten Erweiterungen handelt es sich, bis auf die Notiz, nicht um neue Elemente, sondern lediglich um eine geeignete Beschriftung der Grundelemente. Im folgenden werden zuerst die Grundelemente und dann die Erweiterungsmechanismen vorgestellt. 3.1 Klassen Eine Klasse wird durch ein Rechteck mit drei, jeweils durch horizontale Linien getrennte, Komponenten dargestellt. Die oberste Komponente enthält den Klassennamen in zentrierter, fetter Schrift. Handelt es sich um eine abstrakte Klasse, wird er zusätzlich kursiv geschrieben. Der Name beginnt mit einem Großbuchstaben. Die Komponente kann außerdem auch eine Erweiterung für die genauere Spezifizierung der Klasse enthalten. Stereotypen werden zentriert über dem Klassennamen angegeben. Die Angabe von Eigenschaften erfolgt unter dem Klassennamen. Die genauere Spezifizierung der Erweiterungen folgt in Abschnitt 3.4. Die mittlere Komponente enthält die Attribute einer Klasse. Ein Attribut wird durch folgende Syntax spezifiziert: Sichtbarkeit Name: Typ = Defaultwert {Eigenschaften} . Für die Sichtbarkeit (visibility) eines Elements kennt die UML folgende Werte: 16 KAPITEL 3. NOTATION VON UML-KLASSENDIAGRAMMEN • „+“ für öffentliche (public) Sichtbarkeit. Ein solches Element ist für alle Klassen sichtbar. • „#“ für geschützte (protected) Sichtbarkeit. Ein solches Element ist nur innerhalb der definierenden Klasse und in deren Unterklassen sichtbar. • „-“ für private (private) Sichtbarkeit. Ein solches Element ist nur innerhalb der definierenden Klasse sichtbar. Eine fehlende Sichtbarkeitsangabe bedeutet lediglich, dass die Angabe unterdrückt wird, nicht das die Sichtbarkeit nicht definiert ist. Der Name eines Attributs wird üblicherweise klein geschrieben. Für die Angabe des Typs wird meistens die entsprechende Typbezeichnung der verwendeten Programmiersprache benutzt. Besitzt ein Attribut keinen Defaultwert, so folgt die Angabe der Eigenschaften direkt nach der Angabe des Typs. Als Eigenschaften können dabei auch Zusicherungen angegeben werden. Werden Stereotypen angegeben, stehen diese vor der Sichtbarkeitsangabe. Es besteht auch die Möglichkeit, Stereotypen oder Eigenschaften über einem Attributelement anzugegeben. Sie gelten dann für sämtliche Elemente bis zur nächsten Angabe. Die unterste Komponente enthält die Methoden der Klasse. Methoden1 , die lediglich zum setzen und lesen von Attributwerten dienen, werden häufig weggelassen. Die Syntax für die Darstellung einer Methode lautet: Sichtbarkeit Name (Parameter) : Rückgabetyp {Eigenschaften} . Für die Angabe der Sichtbarkeit, der Eigenschaften und der Stereotypen gilt dasselbe wie bei den Attributen. Der Name einer Methode entspricht meist dem Methodennamen in der Implementierung. Die Angabe der Parameter und des Rückgabetyps ist optional. Werden Parameter angegeben, besitzen sie folgende Syntax: Art Name: Implementierungstyp = Defaultwert . Für die Art eines Parameters sind folgende Werte zulässig: • „in“ für Eingabeparameter, • „out“ für Ausgabeparameter, • „inout“ falls beides zutrifft. Für den Implementierungstyp und den Defaultwert gilt dasselbe wie bei den Attributen. Werden mehrere Parameter angeben, so werden diese durch Komma getrennt. Eine abstrakte Methode kann durch die Eigenschaft „{abstract}“ oder durch Kursivschrift der Signatur gekennzeichnet werden. 1 Die Begriffe Methode und Operation werden hier nicht unterschieden. 3.2. BEZIEHUNGEN 17 Der Gültigkeitsbereich (scope) gibt an, ob ein Attribut oder eine Methode statisch (static members) ist. Ein statisches Attribut (Klassenattribut) existiert nur einmal und unabhängig von den Instanzen der Klasse. Eine statische Methode (Klassenmethode) operiert auf der Klasse und nicht auf einem Objekt. Klassenattribute und -methoden werden unterstrichen dargestellt. Wenn die Angabe der Attribute oder Methoden nicht erforderlich ist, können die entsprechenden Komponenten weggelassen werden. Außerdem können benutzerdefinierte Komponenten angefügt werden, wie z.B. eine Komponente für die Angabe von Ausnahmen (exceptions). In Abbildung 3.1 werden verschiedene Darstellungen von Klassen gezeigt. Klasse A +nummer: int = 0 -flag: boolean = false +setzeFlag(in flag:boolean) #berechneWert(): int #berechneWert(): int (a) (b) Subklasse «interface» Schnittstelle (c) Abbildung 3.1: Darstellung einer Klasse in UML-Klassendiagrammen. 3.2 Beziehungen Klassendiagramme können verschiedene statische Beziehungsarten darstellen. Dazu gehören Vererbung, Assoziation und Abhängigkeit. 3.2.1 Vererbung (inheritance) Die Vererbung beschreibt Generalisierungs- und Spezialisierungsbeziehungen, d.h. Beziehungen zwischen einer allgemeineren und einer spezifischeren Klasse. Die allgemeinere Klasse wird als Superklasse (Oberklasse) und die spezifischere als Subklasse (Unterklasse) bezeichnet. Eine Subklasse erbt alle Eigenschaften (Attribute und Methoden) ihrer Superklasse und kann darüber hinaus noch weitere Eigenschaften definieren. Eine Instanz der Subklasse kann somit auch als Instanz der Superklasse verwendet werden (Polymorphismus). Die Subklasse zeigt geerbte Eigenschaften im Klassendiagramm 18 KAPITEL 3. NOTATION VON UML-KLASSENDIAGRAMMEN nur nochmals an, falls sie diese geändert hat, z.B. beim Überschreiben einer Methode (vgl. Abb. 3.1(b)). Die Vererbungsbeziehung wird durch eine Linie zwischen der Subklasse und der Superklasse repräsentiert, wobei das Linienende an der Superklasse mit einem transparenten Dreieck versehen wird, dessen Spitze auf die Superklasse zeigt. Dieselbe Darstellung wird auch für die Schnittstellenvererbung verwendet, d.h. wenn sowohl die Sub- als auch die Superklasse eine Schnittstelle ist. Wird eine Schnittstelle von einer Klasse implementiert, d.h. die Superklasse ist eine Schnittstelle und die Subklasse eine gewöhnliche Klasse, dann wird die Vererbungslinie gestrichelt gezeichnet (vgl. Abb. 3.2(b)). Besitzt eine Superklasse mehrere Subklassen, dann können die Vererbungslinien auch als Vererbungsgabel dargestellt werden (vgl. Abb. 3.2(a)). Eine Vererbungslinie kann außerdem durch einen Diskriminator beschriftet werden. Dieser gibt das Unterscheidungsmerkmal der Subklassen an, das für die Bildung der Vererbungshierarchie ausschlaggebend war. Die Subklassen einer Superklasse können auch unterschiedliche Diskriminatoren besitzen. Beim Verwenden von Vererbungsgabeln werden Stereotypen und Eigenschaften am Linienende der Superklasse platziert. Ansonsten werden sie an einer gestrichelten Linie platziert, die alle beteiligten Vererbungslinien kreuzt. Superklasse «interface» Schnittstelle Subklasse 1 Subklasse 2 Subklasse 3 Klasse 1 (a) Klasse 1 Rolle 1 1 Assoziation Rolle 2 0..1,4 Klasse 2 (c) Klasse 2 (b) Klasse 1 Ganzes 2 Aggregation Teil 0..5 Klasse 2 (d) Klasse 1 Klasse 1 Ganzes 1 Komposition Abhängigkeit Teil 0..5 Klasse 2 Klasse 2 (e) (f) Abbildung 3.2: Darstellung von Beziehungen in UML-Klassendiagrammen. 3.2. BEZIEHUNGEN 3.2.2 19 Assoziation (association) Eine Assoziation beschreibt die Beziehung zwischen Instanzen (Objekte) von Klassen. Sie wird durch eine Linie dargestellt, die die beteiligten Klassen verbindet (vgl. Abb. 3.2(c)). Eine Assoziation drückt eine Bekanntschaft der beteiligten Objekte aus. Meistens kennen sich die Objekte gegenseitig, man spricht dann von einer bidirektionalen Assoziation. Bei einer unidirektionalen Assoziation gilt die Bekanntschaft nur in eine Richtung. Die Assoziationslinie wird dann mit einer Pfeilspitze versehen, so das der Pfeil vom „wissenden“ zum „unwissenden“ Objekt zeigt. Man spricht dabei auch von Navigierbarkeit (navigability) in eine bzw. in beide Richtungen. Die Assoziationslinie kann außerdem mit einem Assoziationsnamen beschriftet werden. Um die Leserichtung der Assoziation zu bestimmen, kann beim Assoziationsname ein Pfeil in Form eines gefüllten Dreiecks angebracht werden. Bei einer binären Assoziation sind genau zwei Klassen an einer Beziehung beteiligt. Steht eine Klasse zu sich selbst in Beziehung, handelt es sich um eine reflexive Assoziation. Die verschiedenen Instanzen der Klasse, die an der reflexiven Assoziation beteiligt sind, nehmen dabei unterschiedliche Rollen ein. Eine Rolle gibt die Bedeutung einer Klasse innerhalb der Assoziation an. Der Rollenname steht an dem Ende der Assoziationslinie, an dem sich die beschriebene Klasse befindet. Vor dem Rollenname kann eine Sichtbarkeitsangabe wie bei Attributen und Methoden stehen. Auf die explizite Angabe einer Rolle kann verzichtet werden, falls diese aus dem Klassennamen abgeleitet werden kann. Existieren mehrere Assoziationsbeziehungen zwischen zwei Klassen oder handelt es sich um eine reflexive Assoziation, so muss die Rolle stets explizit angegeben werden. Assoziationslinien, Rollennamen und Assoziationsnamen können außerdem durch Zusicherungen, Eigenschaften oder Stereotypen genauer spezifiziert werden. Die Angabe erfolgt jeweils in der Nähe der entsprechenden Komponente. Die Kardinalität (multiplicity) gibt an, wieviele Objekte einer Klasse A an einer Beziehung zu einem Objekt der Klasse B beteiligt sind. Die Kardinalität steht dabei an dem Ende der Assoziationslinie, an der sich die Klasse A befindet. Sie wird dabei in folgendem Format angegeben: untere-Schranke .. obere-Schranke . Die untere Schranke gibt die minimale Anzahl und die obere Schranke die maximale Anzahl, der an der Beziehung beteiligten Objekte an. Wird nur ein einzelner Wert angegeben, bedeutet dies, dass die untere Schranke gleich der oberen Schranke ist. Es sind auch durch Komma getrennte Kombinationen dieser Angaben möglich (z.B. 1..3,5,7..∗). Ein Stern „∗“ gibt an, dass beliebig viele Objekte an einer Beziehung teilnehmen können. Bei einer unteren Schranke von 0 existiert eventuell gar keine Beziehung zu einem anderen Objekt. 20 KAPITEL 3. NOTATION VON UML-KLASSENDIAGRAMMEN Eine Assoziation kann selbst Attribute und Methoden sowie Assoziationen zu anderen Klassen besitzen. Dies kann durch eine Assoziationsklasse modelliert werden. Die Darstellung einer Assoziationsklasse unterscheidet sich nicht von der Darstellung einer gewöhnlichen Klasse. Die Assoziationsklasse wird aber durch eine gestrichelte Linie mit der Assoziationslinie verbunden. Es existieren zwei Spezialfälle von Assoziationsbeziehungen, die Aggregation und die Komposition. Die Aggregation beschreibt eine Beziehung, bei der ein Objekt A Teil eines anderen Objekts B ist. Die Klasse des Objekts A wird bezüglich der Aggregation als Teilklasse bezeichnet, die Klasse des Objekts B als Aggregatsklasse. Die Unterscheidung zwischen Assoziation und Aggregation ist nicht immer einfach. Man spricht aber grundsätzlich nur dann von Aggregation, wenn das Teil ein fester Bestandteil des Ganzen ist. Die Aggregation wird durch einen transparenten Diamanten am Ende der Assoziationslinie der Aggregatsklasse dargestellt (vgl. Abb. 3.2(d)). Bei einer Komposition wird der Diamant gefüllt gezeichnet (vgl. Abb. 3.2(e)). Die Komposition stellt einen Sonderfall der Aggregation dar mit den folgenden Eigenschaften: • Ein Teil existiert nur höchstens so lange wie das Ganze. Beim Löschen des Ganzen werden auch die Teile gelöscht. • Die Kardinalität der Aggregatsklasse darf nicht größer als eins sein (strong ownership). 3.2.3 Abhängigkeit (dependency ) Eine Abhängigkeit ist ein Beziehung zwischen zwei Elementen, bei der die Änderung des einen Elements möglicherweise auch eine Änderung des anderen Elements (abhängiges Element) erforderlich macht. Bei einer Abhängigkeit stehen die Elemente selbst in Beziehung zueinander, unabhängig von den Instanzen. Abhängigkeiten werden durch einen gestrichelten Pfeil dargestellt, wobei sich das abhängige Element am Fuß des Pfeils befindet (vgl. Abb. 3.2(f)). Der Pfeil kann durch einen Namen oder einen Stereotyp beschriftet werden. Abhängigkeiten, die durch andere Beziehungsarten impliziert werden, werden normalerweise nicht nochmals gesondert dargestellt. 3.3 Pakete (packages) Pakete dienen der Gruppierung von Elementen. Ein Paket ist eine Art benannter Behälter für Elemente und kann auch weitere Pakete enthalten. Bei einer geeigneten Gruppierung sorgen Pakete für ein übersichtliches System. Pakete werden durch ein Rechteck mit Reiter dargestellt (wie ein Aktenordner). Wird der Inhalt des Pakets angezeigt, steht der Paketname im Reiter, ansonsten wird er innerhalb des Rechtecks platziert (vgl. Abb. 3.3). 3.4. ERWEITERUNGSMECHANISMEN 21 Stereotypen werden über den Paketnamen und Eigenschaften oder ZusichePaket 2 Paket 1 Klasse 1 Klasse 2 Abbildung 3.3: Darstellung von Paketen in UML-Klassendiagrammen. rungen hinter oder unter dem Paketnamen angegeben. Ein Paket definiert einen Namensraum. Die in einem Paket enthaltenen Klassen- und Paketnamen müssen eindeutig sein, es können aber Klassen oder Pakete mit gleichem Namen in verschiedenen Paketen existieren. Eine Referenz zu einer Klasse in einem anderen Paket wird durch Paketname::Klassenname angegeben. Da Pakete ineinander verschachtelt sein können, kann der Pfad zu einer Klasse aus mehreren durch „::“ getrennten Paketnamen bestehen. Der qualifizierte Name einer Klasse, der aus Paketpfad und Klassenname besteht, ist also immer eindeutig. Beziehungen zwischen Paketen werden durch Abhängigkeiten modelliert. 3.4 Erweiterungsmechanismen Die Anzahl verschiedener Notationselemente in Klassendiagrammen ist recht gering. Um dennoch möglichst viel Semantik in den Diagrammen unterbringen zu können, bietet die UML Erweiterungen für die Angabe von Zusicherungen, Eigenschaften, Stereotypen und Notizen an. Da es sich dabei, bis auf die Notiz, lediglich um eine geeignete Beschriftung der Grundelemente handelt, wird die Anzahl der verschiedenen Elemente weiterhin überschaubar gehalten. 3.4.1 Zusicherungen (constraints) Durch Zusicherungen kann man Einschränkungen und Invarianten für Elemente formulieren. Zusicherungen sind Ausdrücke, die stets wahr sein müssen. In der UML kann eine Zusicherung frei formuliert werden, sie muss dabei lediglich von geschweiften Klammern umschlossen sein. Falls z.B. ein Kunde einer Firma ein Mindestalter von 18 haben muss, kann dies durch die 22 KAPITEL 3. NOTATION VON UML-KLASSENDIAGRAMMEN Zusicherung {Alter >= 18} ausgedrückt werden. Die Formulierung kann sowohl in Umgangssprache als auch durch einen Ausdruck einer Programmiersprache erfolgen. Inzwischen existieren auch spezielle Sprachen für die Formulierung von Zusicherungen, wie die Object Constraint Language (OCL). Neben den benutzerdefinierten Zusicherungen existieren auch bereits vordefinierte Zusicherungen in der UML. Einige davon werden in Tabelle 3.1 erläutert. Gilt eine Zusicherung für mehrere Elemente, kann sie sich auch in einer Notiz (s. Notizen auf S.23) befinden und durch gestrichelte Linien mit den entsprechenden Elementen verbunden werden. Zusicherung Element {complete} Vererbung Bedeutung Alle Subklassen wurden spezifiziert, es können keine weiteren hinzukommen. {ordered} Assoziation Menge der Objekte auf der Zielseite der Assoziation sind geordnet. {xor} Assoziation Objekt kann nur an einer der angegebenen Assoziationen beteiligt sein. Tabelle 3.1: Vordefinierte Zusicherungen der UML. 3.4.2 Eigenschaften (properties) Für die Angabe von Eigenschaften eines Elements, für die keine graphische Notation existiert, können benutzerdefinierte Eigenschaften verwendet werden. Diese werden als Schlüsselwort-Wert-Paare (tagged value) angegeben und wie Zusicherungen von geschweiften Klammern umschlossen. In einem Klammerpaar können mehrere durch Komma getrennte Eigenschaften stehen. Eine Eigenschaft besitzt folgende Syntax: Schlüsselwort = Wert . Das Schlüsselwort gibt den Namen der Eigenschaft an, der innerhalb des betreffenden Elementtyps eindeutig sein muss. Besitzt die Eigenschaft einen boolschen Typ, so ist ihr Defaultwert true, d.h. die Angabe des Wertes kann entfallen. Trifft eine Eigenschaft nicht zu (Wert = false) wird sie einfach nicht angegeben. Einige von der UML vordefinierte Eigenschaften werden in Tabelle 3.2 aufgezählt. 3.4.3 Stereotypen (stereotypes) Stereotypen ermöglichen die genauere Klassifizierung von Elementen. Ein Klassenelement repräsentiert z.B. sowohl eine normale Klasse wie auch eine 3.4. ERWEITERUNGSMECHANISMEN Eigenschaft {abstract} 23 Element Methode, Klasse Bedeutung Alternative Darstellung von abstrakten Klassen bzw. Methoden (anstatt kursivem Namen) {frozen} Attribut Ein einmal definierter Wert kann nicht mehr geändert werden {query} Methode Methode hat keine Seiteneffekte (Systemzustand bleibt erhalten) Tabelle 3.2: Vordefinierte Eigenschaften der UML. Schnittstelle. Durch die Angabe eines Stereotyps kann nun ein entsprechender Untertyp des Elements gebildet werden (vgl. Abb. 3.1(c)). Im Unterschied zu Eigenschaften, erweitern Stereotypen das Metamodell und somit die Modellierungssprache. Tabelle 3.3 zeigt einige von der UML vordefinierte Stereotypen und deren Bedeutung. Der Name eines Stereotyps wird stets von französischen Anführungszeichen («, ») umschlossen. Neben vordefinierten Stereotypen können auch benutzerdefinierte eingeführt werden. Stereotyp «access» Bedeutung Quellpaket darf öffentliche Elemente des Zielpaketes referenzieren «constructor» Methode Methode ist ein Konstruktor «extends» Vererbung Vererbung um erweiterte Funktionalität anzubieten «interface» Klasse Klasse ist eine Schnittstelle «utility» Klasse Klasse besitzt nur statische Methoden und Attribute Tabelle 3.3: Vordefinierte Stereotypen der UML. 3.4.4 Element Abhängigkeit Notizen (notes) Wichtige Informationen über Elemente, die mit den bisher vorgestellten Erweiterungsmechanismen nicht dargestellt werden können, können durch Notizen in das Klassendiagramm aufgenommen werden. Eine Notiz dient jedoch nicht der Erweiterung der Semantik, sie wird lediglich zur genaueren Erläuterung eines Sachverhalts oder einer Entscheidung verwendet. Eine Notiz wird durch ein Rechteck mit einem Eselsohr in der rechten oberen Ecke dargestellt und kann beliebigen Text enthalten (vgl. Abb. 3.4). Sie kann durch eine gestrichelte Linie mit den betreffenden Elementen verbunden werden. 24 KAPITEL 3. NOTATION VON UML-KLASSENDIAGRAMMEN Notiz für Klasse 1 und Klasse 2 Klasse 1 Notiz zur Assoziation Klasse 2 Abbildung 3.4: Darstellung einer Notiz in UML-Klassendiagrammen. Es existieren noch weitere Erweiterungen und Elemente wie z.B. parametrisierte Klassen (templates), abgeleitete Assoziationen, abgeleitete Attribute und n-fach Assoziationen. Da die meisten Klassendiagramme aber ohne diese Elemente auskommen, werden sie hier nicht erläutert. Die genaue Spezifikation aller Elemente und Erweiterungen befindet sich in [24]. 3.5 Konsequenzen für den Layoutalgorithmus In den vergangenen Abschnitten wurden die verschiedenen Elemente von UML-Klassendiagrammen vorgestellt. Da der Layoutalgorithmus einen Graphen als Eingabe erwartet, müssen die Elemente entsprechend auf diesen abgebildet werden. Klassen und Pakete werden dabei auf die Knoten und Beziehungen auf die Kanten des Graphen abgebildet. Für den Eingabegraph gilt außerdem folgendes: • Da eine Klasse zu sich selber in Beziehung stehen kann, enthält der Eingabegraph möglicherweise Selbstschleifen. • Da verschiedene Beziehungen zwischen zwei Klassen existieren können, enthält der Eingabegraph möglicherweise Mehrfachkanten. • Die Größe der Knoten hängt von der Anzahl und der Länge der Attributund Methodensignaturen ab und ist somit variabel. Der Eingabegraph enthält also Knoten unterschiedlicher Größe. • UML-Klassendiagramme lassen sich auf allgemeine, teilgerichtete Graphen abbilden. • Die Elemente von UML-Klassendiagrammen können zusätzliche Beschriftungen enthalten, wie z.B. Rollennamen, Kardinalitäten und Stereotypen. Diese müssen an den Eingabegraphen übermittelt und dann vom Layoutalgorithmus geeignet platziert werden. Kapitel 4 Ästhetikkriterien Ein Layoutalgorithmus soll möglichst ansprechende Zeichnungen erzeugen. Um dies zu erreichen müssen zunächst einmal die ästhetischen Anforderungen ermittelt werden, die an die entstehenden Zeichnungen gestellt werden. Da die Graphen, je nach Anwendungsbereich, eine unterschiedliche Bedeutung besitzen, variieren die Anforderungen entsprechend. Ästhetikkriterien legen Grundsätze fest, die für eine möglichst übersichtliche und verständliche Darstellung der durch den Graphen repräsentierten Elemente und Beziehungen sorgen sollen. Bei Klassendiagrammen werden, wie bereits erwähnt, Klassen- und Packetelemente auf Knoten und Beziehungen auf Kanten abgebildet. Die UML gibt die Bedeutung und Notation der Elemente vor, aber nicht wie diese im Diagramm möglichst lesbar dargestellt werden. Die ermittelten Ästhetikkriterien müssen vom Layoutalgorithmus durch eine entsprechende grafische Anordnung der Elemente realisiert werden. Damit ein Layoutalgorithmus in der Praxis sinnvoll eingesetzt werden kann, müssen die gewählten Ästhetikkriterien von Algorithmen in polynomieller Zeit umgesetzt werden können. In den folgenden beiden Abschnitten werden verschiedene syntaktische und semantische Ästhetikkriterien vorgestellt. Anschließend wird deren Relevanz und Bedeutung bezüglich Klassendiagrammen untersucht, um eine geeignete Menge zu finden, die vom Layoutalgorithmus berücksichtigt werden soll. 4.1 Syntaktische Ästhetikkriterien Bereits aus der abstrakten Graphstruktur lassen sich Ästhetikkriterien ableiten. Diese werden als syntaktische Ästhetikkriterien bezeichnet, da sie keinen Bezug auf die Semantik der einzelnen Elemente nehmen. Sie legen einfache, grafische Grundsätze fest, die allgemein für Zeichnungen von Graphen zutreffen und somit meistens sinnvoll eingesetzt werden können. Es folgt eine Auswahl der verbreitetsten syntaktischen Ästhetikkriterien [6, 32]: 26 KAPITEL 4. ÄSTHETIKKRITERIEN Abstand zwischen Knoten Um eine lesbare Zeichnung zu bekommen, sollten sich die Knoten nicht überlappen und nicht zu nahe aneinander platziert werden. Der geeignete Abstand hängt von der Knotengröße und der Anzahl der Kanten an den Knoten ab. Werden Knoten zu weit weg voneinander platziert, führt dies zu einem höherem Flächenverbrauch sowie zu längeren Kanten zwischen den Knoten. Länge der Kanten Zeichnungen mit kurzen Kanten sind in der Regel einfacher zu lesen, da sich die verbundenen Knoten nahe aneinander befinden. Lange Kanten besitzen oft mehrere Kreuzungen und Knicke. Sind Kanten zu kurz, ist der Abstand zwischen zwei Knoten zu gering. Es kann auch auf eine möglichst einheitliche Kantenlänge geachtet werden. Dieses Kriterium ist aber schwer zu realisieren und steht im Konflikt mit einigen anderen, noch folgenden Kriterien. Abstand zwischen Knoten und Kanten Kanten, die an einem Knoten vorbeigehen, sollten nicht zu dicht an diesem platziert werden, damit die Zeichnung übersichtlich bleibt. Kanten sollten sich außerdem nicht überlappen. Zwei parallele Kantensegmente sollten einen Mindestabstand einhalten, damit sie besser unterschieden werden können. Anzahl der Kantenkreuzungen Kreuzungen zwischen Kanten machen den Verlauf einer Kante unübersichtlich. Bei vielen Kreuzungen wird eine Zeichnung daher schnell unleserlich. Es gilt deshalb, die Anzahl der Kreuzungen möglichst klein zu halten. Ganz vermeiden lassen sich Überkreuzungen nur bei planaren Graphen. UML-Klassendiagramme sind aber i.a. keine planaren Graphen. Anzahl der Kantenknicke Kantenknicke werden von Algorithmen produziert, die die Kanten nicht geradlinig oder als Kurven zeichnen. Durch viele Kantenknicke wird eine Zeichnung schwerer lesbar, da dem Kantenverlauf schwerer zu folgen ist. Neben der Minimierung der Gesamtzahl kann auch auf die Ausgewogenheit von Knicken geachtet werden, d.h. jede Kante soll z.B. höchstens k Knicke besitzen. Verteilung der Knoten über die Zeichenfläche Eine gleichmäßige Verteilung der Knoten über die Zeichenfläche führt zu einer übersichtlichen Zeichnung bezüglich der Knoten. Allerdings steht dieses Kriterium in Konflikt zu vielen anderen Kriterien. Eine 4.1. SYNTAKTISCHE ÄSTHETIKKRITERIEN 27 gleichmäßige Verteilung kann z.B. zu langen Kanten und vielen Kantenknicken führen. Gerade wenn Graphelemente eine spezielle Semantik haben, ist dieses Kriterium eher unpraktikabel. Platzierung von Väterknoten Häufig werden Väterknoten zentriert über ihren Kinderknoten dargestellt. Dies ist vor allem dann sinnvoll, wenn die hierarchische Struktur des Graphen in den Vordergrund gestellt werden soll. Durch die Zentrierung wird die Hierarchie sehr übersichtlich dargestellt. Das Kriterium kommt oft bei Baumstrukturen zum Einsatz. Platzierung von Geschwisterknoten Geschwisterknoten eines Baumes sollten sich auf einer einheitlichen Höhe befinden. Das Kriterium führt zu übersichtlicheren Diagrammen, da die Hierarchiestufen leichter erkennbar sind. Symmetrie Symmetrie in einer Zeichnung führt zur schnelleren Erfassung des dargestellten Sachverhaltes. Symmetrie ist aber nicht immer im geeigneten Maße vorhanden bzw. ist sie schwer zu erfassen. Versucht man möglichst viel Symmetrie darzustellen, werden andere Kriterien vernachlässigt, z.B. entstehen oft zusätzliche Kantenkreuzungen. Winkel zwischen den Kanten Der Winkel zwischen zwei aufeinanderfolgenden Kanten an einem Knoten sollte möglichst groß sein, um die Kanten besser unterscheiden zu können. Bei kleinen Winkeln ist die Unterscheidung der Kanten in der Nähe des Knotens schwierig. Verwendung der Zeichenfläche Oft soll die benötigte Zeichenfläche möglichst klein gehalten werden. Dieses Kriterium wird vor allem beim Schaltungsentwurf (VLSI) optimiert. Auch bei UML-Klassendiagrammen ist es vorteilhaft, kompakte und somit leichter überschaubare Zeichnungen zu erstellen. Natürlich müssen die Mindestabstände zwischen Knoten trotzdem eingehalten werden. Das Kriterium wird teilweise schon durch die Kriterien „geringe Länge von Kanten“ und „geeigneter Knotenabstand“ realisiert. Seitenverhältnis Zeichnungen mit ausgewogenem Seitenverhältnis sind normalerweise übersichtlicher als Zeichnungen, die übermäßig breit oder hoch sind. Allerdings führen Hierarchistrukturen oft zu einem unausgewogenem Seitenverhältnis, wenn man die hierarchische Struktur übersichtlich darstellen will. Orthogonalität Bei einer orthogonalen Zeichnung werden die Kanten durch vertikale 28 KAPITEL 4. ÄSTHETIKKRITERIEN und horizontale Segmente dargestellt. Orthogonale Zeichnungen wirken meist sehr übersichtlich, auch wenn sie Kantenknicke enthalten. Die Orthogonalität sorgt außerdem für die Einhaltung anderer Kriterien, z.B. entstehen keine kleinen Winkel zwischen den Kanten. 4.2 Semantische Ästhetikkriterien Neben den syntaktischen existieren auch semantische Ästhetikkriterien. Diese nehmen Bezug auf die Bedeutung der einzelnen Elemente des Graphen und besitzen deshalb zusätzliche Informationen über die Elemente. Die semantischen Ästhetikkriterien sind deshalb stark vom Anwendungsbereich abhängig. Für Klassendiagramme sind u.a. folgende semantische Ästhetikkriterien [12] verbreitet: Richtung der Kanten Ein Graph, der ein UML-Klassendiagramm repräsentiert, besteht aus hierarchischen und nicht hierarchischen Kanten. Die hierarchischen Kanten modellieren Vererbungs- und Implementierungsbeziehungen. Solche Kanten werden oftmals in eine einheitliche Richtung gezeichnet, wodurch die Hierarchiestruktur besser zur Geltung kommt (vgl. Abb. 4.1(b)). Platzierung verwandter Elemente Verwandte Elemente, die z.B. durch Komposition oder n-fach Assoziation entstehen, sollten möglichst nahe aneinander platziert werden. Um die Lesbarkeit zu erhöhen, sollten Assoziationsklassen außerdem möglichst nahe an der dazugehörigen Assoziationlinie stehen. Platzierung von Erweiterungen Erweiterungen und andere Beschriftungen sollten so platziert werden, dass sie dem entsprechenden Element zugeordnet werden können und sich möglichst nicht überlappen. Darstellung der Vererbungshierarchie In der UML existieren zwei Varianten für die Darstellung von Vererbungshierarchien. Entweder wird jede Vererbungsbeziehung durch eine separate Vererbungslinie zwischen Super- und Subklasse symbolisiert, oder die Vererbungslinien aller Subklassen einer Superklasse treffen sich an einem Punkt und gehen dann gemeinsam zur Superklasse, wobei sie eine Gabelform wie in Abb. 4.1(c) annehmen. Das Benutzen von Vererbungsgabeln führt zwar zu zusätzlichen Knicken, diese dienen aber der übersichtlicheren Darstellung der Vererbungshierarchie. Font und Textausrichtung Die Textausrichtung kann horizontal, vertikal oder beliebig sein. Die Wahl des Fonts spielt für den Algorithmus keine Rolle. 4.3. AUSWAHL GEEIGNETER ÄSTHETIKKRITERIEN 29 1 1 5 3 1 6 2 (a) 4 2 4 3 3 5 (b) 6 2 4 5 6 (c) Abbildung 4.1: Verschiedene Zeichnungen eines Graphen. Die hierarchischen Beziehungen kommen in den Zeichnungen (b) und (c) besser zur Geltung. Die hier aufgezählten Ästhetikkriterien sind ausschließlich statische Kriterien. Dynamische Ästhetikkriterien nehmen Bezug auf die Veränderung eines Diagramms, wenn sich der zugrundeliegende Graph ändert. Ein wichtiges dynamisches Kriterium ist die Minimierung der Veränderung der bestehenden Zeichnung („preserving the mental map“ [10]), wenn neue Elemente hinzugefügt werden. Das Kriterium steht aber oft mit anderen in Konflikt, z.B. mit der Minimierung der Anzahl der Kantenkreuzungen. Dynamisches Graphzeichnen ist eine recht neue Disziplin und befindet sich noch in einem Anfangsstadium. Da Layouttools oft in interaktiven Anwendungen eingesetzt werden, müssen die verwendeten Algorithmen effizient sein. Viele der hier aufgezählten Ästhetikkriterien sind aber NP-harte Optimierungsprobleme, wie die Kreuzungsminimierung eines allgemeinen Graphen [31]. Die meisten Algorithmen sind deshalb Heuristiken, die oft eine gute Nährung aber meist keine optimale Lösung bieten. 4.3 Auswahl geeigneter Ästhetikkriterien In den letzten beiden Abschnitten wurden verschiedene syntaktische und semantische Ästhetikkriterien vorgestellt. In diesem Abschnitt sollen nun die für Klassendiagramme geeignetsten ausgewählt und deren Priorität festgelegt werden. Dies ist notwendig, da sich wie gesehen, einige Kriterien wiedersprechen. Die Priorität legt die Wichtigkeit eines Ästhetikkriteriums gegenüber einem anderen fest. Das Kriterium mit der niedrigeren Priorität wird nur insoweit angewendet, wie es das Kriterium mit der höheren Priorität nicht negativ beeinflusst. Es existieren verschiedene Studien, die die Auswirkungen von Ästhetikkriterien untersuchen. In [25] wurden die Auswirkungen von fünf verschiede- 30 KAPITEL 4. ÄSTHETIKKRITERIEN nen syntaktischen Ästhetikkriterien auf die Lesbarkeit von Zeichnungen allgemeiner Graphen untersucht. Für die Untersuchung wurden Personen Fragen über die Graphen gestellt, wobei die Zeichnungen die Ästhetikkriterien unterschiedlich stark berücksichtigten. Die Qualität einer Zeichnung wurde anhand der Beantwortungsgenauigkeit und -geschwindigkeit der Fragen ermittelt. Ein Ästhetikkriterium wurde dann als nützlich angesehen, wenn bei dessen Verwendung die Antwortgeschwindigkeit oder die Genauigkeit der Antwort positiv beeinflusst wurde. Bei der Studie ging die Minimierung der Anzahl der Kantenkreuzungen als das wichtigste Kriterium hervor. Auch die Minimierung der Anzahl der Kantenknicke sowie die Maximierung der Symmetrie hatten Auswirkungen auf die Lesbarkeit. Für die Maximierung des kleinsten Winkels zwischen Kanten und die Maximierung der Orthogonalität wurden nur geringe Auswirkungen festgestellt. Da die Bedeutung eines Ästhetikkriteriums vom jeweiligen Anwendungsgebiet abhängig ist, sind die Ergebnisse für allgemeine Graphen nicht automatisch auch auf Klassendiagramme übertragbar. Die von Benutzern bevorzugten Ästhetikkriterien bezüglich Klassendiagrammen wurden in [26] ermittelt. Dazu mussten Versuchspersonen jeweils von zwei alternativen Darstellungen eines Graphen, die von ihnen bevorzugte Darstellung wählen. Tabelle 4.1 zeigt einen Auszug des Ergebnisses der Untersuchung. Wie zu sehen ist, Ästhetik Bevorzugung (in %) weniger Kantenkreuzungen 93% weniger Kantenknicke 91% nur horizontale Beschriftungen 86% Vererbungsgabeln 76% kompaktere Zeichnung 73% mehr Orthogonalität 61% Tabelle 4.1: Ästhetik Präferenzen für Klassendiagramme (Auszug aus [26]) gingen auch hier die Kriterien „Minimierung der Anzahl der Kantenknicke“ und „Minimierung der Anzahl der Kantenkreuzungen“ als die wichtigsten Kriterien hervor. Ein in [28] beschriebenes Experiment, verwendete einen anderen Ansatz zur Ermittlung der wichtigsten Ästhetikkriterien von Klassendiagrammen. Wie bei der Studie über syntaktische Ästhetikkriterien, mussten Versuchspersonen Fragen zu bestehenden Klassendiagrammen beantworten, die ein Kriterium in einem bestimmten Maß erfüllten. Je nach Genauigkeit und Geschwindigkeit der Beantwortung wurde dann auf die Wichtigkeit eines Kriteriums geschlossen. Das Experiment zeigte, dass die von Versuchspersonen bevorzugten Kriterien nicht unbedingt zu einer höheren Lesbarkeit führen, 4.3. AUSWAHL GEEIGNETER ÄSTHETIKKRITERIEN 31 die statistisch nachweisbar ist. Für die Knotenverteilung, die Kantenlänge, die Symmetrie, die Richtung der Kanten und die Orthogonalität konnten keine Auswirkungen nachgewiesen werden. Für die Anzahl der Kantenknicke entsprach das Ergebnis den Erwartungen. Weniger Knicke wirkten sich positiv auf die Lesbarkeit eines Diagramms aus. Die Ergebnisse des Experiments führten zu der Annahme, dass die Wichtigkeit vieler Ästhetikkriterien stark von der semantischen Gruppierung von verwandten Objekten abhängt. Bei verwandten Objekten ist es z.B. wichtiger, diese nahe beieinander zu platzieren, als auf möglichst viel Symmetrie zu achten. In der Praxis tauchen in Klassendiagrammen viele Notationsvarianten auf. In [27] wurde untersucht, welche Varianten von Anwendern bevorzugt werden. Dabei wurde unter anderem festgestellt, dass nahezu alle Versuchspersonen eine Aufwärtszeichnung der Vererbungskanten (alle Kanten zeigen nach oben) als intuitiver beurteilten. Die meisten Personen bevorzugten außerdem die Verwendung von Vererbungsgabeln zum Zeichnen von Vererbungshierarchien, da sie diese bei größeren Diagrammen übersichtlicher fanden. Die Ergebnisse zeigten aber auch, dass die Benutzer bei diesen Varianten mehr Fehler bei der Beantwortung von Fragen zu den Klassendiagrammen gemacht haben als bei den Alternativen. Das wurde damit erklärt, dass die Alternativen wohl weniger intuitiv waren und die Benutzer sich daher stärker konzentrieren mussten. Dieses Ergebnis sollte jedoch nicht dazu führen, Zeichnungen absichtlich schwer zugänglich zu machen. Für den zu entwickelten Layoutalgorithmus wurden aufgrund der Erkenntnisse der Studien folgende Ästhetikkriterien als Eckpfeiler gewählt: 1. Orthogonalität 2. Verwenden von Vererbungsgabeln 3. einheitliche Kantenrichtung (upward planarity) 4. einheitliche Höhe von Geschwisterknoten bei der Vererbung 5. wenige Kantenkreuzungen 6. wenige Kantenknicke Bei syntaktischen Graphen spielt die Maximierung der Orthogonalität noch keine Rolle. Bei semantischen Graphen gewinnt sie jedoch an Bedeutung [26]. Eine orthogonale Zeichnung sorgt dafür, dass die Winkel zwischen den Kanten nicht zu klein sind. Für orthogonale Zeichnungen existieren außerdem Algorithmen, die nur wenige Kreuzungen und Knicke produzieren. Dadurch bietet sich ein orthogonaler Ansatz für den zu entwickelnden Layoutalgorithmus an. Die Verwendung von Vererbungsgabeln und einer einheitlichen Kantenrichtung wird von vielen Benutzern bevorzugt. Durch die einheitliche Kantenrichtung werden Vererbungsstrukturen besonders übersichtlich dargestellt. Beide Kriterien beziehen sich nur auf eine bestimmte Kantenmenge. 32 KAPITEL 4. ÄSTHETIKKRITERIEN Die Ästhetikkriterien „Minimierung der Anzahl von Kantenkreuzungen“ und „Minimierung der Anzahl von Kantenknicken“ gingen aus den obigen Studien als die wichtigsten Kriterien hervor. Das Kriterium „einheitlichen Höhe von Geschwisterknoten“ wurde in keiner der Studien untersucht. Die Anwendung des Kriteriums ist aber gerade bei Vererbungsstrukturen wünschenswert. Da die bevorzugten Ästhetikkriterien auch immer individuell vom Benutzer abhängen, sollte der Layoutalgorithmus möglichst flexibel sein und eine Anpassung an bestimmte Kriterien ermöglichen. Die Priorität der gewählten Ästhetikkriterien entspricht der aufgezählten Reihenfolge, d.h. jede Zeichnung ist auf jeden Fall orthogonal. Die Kriterien „Benutzen von Vererbungsgabeln“ und „einheitliche Kantenrichtung“ werden angewendet, obwohl sie zu mehr Kreuzungen und Knicken führen können. Das Kriterium „einheitliche Höhe von Geschwisterknoten“ wird nur angewendet, falls dadurch die einheitliche Kantenrichtung erhalten bleibt. Kapitel 5 Der Topology-Shape-Metrics Ansatz Dem zu entwickelnden Layoutalgorithmus für UML-Klassendiagramme soll ein orthogonaler Ansatz zugrundeliegen, der auf dem sogenannten TopologyShape-Metrics Ansatz basiert. Der Topology-Shape-Metrics Ansatz wird im folgenden Abschnitt erläutert. Anschließend werden existierende Algorithmen vorgestellt, die den Topology-Shape-Metrics Ansatz realisieren. Im nächsten Kapitel werden diese Algorithmen dann entsprechend modifiziert, um die spezifischen Anforderungen, die sich für Klassendiagramme ergeben, zu integrieren. Für einen nicht zusammenhängenden Graph G, wird der Layoutprozess für alle Zusammenhangkomponenten von G ausgeführt. Nach dem Layouten der einzelnen Komponenten, werden diese dann zum Gesamtlayout zusammengesetzt. Im folgenden kann also immer von einem zusammenhängenden Eingabegraph für die einzelnen Algorithmen ausgegangen werden. 5.1 Definition Für das Zeichnen von Graphen existieren verschiedene Paradigmen. Beim orthogonalen Graphzeichnen wird gewöhnlich der Topology-Shape-Metrics Ansatz [32] verwendet, der den Layoutvorgang eines Graphen in folgende drei Phasen unterteilt: 1. In der ersten Phase wird die Topologie (topology) des Graphen festgelegt. Die Topologie beschreibt die Anordnung der Graphelemente. Zwei Graphen besitzen die gleiche Topologie, wenn der eine durch Umformung in den anderen überführt werden kann, ohne dass dabei die Kantenordnung um die Knoten und somit die Faces verändert werden. Die Topologie eines Graphen wird durch die planare Repräsentation beschrieben, welche aus einer ebenen Einbettung des Graphen abgeleitet werden kann. Die Phase wird deshalb auch oft als Einbettung 34 KAPITEL 5. DER TOPOLOGY-SHAPE-METRICS ANSATZ bezeichnet. Nicht planare Graphen werden planarisiert, indem Kantenkreuzungen durch Knoten ersetzt werden. 2. In der zweiten Phase wird die Form (shape) des Graphen festgelegt. Die Form wird durch die Angabe der Kantenknicke und den Winkeln zwischen den Kanten angegeben. Zwei Graphen besitzen die gleiche Form, wenn sie die gleiche Topologie besitzen und man sie durch Veränderung der Kantenlängen (und Knotengröße) ineinander überführen kann. Möchte man eine orthogonale Zeichnung erzeugen, so nennt man diese Phase Orthogonalisierung. Die Form wird dann durch die orthogonale Repräsentation beschrieben. 3. In der dritten Phase wird die Metrik (metric) bestimmt. Die Metrik legt die Größe der Knoten und die Länge der Kanten fest. Zwei Graphen besitzen die gleiche Metrik, falls sie die gleiche Topologie und Form besitzen und bis auf Translation und Rotation identisch zueinander sind. Beim orthogonalen Graphzeichnen wird die Metrik durch die Kompaktierung bestimmt, wodurch dann eine orthogonale Gittereinbettung entsteht. Vor der Kompaktierung müssen die bei der Planarisierung hinzugefügten Knoten wieder entfernt werden. Die Topologie, die Form und die Metrik sind charakteristische Eigenschaften von Gitterzeichnungen. Die einzelnen Phasen werden durch verschiedene Algorithmen realisiert, die verschiedene Ästhetikkriterien fokusieren. Jede Kreuzung, die in der ersten Phase erzeugt wird, wird durch einen künstlichen Knoten repräsentiert. Zuviele solcher Kreuzungsknoten führen oft zu schlechteren Layoutresultaten. In der ersten Phase wird deshalb gewöhnlich ein Algorithmus eingesetzt, der möglichst wenig Kantenkreuzungen erzeugt. Das Hinzufügen oder Entfernen einer Kantenkreuzung bedeutet auch immer ein Ändern der Topologie. Für die zweite Phase wird gewöhnlich ein Algorithmus verwendet, der die Anzahl der Kantenknicke minimiert. Dieses Ästhetikkriterium kann erst in der zweiten Phase berücksichtigt werden, da die erste Phase keine Form und somit auch keine Knicke kennt. In der dritten Phase wird gewöhnlich ein Algorithmus eingesetzt, der die Fläche minimiert. Eine orthogonale Zeichnung wird also Schritt für Schritt aufgebaut. Das bedeutet auch, dass jede Phase auf das Ergebnis der vorausgegangenen Phase aufsetzt. Dies hat u.a. zur Folge, dass die Minimalität der Kantenknicke nur bezüglich der gegebenen Topologie und damit mit bereits festgelegten Kantenkreuzungen bestimmt wird. Durch die Aufteilung in unterschiedliche Phasen, erhält man eine gewisse Unabhängigkeit bei der Algorithmenwahl für eine Phase. 5.2. EINBETTUNG 5.2 35 Einbettung Um die erste Phase des Topology-Shape-Metrics Ansatz zu realisieren, muss eine planare Repräsentation P für den Eingabegraph G gefunden werden. Da Graphen, die UML-Klassendiagramme modellieren, im allgemeinen nicht planar sind, müssen diese erst planar gemacht werden. Diesen Vorgang nennt man Planarisierung. Sie basiert darauf, dass ein Graph, der nicht planar ist, dadurch planar gemacht werden kann, dass jede Kantenkreuzung durch einen Knoten ersetzt wird (vgl. Abb. 5.1). Alle gerichteten Kanten ED des teilgerichteten Eingabegraphen G = (V, ED ∪EU ) sollen aufwärtsgerichtet gezeichnet werden und müssen deshalb aufwärtsplanar eingebettet werden. Der von der Kantenmenge ED induzierte Subgraph von G muss dazu azyklisch sein. c Abbildung 5.1: Ersetzung einer Kantenkreuzung durch einen Knoten. Der hier vorgestelle Planarisierungsalgorithmus geht folgendermaßen vor: Zuerst werden Selbstschleifen und Mehrfachkanten aus dem Eingabegraph G entfernt. Beim Entfernen von Mehrfachkanten muss darauf geachtet werden, dass die bleibende Kante eine gerichtete ist, falls eine solche existiert. Ansonsten könnte eine gerichtete Mehrfachkante eventuell nicht aufwärtsplanar eingebettet werden. Für den zu planarisierenden Graphen G = (V, E) wird zunächst ein maximaler planarer Subgraph GSub = (V, F ) gesucht, wobei gilt: F ⊆ E. Nach dem Bestimmen des maximalen planaren Subgraphs, werden die entfernten Mehrfachkanten und Selbstschleifen sowie die Restkanten, die nicht in GSub enthalten sind, so in den Subgraphen eingefügt, dass möglichst wenige Kreuzungen entstehen und alle gerichteten Kanten aufwärtsplanar sind. Zwar ist das Problem des Findens eines maximalen planaren Subgraphen für allgemeine Graphen NP-vollständig, es existieren aber verschiedene Heuristiken, die gute Ergebnisse liefern. Die hier beschriebene Heuristik ist die von Goldschmidt und Takvorian (GT-Heuristik) [21]. 5.2.1 GT-Heuristik Die GT-Heuristik besteht aus zwei Phasen. In der ersten Phase wird eine Knotenfolge ermittelt, die alle Knoten des Eingabegraphen enthält. Stellt man sich die Knotenfolge auf einer Linie angeordnet vor, dann versucht die zweite Phase die maximale Anzahl sich nicht überschneidender Kanten F 36 KAPITEL 5. DER TOPOLOGY-SHAPE-METRICS ANSATZ zu finden, die über oder unter der Linie angeordnet werden können (vgl. Abb. 5.2). Es entstehen dabei zwei disjunkte Kantenmengen A ⊆ E und B ⊆ E, für die gilt: |A| + |B| ist maximal und kein Kantenpaar aus A bzw. B schneidet sich bezüglich der Knotenfolge. Es gilt also F = A ∪ B. Sei π : V → N die Funktion, die die Position eines Knotens in der Knotenfolge angibt. Zwei Kanten (u, v) mit π(u) < π(v) und (w, x) mit π(w) < π(x) schneiden sich bezüglich der Knotenfolge, falls π(w) < π(u) < π(x) < π(v) oder π(u) < π(w) < π(v) < π(x). Die Mengen A und B werden auch als Maximum Independent Sets (MIS) bezeichnet. Die Restkanten R = E \ F müssen später, in einem extra Schritt, in den Subgraphen eingefügt werden. 2 3 1 4 5 5 3 4 2 1 6 6 (a) (b) Abbildung 5.2: Darstellung eines Graphen (a) und dem dazugehörigen Ergebnis der GT-Heuristik (b) (aus [17]). Die Anordnung der Knoten in der ersten Phase hat einen erheblichen Einfluss auf die Anzahl der Kanten in F und somit auf die Qualität der gefundenen Lösung. Falls die Knotenfolge einen Hamilton-Zyklus1 bildet, enthält der gefundene planare Subgraph, nach [21], mindestens 43 der Anzahl der Kanten des optimalen planaren Subgraphen. Das Finden eines HamiltonZyklus in einem Graphen ist allerdings ein NP-vollständiges Problem. In [21] wird der folgende Greedy-Algorithmus vorgestellt, der eine gute Knotenfolge liefert, auch wenn damit nur selten ein Hamilton-Zyklus gefunden wird: Der erste Knoten v1 der Knotenfolge ist immer ein Knoten mit kleinstem Grad in G. Sei (v1 , .., vk ) 0 ≤ k ≤ |V | − 1 die Knotenfolge nachdem k Knoten ausgewählt worden sind und Gk = (Vk , Ek ) der Subgraph der durch die Knoten V \ {v1 , .., vk } induziert wird. Der Knoten vk+1 ∈ Vk ist dann entweder ein Nachbarknoten von vk mit kleinstem Grad bezüglich Gk oder falls vk keinen Nachbarknoten besitzt, ein Knoten mit kleinstem Grad bezüglich Gk . 1 Ein Hamilton-Zyklus ist ein einfacher Pfad von G, der alle Knoten beinhaltet. 5.2. EINBETTUNG 37 Da gerichtete Kanten e ∈ ED existieren, die aufwärts gezeichnet werden sollen, muss die erste Phase der Heuristik noch wie in [17] beschrieben modifiziert werden. Für alle gerichteten Kanten (u, v) ∈ ED muss gelten π(u) < π(v). Um dies zu erreichen, wird eine Fehlerfunktion : V → N auf den Knoten definiert, die für jeden Knoten v ∈ V die Anzahl der eingehenden, gerichteten Kanten angibt, die sich in Ek befinden. Ein Knoten v ∈ V darf nun nur in die Knotenfolge aufgenommen werden, falls (v) = 0. Ansonsten existieren Knoten u ∈ V mit (u, v) ∈ ED , die die Bedingung π(u) < π(v) verletzten würden. Die so berechnete Knotenfolge stellt eine topologische Sortierung von G dar. Die Maximum Independent Sets, die in der 2. Phase bestimmt werden, sind normalerweise maximal bezüglich der Anzahl der enthaltenen Kanten. Für teilgerichtete Graphen bietet es sich jedoch an, die Maximum Independent Sets maximal bezüglich der Summe der Gewichte der enthaltenen Kanten zu machen. Dazu wird eine Gewichtsfunktion weight : E → N auf den Kanten eingeführt. Da das spätere Einfügen von gerichteten Kanten einen erheblich größeren Aufwand erfordert, können diese nun durch ein höheres Gewicht bevorzugt werden. Die Maximum Independent Sets enthalten dadurch möglichst viele gerichtete Kanten, allerdings besitzen sie im allgemeinen keine maximale Anzahl von Kanten mehr, so dass die Anzahl der Restkanten R zunimmt, auch wenn R dann weniger gerichtete Kanten enthält. Eine deutliche Verbesserung der GT-Heuristik kann durch die in [29] vorgestellte Randomisierung erzielt werden. In der ersten Phase der Heuristik wird stets ein Knoten mit kleinstem Grad gewählt und in die Knotenfolge eingefügt. Häufig kommt es vor, dass mehrere Knoten mit kleinstem Grad existieren. Wählt man den einzufügenden Knoten aus der Menge der möglichen Knoten zufällig, dann unterscheidet sich die Knotenfolge bei mehrmaliger Berechnung. Wird die zweite Phase für verschiedene Knotenfolgen durchführt, verändert sich auch deren Ergebnis. Durchläuft man die randomisierte GT-Heuristik k mal, erhält man also unterschiedliche Ergebnisse. Ein neues Ergebnis wird nur abgespeichert, wenn es bezüglich der Summe der Gewichte bzw. bezüglich der Anzahl der Kanten, die in den Maximum Independent Sets enthalten sind, besser als das alte Ergebnis war. In den meisten Fällen ist das so erzielte Ergebnis deutlich besser. Die Laufzeit der Heuristik steigt dabei um den Faktor k. Die Laufzeit der ersten Phase beträgt O(|V |2 +|E|), die der zweiten Phase O(|V ||E|2 ) mit oder ohne Gewichtung [14]. Wendet man die Randomisierung an und wählt k konstant, erhöht sich die Laufzeit bezüglich der O-Notation nicht. Die Gesamtlaufzeit beträgt also weiterhin O(|V ||E|2 ). Die Heuristik liefert sehr gute Ergebnisse bezüglich der Größe des gefundenen planaren Subgraphen [5]. Allerdings ist sie aufgrund ihrer Laufzeit eher für kleine bis mittelgroße Graphen geeignet, was aber für UML-Klassendiagramme ausreichen sollte. Für den gefundenen planaren Subgraph GSub muss nun noch wie in [17] beschrieben, die zyklische Kantenordnung um die Knoten be- 38 KAPITEL 5. DER TOPOLOGY-SHAPE-METRICS ANSATZ stimmt werden. Nun erhält man einen eben eingebetteten, aufwärtsplanaren Subgraph mit der planaren Repräsentation PSub . 5.2.2 Routen von Kanten Die Restkanten R, die nicht im planaren Subgraph GSub enthalten sind, müssen nun mit möglichst wenig Überkreuzungen und unter Beibehaltung der Aufwärtsplanarität in GSub eingefügt werden. Dieser Vorgang wird als Routen der Kanten bezeichnet. Die Menge der gerichteten Restkanten wird dabei mit RD und die Menge der ungerichteten Kanten mit RU bezeichnet. Die nun vorgestellte Vorgehensweise stammt aus [14] und [17]. Routen von aufwärtsgerichteten Kanten Jede gerichtete Kante (v, w) ∈ RD muss als monoton steigende Kurve zwischen ihrem Startknoten v und ihrem Endknoten w gezeichnet werden, wobei möglichst wenige Kreuzungen enstehen sollen. Um dies zu erreichen, muss der Graph GSub zunächst zu einem st-Graph Gst erweitert werden. Definition 3 (st-Graph) Ein st-Graph ist ein gerichteter, azyklischer Graph mit genau einer Quelle s und einer Senke t. Eine Quelle s ist ein Knoten für den δin (s) = 0, eine Senke t ist ein Knoten für den δout (t) = 0. Satz 2 Sei G ein gerichteter Graph. Folgende Aussagen sind äquivalent: • G ist aufwärtsplanar. • G erlaubt eine aufwärtsplanare, geradlinige Zeichnung. • G ist der aufspannende Subgraph eines planaren st-Graphen. Der Beweis zu diesem Satz findet sich in [9]. Aus dem Satz folgt, dass jeder Graph G, der aufwärtsplanar ist, auch zu einem st-Graphen erweitert werden kann. Für eine Aufwärtseinbettung von GSub besteht die Erweiterung zu Gst darin, dass unerwünschte Senken und Quellen durch Hinzufügen von Kanten entfernt werden. Dies geschieht mit Hilfe der Knotenfolge, die in der ersten Phase der GT-Heuristik berechnet wurde. Die zusätzlich hinzugefügten Kanten werden Augmentierungskanten genannt. Sie werden nach dem Routen der aufwärtsgerichteten Kanten wieder aus dem Graphen entfernt. Der st-Graph Gst wird zur Levelisierung der Knoten von GSub eingesetzt. Dazu wird eine Funktion level : V → N eingeführt, die jedem Knoten eine Höhe zuweist. Die Höhe level(v) eines Knotens v in Gst ist die Länge des maximalen Pfades vom Knoten s zum Knoten v. Damit die Zuweisung korrekt 5.2. EINBETTUNG 39 ist, müssen auch die Kanten berücksichtigt werden, die nicht in GSub enthalten sind. Ansonsten zerstört man eventuell einen längsten Pfad. Außerdem muss jede ungerichtete Kante temporär gerichtet werden. Die Richtung der Kanten muss dabei so gewählt werden, dass keine Zykel in Gst entstehen, da sonst keine Höhenzuweisung möglich ist. Man wählt die Richtung einer Kante deswegen so, dass sich ihr Startknoten, bezüglich der Knotenfolge, die in der 1. Phase der GT-Heuristik berechnet wurde, vor dem Endknoten befindet. Da die Knotenfolge dann eine topologische Sortierung von Gst darstellt, ist Gst zykelfrei. Nach der Levelisierung wird die temporäre Richtung der ungerichteten Kanten wieder aufgehoben. Um eine Kante (v, w) ∈ RD aufwärtsplanar einbetten zu können, muss gelten level(v) < level(w). Eine aufwärtsplanare Einbettung eines st-Graphen besitzt folgende Eigenschaften: • Der Knoten s ist der niedrigste und der Knoten t ist der höchste Knoten und beide liegen am äußeren Face. • Jedes Face f besitzt für sich betrachtet selbst eine Quelle sf und eine Senke tf . • Da keine horizontalen Kanten in einer Aufwärtseinbettung erlaubt sind, geht ein Face über mindestens 2 Ebenen (von Mehrfachkanten abgesehen). Um eine Kante (v, w) ∈ RD aufwärtsplanar in den Graphen Gst zu routen, wird nun ein Routinggraph GRouting = (VRouting , ERouting ) aufgebaut, auf dessen Kantenmenge eine Funktion cost : ERouting → {0, 1} definiert wird, die den Kanten Kosten zuweist. Sei Ebene i der Teilraum zwischen level i und level i + 1. Der Routinggraph GRouting eines st-Graphen Gst wird folgendermaßen erstellt (vgl. Abb. 5.3): • Für jedes innere Face f von Gst wird, für jede von f überdeckte Ebene i, ein Knoten vf,i erzeugt. Die aufeinanderfolgenden Knoten von f werden durch gerichtete Kanten (vf,i , vf,i+1 ) verbunden, die die Kosten 0 besitzen. • Das äußere Face fout von Gst wird im Routinggraph durch ein linkes und ein rechtes äußeres Face dargestellt, welche mit fout,l bzw. fout,r bezeichnet werden. Für jede Ebene i werden Knoten vfout,r ,i bzw. vfout,l ,i erzeugt. Die aufeinanderfolgenden Knoten eines Repräsentanten werden wiederum jeweils durch eine gerichtete Kante verbunden, die die Kosten 0 besitzt. • Alle Knoten vf,i und vg,i zweier benachbarter Faces f und g, die sich auf der selben Ebene i befinden, werden durch die gerichteten Kanten 40 KAPITEL 5. DER TOPOLOGY-SHAPE-METRICS ANSATZ (vf,i , vg,i ) und (vg,i , vf,i ) verbunden. Diese Kanten besitzen die Kosten 0, falls die abgrenzende Kante eine Augmentierungskante ist und die Kosten 1 sonst. Diese Unterscheidung hat folgenden Grund: Eine Augmentierungskante kann zwar an einer Kreuzung in Gst beteiligt sein, nach dem Einfügen der Restkanten werden die Augmentierungskanten aber wieder entfernt, wodurch eine Augmentierungskante niemals Kreuzungen im Graph G erzeugen kann. Nach dieser Konstruktion ist ein Routinggraph immer planar. level 6 10 Ebene 5 6 7 8 level 5 9 level 4 Ebene 4 Ebene 3 5 level 3 4 level 2 Ebene 2 Ebene 1 3 2 level 1 Ebene 0 1 level 0 Abbildung 5.3: Darstellung eines st-Graphen und dessen Routinggraph. Nachdem der Routinggraph GRouting von Gst erstellt wurde, müssen noch die Knoten v 0 und w0 in diesen eingefügt werden, welche die Knoten v und w der einzufügenden Kante (v, w) repräsentieren. Der Knoten v 0 wird mit allen Knoten im Routinggraph verbunden, die auf der Ebene level(v) liegen und ein an v angrenzendes Face repräsentieren. Die entstehenden Kanten besitzen die Kosten 0. Der Knoten w0 wird analog mit den Knoten verbunden, die auf der Ebene level(w) − 1 liegen. Die Kosten des billigsten Weges zwischen den Knoten v 0 und w0 im Routinggraph entspricht nun der minimalen Anzahl von Überkreuzungen der einzufügenden Kante im Graph G unter Berücksichtigung der Aufwärtsplanarität. Die Kante wird nun entlang des billigsten Weges in Gst eingefügt. Dazu muss die Kantenordnung an den Knoten v und w aktualisiert und für 5.2. EINBETTUNG 41 jeden entstandenen Kreuzungsknoten die zyklische Kantenordnung angegeben werden. Beim Einfügen einer Kante steigt die Anzahl der Knoten von Gst demnach um die Anzahl der Kantenkreuzungen. Bevor die nächste Kante in Gst eingefügt werden kann, werden die Knoten v 0 und w0 wieder aus dem Routinggraph entfernt. Außerdem muss der Routinggraph aktualisiert werden, da sich der zugrundeliegende Graph Gst geändert hat. Die Laufzeit für das Einfügen der Kanten aus RD beträgt O |RD | · (|V | + c)2 , wobei c die Gesamtzahl der Kantenkreuzungen bezeichnet. Die Berechnung eines billigsten Pfades in einem planaren Graphen G = (V, E) mit nicht-negativen Kantenkosten kann dabei in O(|V |) erfolgen [23]. Routen von ungerichteten Kanten Nachdem die gerichteten Kanten in Gst eingefügt worden sind und die Augmentierungskanten entfernt wurden, müssen nun die Kanten aus RU mit möglichst wenig Kreuzungen in GSub 2 eingefügt werden. Da diese nicht monoton steigend eingefügt werden müssen, vereinfacht sich der Einfügevorgang erheblich. Zum Finden einer kreuzungsminimalen Route einer ungerichteten Kante, kann der duale Graph von GSub verwendet werden. Definition 4 (dualer Graph) Sei G = (V, E) ein eben eingebetteter Graph und F die Menge der Faces von G. Für den dualen Graph GD = (V 0 , E 0 ) von G gilt: • Für jedes Face f ∈ F existiert ein Knoten in V 0 . • Für jede Kante e ∈ E existiert eine ungerichtete Kante in E 0 , zwischen den beiden Knoten aus V 0 , die die, durch die Kante e getrennten, Faces repräsentieren. Der duale Graph GD eines eben eingebetteten Graphen G ist also ungerichtet, zusammenhängend und planar. Der duale Graph von GD ist zum Graphen G isomorph. Wenn zwei Faces von G mehrere Kanten gemeinsam haben, entstehen Mehrfachkanten in GD . Selbstschleifen in GD werden durch Brücken in G verursacht (vgl. Abb. 5.4). Um nun eine Kante (v, w) ∈ RU zu routen, muss der duale Graph von GSub erstellt werden. Auf den Kanten des dualen Graphen wird eine Kostenfunktion definiert, wobei alle Kanten die Kosten 1 besitzen. Jetzt werden, wie im aufwärtsgerichteten Fall, die Stellvertreterknoten v 0 und w0 in den dualen Graph eingefügt. Den Knoten v 0 bzw. w0 verbindet man mit den Knoten des dualen Graphen, die die Faces repräsentieren, die an den Knoten v bzw. w angrenzen. Die dabei enstandenen Kanten besitzen die Kosten 2 GSub bezeichnet jetzt den Graphen, der durch die Entfernung der Augmentierungskanten aus Gst entstanden ist. 42 KAPITEL 5. DER TOPOLOGY-SHAPE-METRICS ANSATZ 2 1 7 3 4 5 6 Abbildung 5.4: Darstellung eines Graphen und dem dazugehörigen dualen Graph. 0. Berechnet man nun den billigsten Weg zwischen den Knoten v 0 und w0 , dann entsprechen dessen Kosten der minimalen Anzahl von Kreuzungen, die beim Einfügen der Kante (v, w) in den Graphen GSub entstehen. Beim Einfügen muss analog zum aufwärtgerichteten Fall, die zyklische Kantenordnung der betreffenden Knoten aktualisiert werden. Die Laufzeit für das Einfügen der Kanten aus RU beträgt O |RU | · (|V | + c) . Nachdem sämtliche Kanten aus RU eingefügt wurden, erhält man eine aufwärtsplanare Einbettung des Graphen GSub . Dieser stellt nun eine Erweiterung des Graphen G dar, da er zusätzlich die entstandenen Kreuzungsknoten enthält. Auch für planare Graphen kann die gefundene ebene Einbettung Kreuzungen besitzen. Diese entstehen durch eine ungünstige Wahl des planaren Subgraphen oder durch ungünstige Kantenrouten. Da |RD | = O(|E|), ergibt sich für die gesamte Einbettung eine Laufzeit von: 5.2.3 O |V ||E|2 + |E| · (|V | + c)2 . Rerouting von Kanten Restkanten werden nacheinander in den planaren Subgraphen eingefügt. Auch wenn jede Kante zum Zeitpunkt des Einfügens knickminimal geroutet wird, kann sich die Wahl einer Route im nachhinein als ungünstig erweisen. Die Entscheidung für eine Route beeinflusst die möglichen Routen der noch einzufügenden Kanten. Man kann also nicht sagen, ob die Route einer Kante auch im Hinblick auf die noch einzufügenden Kanten optimal ist. Durch das Rerouting können schlechte Entscheidungen bei der Routenwahl noch im nachhinein korrigiert werden. Dazu werden Kanten, die Kreuzungen verursachen, aus dem Graph entfernt, neu geroutet und wieder eingefügt. Durch das Rerouting von Kanten kann die Anzahl der Kantenkreuzungen im Graphen reduziert werden. 5.3. ORTHOGONALISIERUNG 43 Kanten mit vielen Kreuzungen besitzen das größte Verbesserungspotential, deshalb beginnt man beim Rerouting mit solchen Kanten. Die Anzahl der Rerouting-Durchläufe sollte begrenzt werden, da Graphen mit vielen Kreuzungen sonst eine sehr hohe Laufzeit verursachen würden, da sich beim Rerouten einer Kante auch die Anzahl der Kantenkreuzungen anderer Kanten ändert. Um eine Kante neu zu routen, muss zuerst der duale Graph bzw. der Routinggraph erzeugt werden. Dann wird nach einer besseren Route für die Kante gesucht. Wird eine bessere Route gefunden, dann wird die Kante aus dem Graphen entfernt und auf der neuen Route wieder eingefügt. 5.3 Orthogonalisierung Nachdem eine planare Repräsentation P für den Graphen G gefunden wurde, muss diese nun zu einer orthogonalen Repräsentation H erweitert werden. Dazu muss die Form des Graphen bestimmt werden. Um eine übersichtliche Zeichnung zu erhalten, sollten dabei möglichst wenig Knicke entstehen. 5.3.1 Tamassias Algorithmus In diesem Abschnitt wird ein von Tamassia [30] entwickelter, kombinatorischer Algorithmus vorgestellt, der in der Lage ist, eine knickminimale orthogonale Repräsentation eines planaren 4-Graphen mit gegebener planarer Repräsentation zu berechnen. Dabei werden die Knoten des Graphen als Punkte auf einem orthogonalen Gitter angesehen (vgl. Abb. 2.3). Tamassias Algorithmus ermittelt die knickminimale orthogonale Repräsentation durch das Lösen eines Min-Cost-Flow-Problems. Abbildung auf ein Min-Cost-Flow-Problem Im folgenden sei G = (V, E) ein planarer 4-Graph und P dessen planare Repräsentation. Es wird nun ein Netzwerk N (P ) = (VN , EN ) aus der planaren Repräsentation P konstruiert, aus dessen minimalen Kostenfluss eine knickminimale orthogonale Repräsentation abgeleitet werden kann. Dazu wird auf den Kanten des Netzwerks eine Kosten- und Kapazitätsfunktion definiert. Für die Knotenmenge des Netzwerkes VN gilt: VN = {s} ∪ {t} ∪ UV ∪ UF , wobei s die Quelle und t die Senke des Netzwerks bezeichnet. Die Knotenmenge UV enthält einen Knoten uv für jeden Knoten v ∈ V und die Knotenmenge UF enthält einen Knoten uf für jedes Face f von G. Die Kantenmenge EN setzt sich aus folgenden Kanten zusammen: • Kanten (s, uv ) wobei gilt: uv ∈ UV . Die Kanten haben die Kosten 0 und die Kapazität 4 − δ(v) (vgl. Abb. 5.5(a)). 44 KAPITEL 5. DER TOPOLOGY-SHAPE-METRICS ANSATZ • Kanten (s, uf ) wobei gilt: uf ∈ UF und f ist ein inneres Face von G mit δ(f ) ≤ 3. Die Kanten haben die Kosten 0 und die Kapazität 4 − δ(f ). • Kanten (uf , t) wobei gilt: uf ∈ UF und f ist entweder das äußere Face von G oder ein inneres Face mit δ(f ) ≥ 5. Die Kanten haben die Kosten 0 und die Kapazität δ(f ) + 4, falls f das äußere Face ist bzw. δ(f ) − 4 sonst (vgl. Abb. 5.5(b)). • Kanten (uv , uf ) wobei gilt: uv ∈ UV , uf ∈ UF und v ist ein Endpunkt einer Kante aus P (f ). Die Kanten haben die Kosten 0 und die Kapazität ∞ (vgl. Abb. 5.5(c)). • Kanten (uf , ug ) und (ug , uf ) wobei gilt: uf , ug ∈ UF und die Faces f und g besitzen mindestens eine gemeinsame Kante. Besitzt ein Face f eine Brücke, so ensteht eine Selbstschleife (uf , uf ). Die Kanten haben die Kosten 1 und die Kapazität ∞ (vgl. Abb. 5.5(d)). Interpretation des Flusses Für den Flusswert |f | des Netzwerkes N (P ) gilt: |f | = X cap(s, v) = v∈VN X (5.1) cap(w, t). w∈VN Die Gleichheit folgt aus der Eulerschen Formel, da X w∈VN cap(w, t) − X v∈VN X cap(s, v) = δ(f ) − 4 + δ(f ) + 4 out f ∈F \fout ∧ δ(f )≥5 X X − 4 − δ(f ) + 4 − δ(v) f ∈F \fout ∧ δ(f )≤3 = X f ∈F v∈UV X δ(f ) − 4 + 8 + δ(v) − 4 v∈UV = 2|E| − 4|F | + 8 + 2|E| − 4|V | EF = 4 |E| − |F | − |V | + 2 = 0. Aus Formel (5.1) folgt, dass der Fluss über die Kanten (s, uv ), (s, uf ) sowie (uf , t) gleich der Kapazität der Kanten ist. Der Fluss in einen Knoten uv ∈ UV ist ≤ 3, da uv nur eine eingehende Kante (s, uv ) besitzt, deren Kapazität ≤ 3. 5.3. ORTHOGONALISIERUNG 45 1 uv2 2 3 uv3 u f3 u f2 s uv6 t 2 u v1 uv4 1 uv5 1 u f1 (a) uv2 uv3 u f3 u f2 s u v1 uv6 uv4 1 t uv5 9 u f1 (b) uv3 uv2 u f2 s uf3 uv4 uv1 uv6 t uv5 uf1 (c) uv2 uv3 u f2 s uv1 u f3 uv4 uv6 t u v5 u f1 (d) Abbildung 5.5: Konstruktion des orthogonalen Netzwerks. Die gestrichelten Kanten stellen die Kanten des zugrundeliegenden Graphs dar. 46 KAPITEL 5. DER TOPOLOGY-SHAPE-METRICS ANSATZ Der Fluss im Netzwerk N (P ) kann nun wie folgt interpretiert werden: Jede Flusseinheit über eine Kante (uf , ug ) repräsentiert den Knick einer Kante, die die beiden Faces f und g abgrenzt. Der Knick formt dabei einen 90 Grad Winkel innerhalb des Face f und kann einer beliebigen abgrenzenden Kante zugewiesen werden. Ein Fluss der Höhe x über eine Kante (uv , uf ) definiert einen Winkel der Größe (x + 1) · 90 Grad zwischen den beiden Kanten von P (f ), die zum Knoten v inzident sind. Ein Winkel von 90 Grad wird also durch einen Fluss von 0 modelliert. Aus der Flusserhaltungsbedingung folgt, dass die Summe der Winkel um einen Knoten v immer 360 Grad beträgt und jedes Face f ein rektilineares Polygon bildet. Ein gültiger Fluss mit den Kosten b führt zu einer orthogonalen Repräsentation mit genau b Knicken. Ein minimaler Kostenfluss führt also zu einer orthogonalen Repräsentation, die eine minimale Anzahl von Kantenknicken besitzt. Ein detailierter Algorithmus zum Bestimmen der orthogonalen Repräsentation aus dem minimalen Kostenfluss findet sich in [30]. Satz 3 Für einen planaren 4-Graphen G mit n Knoten und einer planaren Repräsentation P , findet der vorgestellte Algorithmus eine knickminimale orthogonale Repräsentation in der Zeit O(n2 log n). Die Laufzeit wird dabei durch das Lösen des Min-Cost-Flow-Problems dominiert. Der Beweis des Satzes befindet sich in [30]. 5.3.2 Das Kandinsky-Modell Der im letzten Abschnitt vorgestellte Algorithmus kann nur für 4-Graphen eingesetzt werden. Wenn der Grad eines Knotens größer als vier ist, würde das im bisherigen Modell zu Überlappungen führen, da in einer orthogonalen Gittereinbettung nur 4 verschiedene Richtungen an einem Knoten existieren und die Knoten als Punkte dargestellt wurden. Da Knoten, die UMLEntities repräsentieren, einen höheren Grad besitzen können, muss Tamassias Modell entsprechend erweitert werden. Eine solche Erweiterung bietet das Kandinsky-Modell [18]. In ihm werden die Knoten als Rechtecke mit einheitlicher Größe dargestellt, deren Mittelpunkt auf einem Gitter liegt. Dieser Abschnitt beschreibt die Erweiterung des orthogonalen Netzwerkes N (P ) zum quasi-orthogonalen Kandinsky-Netzwerk. Um Knoten mit Grad > 4 zu modellieren, müssen 0 Grad Winkel zugelassen werden. Ein 0 Grad Winkel zwischen zwei Kanten würde, basierend auf Tamassias Modell, durch einen Fluss von −1 von einem Knoten uv ∈ UV zu einem Knoten uf ∈ UF modelliert werden. Die Größe des Winkels wäre dann (1 + x) · 90 = 0 Grad. Im Kandinsky-Modell werden 0 Grad Winkel durch einen Fluss von 1 in die entgegengesetzte Richtung, also von uf nach uv , dargestellt. Dazu muss das Netzwerk N (P ) um folgende Kanten ergänzt werden: 5.3. ORTHOGONALISIERUNG 47 • Kanten (uf , uv ) wobei gilt: uf ∈ UF , uv ∈ UV und es existiert bereits eine Kante (uv , uf ) in N (P ). Die Kanten haben die Kosten 0 und die Kapazität 1. • Kanten (uv , t) wobei gilt: uv ∈ UV und δ(v) ≥ 5. Die Kanten haben die Kosten 0 und die Kapazität δ(v) − 4. Die Kanten (uv , t) sind nötig, da bei 0 Grad Winkeln zusätzlicher Fluss über Kanten (uf , uv ) in den Knoten uv fließt, der dann auch wieder abfließen können muss. Für Knoten uv mit δ(v) ≥ 5 existiert dann keine Kante (s, uv ). Diese Erweiterung stellt noch kein gültiges Modell dar. Die weiteren Modifikationen basieren auf folgender Beobachtung: Wenn man von Mehrfachkanten absieht, verbindet jede Kante, die von der selben Knotenseite ausgeht, verschiedene Nachbarknoten. Da die Knoten zentriert auf einem Gitter angeordnet werden, können solche Kanten nicht vollständig parallel verlaufen, ohne das Überlappungen entstehen. Es kann also maximal eine Kante geben, die geradlinig verläuft, die anderen Kanten müssen knicken. Im Kandinsky-Modell erzeugt deshalb jeder 0 Grad Winkel einen Knick einer der beiden beteiligten Kanten. Solche Knicke werden Kandinsky-Knicke genannt, die herkömmlichen Knicke nennt man Face-Knicke. Die Kante ohne Kandinsky-Knick wird als Mittelkante bezeichnet, obgleich sie nicht immer die mittlere Kante im topologischen Sinne darstellen muss. Für alle Kanten, die sich an derselben Knotenseite befinden, gilt folgendes: Alle Kanten, die bezüglich der zyklischen Kantenordnung links von der Mittelkante liegen, müssen nach links knicken. Kanten, die sich rechts von der Mittelkante befinden, müssen entsprechend nach rechts knicken. Ein Kandinsky-Knick wird also nicht durch die Topologie der Graphstruktur, sondern durch diese Eigenschaft des Modells verursacht. Eine weitere wichtige Eigenschaft des Kandinsky-Modells ist, dass es keine leeren Faces erlaubt, d.h. keine Dreiecke, die eine leere Region beschreiben (vgl. Abb. 5.6). Diese Eigenschaft Abbildung 5.6: Zwei Möglichkeiten für leere Faces, welche im verwendeten Kandinsky-Modell nicht erlaubt sind. führt zu folgendem Lemma: Lemma 1 Jedem 0 Grad Winkel einer Kandinsky-Zeichnung kann eindeutig ein 270 Grad Winkel zugeordnet werden. 48 KAPITEL 5. DER TOPOLOGY-SHAPE-METRICS ANSATZ Der Beweis dazu befindet sich in [18]. Diese Eigenschaft ist erforderlich, damit der minimale Kostenfluss in eine gültige quasi-orthogonale Repräsentation umgewandelt werden kann. Die Beobachtungen können nun wie folgt umgesetzt werden: Sei v ein Knoten von G und e1 , e2 zwei benachbarte Kanten, die zu v inzident sind. Sei f das von e1 und e2 eingeschlossene Face, g das Face, dass durch die Kante e1 vom Face f abgegrenzt wird und h das Face, dass durch die Kante e2 vom Face f abgegrenzt wird (vgl. Abb. 5.7). Für die Realisierung eines 0 e1 e2 e1 uf uf ug e2 uh ug uh uv uv (a) (b) Abbildung 5.7: In beiden Abbildungen ist ein Fluss über beide Netzwerkkanten gleichzeitig verboten. Grad Winkels zwischen den Kanten e1 und e2 muss eine Flusseinheit von uf in den Knoten uv fließen. Dies ist jedoch nur dann zulässig, falls auch Fluss von ug bzw. uh nach uf fließt, der dann den Kandinsky-Knick der Kante e1 bzw. e2 formt. Deswegen modelliert man 0 Grad Winkel direkt durch Kanten (ug , uv ) und (uh , uv ), welche Kosten 1 und Kapazität 1 besitzen. Zur Berechnung der quasi-orthogonalen Repräsentation werden die Kanten dann wieder durch die Originalkanten (ug , uf ) und (uf , uv ) bzw. (uh , uf ) und (uf , uv ) ersetzt. Bei dieser Modellierung entspricht nicht jeder gültige Flusswert des Netzwerks einer gültigen Zeichnung. Um dies zu erreichen, müssen folgende Eigenschaften gewährleistet werden: • Da keine negativen Winkel existieren, darf nur entweder Fluss von ug nach uv über e1 oder von uh nach uv über e2 fließen (vgl. Abb. 5.7(a)) (Fluss von eins in den Knoten bedeutet 0 Grad Winkel, Fluss von zwei nicht definiert!). • Falls eine Flusseinheit von ug nach uv über e1 fließt, darf nicht gleichzeitig eine Flusseinheit von uf nach uv über e1 fließen (vgl. Abb. 5.7(b)). Dadurch wird gewährleistet, dass alle Kanten links von der Mittelkante nach links und alle Kanten rechts von der Mittelkante nach rechts knicken. 5.3. ORTHOGONALISIERUNG 49 Um beide Eigenschaften gleichzeitig zu realisieren, wird das Netzwerk N (P ) wie folgt modifiziert: Für jede Kante ei eines Knotens v werden zwei Knoten v,r Hev,l i und Hei erzeugt und für jedes Face f , das an den Knoten v angrenzt, ein v Knoten Hf . Nun müssen folgende Kanten zum Netzwerk N (P ) hinzugefügt werden (vgl. Abb. 5.8): v,l • Kanten (uf , Hev,r i ) und (uf , Hej ), wobei f das Face bezeichnet, das durch die Kanten ei und ej begrenzt wird und ej die Kante, die bezüglich f in Richtung des Knotens v durchlaufen wird. Diese Kanten besitzen die Kapazität 1 und die Kosten 2c + 1. • Kanten (Hfv , uv ) mit der Kapazität 1 und den Kosten 0. Diese Kante sorgt für die erste Eigenschaft, indem sie die Kapazität auf 1 beschränkt und somit höchstens eine Flusseinheit in den Knoten fließen kann. v,r v v • Kanten (Hev,l i , Hf ) und (Hej , Hf ), wobei für f und ej dasselbe gilt wie oben. Diese Kanten besitzen die Kapazität 1 und die Kosten 0. v,r v,l v,l • Kanten (Hev,r i , Hei ) und (Hei , Hei ) mit der Kapazität 1 und den Kosten −c. Jedes dieser Kantenpaare bildet einen Zykel mit den Kosten −2c. Ein Pfad vom Knoten uf zum Knoten uv hat deshalb die Kosten 2c + 1 − 2c = 1. Wenn der Zykel schon gesättigt ist, besitzt der Pfad die Kosten 2c + 1. Dadurch wird die zweite Eigenschaft erfüllt. e1 H e1 2c+1 uh h H f v e2 H v,r e3 e3 H v,r e1 −c 2c+1 v h H uf v f uv 2c+1 g e3 v,l −c e1 2c+1 −c −c v,l H e3 2c+1 v H g ug −c 2c+1 v,r H e2 H −c v,l e2 e2 Abbildung 5.8: Das Kandinsky-Netzwerk um einen Knoten v. Die Kanten ohne Kostenangaben haben die Kosten 0. Durch die beschriebenen Änderungen entstehen Zyklen mit negativen Kosten in N (P ). Dies schränkt die Möglichkeit der verwendeten Algorithmen 50 KAPITEL 5. DER TOPOLOGY-SHAPE-METRICS ANSATZ zum Lösen des Min-Cost-Flow-Problems ein. Das entstandene Problem kann durch ein Lineares Programm (ILP) formuliert werden, welches eine optimale Lösung findet. Es ist aber kein Algorithmus bekannt, der das Problem in polynomieller Zeit lösen kann. Deswegen wird eine Heuristik zum Lösen des Problems verwendet. Die Heuristik basiert auf einem Algorithmus, der den Fluss entlang billigster Wege von s nach t erweitert. Da die Zyklen und deren Länge bekannt ist, kann man die billigsten Wege mit einer modifizierten Version des Algorithmus von Dijkstra bestimmen. Durch die Heuristik kann das Problem weiterhin in der Laufzeit O(n2 log n) gelöst werden, wobei die gefundene Lösung aber nicht immer optimal ist. Da UML-Klassendiagramme Knoten unterschiedlicher Größe enthalten, muss das verwendete Modell mit diesen umgehen können. Das hier beschriebene Kandinsky-Modell bringt die dazu nötigen Eigenschaften schon mit. Die Handhabung von Knoten unterschiedlicher Größe ist deshalb nur noch ein Kompaktierungsproblem. 5.4 Kompaktierung Um aus der orthogonalen Repräsentation H, die in der 2. Phase berechnet wurde, eine orthogonale Gittereinbettung zu erhalten, müssen noch die Längen der horizontalen und vertikalen Kantensegmente berechnet werden. Bei der Längenberechnung müssen folgende Punkte beachtet werden [30]: • Die Längen aller Segmente sind positiv und ganzzahlig. • Jeder Zykel des Graphen wird auf ein geradliniges Polygon abgebildet. • Es existieren keine Segmente die sich schneiden, außer gegebenenfalls an ihren gemeinsamen Endpunkten. Der Kompaktierungsalgorithmus geht im Falle von 4-Graphen folgendermaßen vor: Zuerst wird eine normalisierte orthogonale Repräsentation H 0 erzeugt, indem jedes Face von H durch Hinzufügen von zusätzlichen Knoten und Kanten in Rechtecke zerlegt wird. Um eine orthogonale Gittereinbettung Q0 zu erhalten, muss den Seiten der Rechtecke von H 0 eine konsistente, ganzzahlige Länge zugewiesen werden. Danach werden die zusätzlich hinzugefügten Knoten und Kanten wieder aus Q0 entfernt, wodurch die orthogonale Gittereinbettung Q entsteht. Die Laufzeit dieser Vorgehensweise beträgt O(|V | + |B|), wobei B die Menge der Knicke bezeichnet. Der hier verwendete Kompaktierungsalgorithmus muss außerdem folgende zusätzliche Eigenschaften besitzen: • Die Kompaktierung muss auch mit Graphen zurecht kommen, deren maximaler Knotengrad größer als 4 ist, da Knoten in UML-Klassendiagrammen einen höheren Grad besitzen können. 5.4. KOMPAKTIERUNG 51 • Die Kompaktierung muss Knoten variabler Größe berücksichtigen, da die Größe der Klassenknoten in UML-Klassendiagrammen von der Anzahl und Länge der Attribut- und Methodensignaturen abhängt und somit variabel ist. In [18] wird beschrieben, wie die Kompaktierung im Kandinsky-Modell mit einheitlicher Knotengröße durchgeführt werden kann. Dabei werden die Originalknoten durch Rechtecke aus mehreren „kleinen“ Knoten ersetzt (vgl. Abb. 5.9). Dadurch entsteht ein planarer 4-Graph, der mit einer Variante des vorherigen Algorithmus berechnet werden kann. Wählt man die Anzahl der „kleinen“ Knoten pro Seite hoch genug, dann kann jede Mittelkante in der Mitte der jeweiligen Knotenseite gezeichnet werden. v Abbildung 5.9: Ersetzung eines Knotens durch viele kleine Knoten. Bei einer einheitlichen Knotengröße können die Knoten bei der Kompaktierung als Punkte angesehen werden. Es müssen also nur die Längen der Kantensegmente berechnet werden, ohne Berücksichtigung der Knotengröße. Die Knoten können sich niemals überlappen. Besitzen die Knoten unterschiedliche Größen, wird die Kompaktierung komplizierter, da man jetzt auch die Größe der Knoten während der Kompaktierung beachten muss. Die entstehende Zeichnung soll dabei auch weiterhin keine Überlappungen zwischen Knoten besitzen. Bei der Kompaktierung für das Kandinsky-Modell mit unterschiedlichen Knotengrößen, wird zusätzlich eine Längenfunktion eingeführt. Das Kompaktierungsproblem kann dann durch ein lineares Programm (kandinsky linear program[15]) formuliert werden. Durch die Rechteckzerlegung wird gewährleistet, dass eine gültige Lösung für das lineare Programm gefunden werden kann. Unter der Annahme, dass sich die Anzahl der Knicke linear zur Anzahl der Knoten verhält, besitzt diese Vorgehensweise eine Laufzeit von O(|V |). Genaueres dazu findet sich in [15]. Da in UML-Klassendiagrammen auch Beziehungen beschriftet werden können, besteht ein weiteres Problem darin, diese Beschriftungen (labels) geeignet zu platzieren. Die Beschriftung der Kanten (Labeling) erfolgt bei vielen Algorithmen in einem extra Schritt im nachhinein. Um bessere Resul- 52 KAPITEL 5. DER TOPOLOGY-SHAPE-METRICS ANSATZ tate zu erzielen, können die Beschriftungen jedoch bereits, wie in [22] und [2] beschrieben, in der Kompaktierungsphase berücksichtigt werden. Kapitel 6 Ein Layoutalgorithmus für UML-Klassendiagramme Im vorherigen Kapitel wurden existierende Algorithmen vorgestellt, die die drei Phasen des Topology-Shape-Metrics Ansatzes für allgemeine Graphen realisieren. In diesem Kapitel werden die Erweiterungen und Modifikationen dieser Algorithmen vorgestellt, um die ermittelten Ästhetikkriterien, die sich durch die Semantik von UML-Klassendiagrammen ergeben, in den Layoutalgorithmus mit einzubeziehen. Dazu gehören vor allem das Aufwärtszeichnen von Kanten sowie die Darstellung der Vererbungshierarchie durch Vererbungsgabeln. Der UML-Standard selbst macht keine Vorgaben zum Layout von Klassendiagrammen. Wie in Kapitel 3.5 ermittelt wurde, sind Graphen Guml = (Vuml , Euml ), die UML-Klassendiagramme repräsentieren, teilgerichtete Graphen, die Mehrfachkanten und Selbstschleifen enthalten können. Die Knoten haben unterschiedliche Größen und ihr Grad kann größer als vier sein. Die Knotenmenge Vuml setzt sich aus folgenden disjunkten Knotenmengen zusammen: Der Knotenmenge K, deren Elemente Klassen repräsentieren, der Knotenmenge S, deren Elemente Schnittstellen repräsentieren und der Knotenmenge P , deren Elemente Pakete repräsentieren. Es gilt also: Vuml = K ∪ S ∪ P . Die Kantenmenge Euml = Euml,D ∪ Euml,U besteht aus folgenden disjunkten Kantenmengen: Vererbungskanten: EKVer ⊆ K × K, EKV er ⊆ Euml,D ESVer ⊆ S × S, ESV er ⊆ Euml,D EImpl ⊆ K × S, EImpl ⊆ Euml,D Assoziationen: EAss ⊆ V × V , EAss ⊆ Euml Abhängigkeiten: EAbh ⊆ V × V , EAbh ⊆ Euml,D 54 KAPITEL 6. EIN LAYOUTALGORITHMUS FÜR UML-KLASSENDIAGRAMME Es gilt also: Euml = EKVer ∪ESVer ∪EImpl ∪EAss ∪EAbh . Die Graphelemente sind außerdem entsprechend der UML-Konvention beschriftet. Der Eingabegraph G = (V, E) des Layoutalgorithmus unterscheidet folgende besondere Kantenmengen: • E↑ ⊆ E, die Menge der gerichteten Kanten, die aufwärtsgezeichnet werden sollen. Der von E↑ induzierte Subgraph von G muss azyklisch sein. Da in UML-Klassendiagrammen Beziehungen existieren, die durch gerichtete Kanten Euml,D dargestellt, aber dennoch nicht aufwärtsgerichtet gezeichnet werden (z.B. Assoziationen), unterscheidet man hier diese beiden Kantenmengen. Die Kanten e ∈ Euml,D \E↑ sind bezüglich des Graphen G ungerichtet. • EHyp ⊆ E↑ , die Menge der Kanten, die Hyperkanten bilden sollen. All diese Kanten sind aufwärtsgerichtet. Das Konzept der Hyperkanten, das im nächsten Abschnitt vorgestellt wird, benötigt man, um Vererbungsgabeln zu realisieren. • ETree ⊆ E↑ , eine Menge von Baumkanten. UML-Klassendiagramme enthalten oft Baumhierarchien, welche auf diese Kantenmenge abgebildet werden können. Enthält die Menge ETree mehrere Bäume, dürfen sich diese nicht überlappen, d.h. jeder Knoten ist höchstens Knoten eines Baumes. Damit die Baumhierarchie übersichtlich dargestellt werden kann, müssen die Baumkanten möglichst überkreuzungsfrei und ohne zusätzliche Knicke gezeichnet werden. Die Minimierung der Anzahl der Kreuzungen und Knicke ist zwar ein allgemeines Kriterium, Baumkanten besitzen diesbezüglich aber eine erhöhte Priorität gegenüber den anderen Kanten. Für das kreuzungsminimale bzw. knickminimale Zeichnen eines Baumes werden deswegen auch zusätzliche Kreuzungen bzw. Knicke der anderen Kanten in Kauf genommen. Eine übersichtliche Baumhierarchie fordert außerdem, dass die Kanten aufwärtsgerichtet gezeichnet werden. Deshalb gilt ETree ⊆ E↑ . Die Kanten zeigen dabei alle in Richtung der Wurzel r, für die somit δout,ETree (r) = 0 gilt. Neben diesen Kantenmengen enthält der Eingabegraph außerdem noch Informationen über die Größe der Knoten sowie über die Beschriftungen der Elemente. Da für diese Informationen keine Veränderungen an den bestehenden Algorithmen vorgenommen werden, müssen sie hier nicht weiter beachtet werden. Beim Layouten eines Graphen Guml werden dessen Kantenmengen, je nach Bedarf, den Kantenmengen E↑ , ETree und EHyp zugeordnet. Dabei muss lediglich darauf geachtet werden, dass die Zuordnung verträglich ist. Durch die flexible Zuordnung können verschiedene Ästhetikpräferenzen berücksichtigt werden. Unter der Annahme, dass keine Mehrfachvererbung von Klassen zugelassen wird, kann z.B. folgende Zuordnung gewählt werden: 6.1. HYPERKANTEN UND VERERBUNGSGABELN 55 E↑ = EKVer ∪ ESVer ∪ EImpl EHyp = EKVer ETree = EKVer Durch diese Festlegung werden Vererbungs- und Implementierungsbeziehungen hierarchisch (aufwärtsgerichtet) dargestellt. Die Klassenvererbung soll besonders hervorgehoben und durch Vererbungsgabeln (Hyperkanten) dargestellt werden. 6.1 Hyperkanten und Vererbungsgabeln In UML-Klassendiagrammen erfreut sich die Verwendung von Vererbungsgabeln zur Darstellung der Vererbungshierarchie großer Beliebtheit. In einem Graph entspricht diese Struktur einer Hyperkante zwischen dem Knoten, der die Superklasse repräsentiert und den Knoten, die die Subklassen repräsentieren (vgl. Abb. 6.1(b)). Eine Hyperkante ist eine Kante, die mehr als zwei Knoten verbindet. Ein Graph der Hyperkanten enthält, nennt man Hypergraph. Um weiterhin mit normalen Graphen arbeiten zu können, werden Hyperkanten durch das Verwenden eines Hilfsknotens modelliert, in dem sich alle beteiligten Kanten treffen (vgl. Abb. 6.1(c)). v u1 u2 (a) v u3 u1 u2 v u3 u1 (b) u2 u3 (c) Abbildung 6.1: Ersetzung von Hyperkanten. Im folgenden wird beschrieben, wie das Konzept angewendet werden kann, um aus der einfachen Darstellung die Abb. 6.1(a) zeigt, die gewünschte Vererbungsstruktur zu erzeugen. Sei v ein Knoten, der eine Superklasse repräsentiert, und USub,v die Menge der Knoten, die eine Subklasse von v repräsentieren. Für jeden Knoten u ∈ USub,v existiert demnach eine gerichtete Kante e = (u, v). Für diese Kanten soll gelten e ∈ EHyp . Um eine Hyperkante zu modellieren, wird nun für jede Superklasse v des Graphen, die mehr als eine Subklasse besitzt, ein Hilfsknoten vDummy erzeugt und durch eine gerichtete Kante (vDummy , v) mit dem Superklassenknoten verbunden. Jede 56 KAPITEL 6. EIN LAYOUTALGORITHMUS FÜR UML-KLASSENDIAGRAMME Kante (u, v) mit u ∈ USub,v wird aus dem Graphen entfernt und durch die Kante (u, vDummy ) ersetzt (vgl. Abb. 6.1(c)). Damit die Struktur einer Vererbungsgabel entsteht, muss den Kanten außerdem eine entsprechende Form zugewiesen werden (vgl. Abb.4.1(c)). Der nächste Abschnitt zeigt, wie man die Form von Kanten festlegen kann. In Abschnitt 6.3.2 wird beschrieben, wie man eine einheitliche Höhe der Geschwisterknoten erreichen kann. Damit sich die Kanten (u, vDummy ) in der Horizontalen überlappen, wird dem Hilfsknoten vDummy einfach eine entsprechend kleine Größe zugewiesen. Bei der vorgestellten Transformation muss folgendes beachtet werden: Die erzeugten Kanten gehören denselben Kantenmengen wie die Originalkanten an, d.h. sind die Originalkanten aufwärtsgerichtet, dann auch die neuen Kanten. Dasselbe gilt auch für die Kantenmengen EHyp und ETree . Durch die beschriebene Transformation wird eine vorliegende Baumeigenschaft nicht zerstört. Die Zeichnung eines Graphen sollte keine zusätzlichen Knoten oder Kanten enthalten. Deshalb müssen die Hilfsknoten und die hinzugefügten Kanten nach dem Layouten wieder entfernt und die Originalkanten entsprechend wieder eingefügt werden. Das Layout einer Originalkante (u, vSuper ) setzt sich aus dem Layout der Kante (u, vDummy ) und der Kante (vDummy , v) zusammen. Alle Originalkanten überdecken sich also bezüglich des Kantenabschnitts (vDummy , v), so dass der Hyperkanteneffekt entsteht. Die Laufzeit für die Hyperkanten-Transformation setzt sich folgendermaßen zusammen: Man geht für alle Knoten die inzidenten Kanten durch. Trifft man dabei auf eingehende Kanten e ∈ EHyp , erzeugt man einen Hilfsknoten und führt die vorgestellte Transformation durch. Die Laufzeit beträgt also O(|V | + |E|). Beim Entfernen der Hilfsknoten müssen die Kanten wieder entsprechend ersetzt werden. Auch das geht in Linearzeit. Wenn man das Hyperkanten-Konzept nicht nur in Baumhierarchien verwenden will, ergeben sich folgende Erweiterungsmöglichkeiten: • Bis jetzt wurden immer nur eingehende, aufwärtsgerichtete Kanten zu einer Hyperkantenstruktur zusammengefasst. Man kann aber analog auch alle ausgehenden, aufwärtsgerichteten Kanten zusammenfassen (vgl. Abb. 6.2(a)). • Man kann Kanten in verschiedene Gruppen einteilen und dann jeweils die Kanten eines Knotens, die derselben Gruppe angehören, durch eine Hyperkantenstruktur zusammenfassen (vgl. Abb. 6.2(b)). Erfolgt die Gruppierung über die Kantenart, können Baumkanten und gewöhnliche aufwärtsgerichtete Kanten an einem Knoten separat zusammengefasst werden. Der Eingabegraph kann auch entsprechende Markierungen für die Gruppen erhalten. 6.2. DER BASISALGORITHMUS v1 v2 u 57 v3 v u1 (a) u2 w1 w2 (b) Abbildung 6.2: Mögliche Erweiterungen des Hyperkantenkonzepts. 6.2 Der Basisalgorithmus In diesem Abschnitt wird der Basisalgorithmus vorgestellt, der die Gabelform der Vererbungskanten sowie die Aufwärtsrichtung der Kanten aus E↑ realisiert. Im folgenden wird von einer aufwärtsplanaren Einbettung des von der Kantenmenge E↑ induzierten Subgraphen ausgegangen. Da Graphen, die UML-Klassendiagramme repräsentieren, eine variable Knotengröße und Knoten v mit δ(v) > 4 besitzen, bietet sich für die Orthogonalisierung das Kandinsky-Modell an. Die Orthogonalisierung wird in zwei Phasen aufgeteilt. Die erste Phase legt die Form der aufwärtsgerichteten Kanten fest. In der zweiten Phase wird die Form der ungerichteten Kanten so bestimmt, dass die Form, die den aufwärtsgerichteten Kanten in der ersten Phase zugewiesen wurde, beibehalten werden kann. Zunächst wird ein Algorithmus vorgestellt, der die Form der aufwärtsgerichteten Kanten festlegt, gefolgt von einem Algorithmus zur Knickreduzierung. Anschließend erfolgt eine Beschreibung der nötigen Änderungen, um die vorgegebenen Kantenformen im Kandinsky-Netzwerk zu berücksichtigen. Schließlich wird das Problem der einheitlichen Ausrichtung der aufwärtsgerichteten Kanten gelöst. 6.2.1 Formzuweisung für die aufwärtsgerichteten Kanten Zu Beginn des Kapitels wurden die Beziehungskanten Euml den Kantenmengen E↑ , ETree und EHyp zugeordnet. Das Ziel dieser Zuordnung ist, dass die entsprechenden Kanten eine bestimmte Form erhalten, so dass übersichtliche Klassendiagramme entstehen. Den Kanten der Kantenmenge E↑ muss eine Form zugewiesen werden, die eine einheitliche Kantenrichtung gewährleistet. Die Kanten der Kantenmenge EHyp sollen zusätzlich eine Gabelform erhalten. Dabei ist zu beachten, dass durch Kreuzungen geteilte Kanten mit mehreren Kanten in diesen Kantenmengen vertreten sein können. 58 KAPITEL 6. EIN LAYOUTALGORITHMUS FÜR UML-KLASSENDIAGRAMME Im folgenden wird ein Algorithmus vorgestellt [16], der den aufwärtsgerichteten Kanten eine Form zuweist, die verträglich mit dem KandinskyModell ist und einen monoton steigenden Verlauf der aufwärtsgerichteten Kanten garantiert. Der Algorithmus arbeitet dazu auf den durch die Kantenmenge E↑ induzierten Subgraphen G↑ = (V↑ , E↑ ). Dabei wird angenommen, dass G↑ zusammenhängend ist. Wie dies gewährleistet werden kann wird in Abschnitt 6.2.4 erläutert. Die Form einer Kante wird durch eine Zeichenkette beschrieben, die aus Elementen der Menge {←, ↑ , →} besteht. Da die Kanten aufwärtsgerichtet sind und somit monoton steigend gezeichnet werden sollen, darf die Richtung ↓ nicht vorkommen. Jedes Element der Zeichenkette gibt die Richtung des zugehörigen Kantensegmentes an. Zwischen zwei aufeinanderfolgenden Elementen der Zeichenkette besteht also immer ein Knick. Zwei aufeinanderfolgende Richtungsangaben müssen konsistent sein, d.h. die Folge ←, → bzw. →, ← ist nicht erlaubt. Der Algorithmus bestimmt die Form einer Kante (v, w) ∈ E↑ in zwei Schritten. Am Knoten v bekommt die Kante ihre Fußform und am Knoten w ihre Kopfform zugewiesen. Durch diese separate Zuweisung ist es möglich, alle Knoten aus V↑ der Reihenfolge nach durchzugehen und den inzidenten, aufwärtsgerichteten Kanten die entsprechende Fuß- bzw. Kopfform zuzuweisen. Die beiden Formen werden dabei entsprechend miteinander verknüpft. Die Fußform steht dabei immer am Anfang der Zeichenkette. Da jede Fußform mit einem ↑ endet, ist eine konsistente Verknüpfung gewährleistet. Der Algorithmus setzt voraus, dass Kreuzungsknoten und HyperkantenHilfsknoten entsprechend markiert sind. An den verschiedenen Knotentypen werden den inzidenten Kanten dann folgende Formen zugewiesen: • Handelt es sich um einen normalen Knoten, dann gilt folgender Grundsatz: Alle eingehenden aufwärtsgerichteten Kanten befinden sich an der Unterseite und alle ausgehenden aufwärtsgerichteten Kanten an der Oberseite des Knotens. Für die ausgehenden Kanten bestimmt man eine Mittelkante, die die Fußform ↑ zugewiesen bekommt. Alle ausgehenden Kanten, die sich links von der Mittelkante befinden, müssen nach links knicken und bekommen daher die Fußform ↑←↑ zugewiesen. Alle ausgehenden Kanten die sich rechts von der Mittelkante befinden, müssen nach rechts knicken und bekommen daher die Fußform ↑→↑ zugewiesen. Die Mittelkante wählt man wie folgt: Existiert eine ausgehende Baumkante (höchstens eine), dann wird diese als Mittelkante gewählt. Ansonsten wird die Kante als Mittelkante gewählt, die sich bezüglich der zyklischen Kantenordnung der ausgehenden Kanten um den Knoten in der Mitte befindet. Bei der Zuweisung der Kopfform der eingehenden Kanten geht man folgendermaßen vor: Zuerst wird wieder eine Mittelkante gewählt. Die Kanten links von der Mittelkante bekommen die Kopfform →↑ und die Kanten rechts von der Mittelkante die Kopfform ←↑ zu- 6.2. DER BASISALGORITHMUS 59 gewiesen. Wenn ein Knoten mehrere eingehende Baumkanten besitzt, wählt man die Baumkante, die sich bezüglich der zyklischen Kantenordnung der eingehenden Baumkanten um den Knoten in der Mitte befindet, als Mittelkante. Ansonsten wählt man die Mittelkante wie bei den ausgehenden Kanten. Abb. 6.3(a) und Abb. 6.3(b) zeigen die Formzuweisung an einem normalen Knoten. In Abb. 6.3(b) stellen die dicken Kanten Baumkanten dar. • Handelt es sich um einen Hyperkanten-Hilfsknoten, dann wird der ausgehenden Kante die Fußform ↑ zugewiesen. Ist die Anzahl der eingehenden Kanten gerade, dann wird der rechten Hälfte der eingehenden Kanten die Kopfform ← und der linken Hälfte die Kopfform → zugewiesen (vgl. Abb. 6.3(c)). Ist die Anzahl der eingehenden Kanten ungerade, so wird der mittleren eingehenden Kante keine Kopfform zugewiesen (vgl. Abb. 6.3(d)). Besitzen die eingehenden Kanten die Fußform ↑, dann stellt diese Formgebung eine Art Zentrierung der Kindknoten dar, da die Anzahl der Knoten auf der rechten Seite der Anzahl der Knoten auf der linken Seite entspricht. Die Zentrierung bezieht sich dabei jedoch nur auf die Anzahl der Knoten und nicht auf die Metrik. • Handelt es sich um einen Kreuzungsknoten, gilt folgendes: Ein Kreuzungsknoten entsteht durch zwei sich kreuzende Kanten e und e0 . Sind diese Kanten aufwärtsgerichtet, dann wird die Form der Kanten am Kreuzungsknoten so festgelegt, dass die eine Kante gerade verläuft und die andere knickt. Die gerade Kante wird dabei folgendermaßen bestimmt: Ist die Kante e eine Baumkante, dann verläuft e gerade und e0 knickt. Ansonsten ist e die knickende und e0 die gerade Kante. Durch diese Zuordnung wird gewährleistet, dass Baumkanten an Kreuzungen nur dann knicken, wenn sie sich mit einer anderen Baumkante kreuzen. Somit können Bäume immer möglichst ohne zusätzliche Knicke dargestellt werden. Sei e die gerade und e0 die knickende Kante. Durch den Kreuzungsknoten wird die Kante e in eine ausgehende eout und eine eingehende Kante ein geteilt. Aus der Kante e0 entstehen analog die Kanten e0out und e0in . Die Kante eout bekommt die Fußform ↑ zugewiesen. Die Form der Kanten e0out und e0in ist abhängig von der zyklischen Ordnung der Kanten um den Kreuzungsknoten. Entweder bekommt die Kante e0out die Fußform →↑ und die Kante e0in die Kopfform → (vgl. Abb. 6.3(e)) oder die Kante e0out bekommt die Fußform ←↑ und die Kante e0in die Kopfform ← zugewiesen (vgl. Abb. 6.3(f)). Ist nur eine der beiden an der Kreuzung beteiligten Kanten aufwärtsgerichtet, dann wird diese Kante gerade gezeichnet (vgl. Abb. 6.3(g)), die ungerichtete Kante bekommt keine Form. KAPITEL 6. EIN LAYOUTALGORITHMUS FÜR UML-KLASSENDIAGRAMME 60 v v h h (a) (b) (c) (d) c c (e) (f) c (g) Abbildung 6.3: Die vom Algorithmus zugewiesenen Kantenformen. Die durchgängigen Kantensegmente haben ihre Form durch den Knoten erhalten. Die dicken Kanten repräsentieren Baumkanten. Mit v werden die normalen Knoten, mit h die Hyperkanten-Hilfsknoten und mit c die Kreuzungsknoten bezeichnet. Die durch den Algorithmus zugewiesene Form sorgt für einen monoton steigenden Verlauf der aufwärtsgerichteten Kanten. Da G↑ aufwärtsplanar eingebettet ist, führt die zugewiesene Form zu einer gültigen Zeichnung, denn jeder aufwärtsplanare Graph besitzt nach [8] eine Aufwärtszeichnung, in der die Knoten durch horizontale und die Kanten durch vertikale Linien repräsentiert werden können. Wenn man die horizontalen Linien durch die vom Algorithmus zugewiesenen Kantenformen ersetzt, erhält man somit eine gültige Zeichnung. Durch die beschriebene Formzuweisung des Algorithmus kann eine Kante des eingebetteten Graphs höchstens vier Knicke besitzen. Die Anzahl der erzeugten Knicke ist also O(|V | + c). Der Algorithmus geht die Knoten von G↑ der Reihe nach durch und weist den inzidenten Kanten eine entsprechende Form zu. Da der Graph planar ist, geht das in der Laufzeit O(|V | + c). 6.2. DER BASISALGORITHMUS 6.2.2 61 Knickreduzierung Der gerade vorgestellte Algorithmus erzeugt einige überflüssige Knicke, die man nachträglich entfernen kann. Dazu werden die Zeichenketten, die die Form der Kanten beschreiben, mit bestimmten Mustern verglichen. Entspricht eine Zeichenkette einem bestimmten Muster, dann kann sie durch eine kürzere Zeichenkette ersetzt werden, wodurch die Anzahl der Knicke der dazugehörigen Kante reduziert wird. Die erste und die letzte Richtung einer Kante darf dabei nicht verändert werden, damit die Aufwärtsrichtung erhalten bleibt. Tabelle 6.1 zeigt die Muster und die entsprechenden Vereinfachungen. Es werden nur Muster beachtet, die bei der Formgebung entstehen können. Wie aus Tabelle 6.1 ersichtlich ist, spielt es für die Vereinfachung Form Bedingung ←↑← v und w sind Kreuzungsknoten →↑→ v und w sind Kreuzungsknoten ←↑←↑ v ist Kreuzungsknoten →↑→↑ v ist Kreuzungsknoten ↑←↑← w ist Kreuzungsknoten ↑→↑→ w ist Kreuzungsknoten ↑←↑←↑ ↑→↑→↑ Tabelle 6.1: Vereinfachung der Form von Kanten neue Form ← → ←↑ →↑ ↑← ↑→ ↑←↑ ↑→↑ e = (v, w). der Kantenform eine Rolle, ob die Endpunkte der Kante Kreuzungsknoten sind oder nicht. Das beruht auf der Eigenschaft der Kreuzungsknoten, dass jede Knotenseite nur eine Kante besitzt. Abb. 6.4 zeigt ein Beispiel für eine Knickreduzierung. Auch nach Durchführung der Vereinfachungen aus Tabelle 6.1 können noch unnötige Knicke vorhanden sein. Es treten z.B. Fälle auf, in denen die Form ↑→↑ zwischen zwei gewöhnlichen Knoten vereinfacht werden kann (vgl. Abb.6.5(a)). Häufig existieren aber auch Anordnungen, bei denen dies nicht möglich ist (vgl. Abb.6.5(b)). Da es sehr komplex ist, für jeden Fall zu überprüfen, ob eine geeignete Anordnung für eine Vereinfachung vorliegt, werden hier nur Vereinfachungen durchgeführt, die immer angewendet werden können. Bei den bisherigen Vereinfachungen genügt es, jeweils die Zeichenkette einer Kante sowie den Typ der Endpunkte zu betrachten. An Kreuzungsknoten ergibt sich eine weitere Möglichkeit, die Anzahl der Knicke zu reduzieren. Dazu muss die Form aller vier, zum Kreuzungsknoten inzidenten, Kanten betrachtet werden. Dies ist nur möglich, falls die Kanten aufwärtsgerichtet sind. Wenn die ausgehende Kante an der Oberseite des Kreuzungsknotens keinen KAPITEL 6. EIN LAYOUTALGORITHMUS FÜR UML-KLASSENDIAGRAMME 62 2 4 1 3 5 6 2 4 1 3 (a) 5 6 (b) Abbildung 6.4: Beispiel zur Knickreduzierung. Die linke Abbildung zeigt die Form der Kanten vor der Knickreduzierung, die rechte Abbildung die Form nach der Knickreduzierung. 3 4 2 1 (a) 3 4 2 1 (b) Abbildung 6.5: In der linken Abbildung kann die Form der Kante (4, 3) auf ↑ reduziert werden. In der Anordnung der rechten Abbildung ist dies nicht möglich. Hyperkanten-Hilfsknoten als Endpunkt besitzt und die Vereinfachungen aus Tabelle 6.1 noch nicht durchgeführt wurden, kann folgende Transformation angewendet werden: Knicken alle Kanten vom Kreuzungsknoten aus gesehen einheitlich nach links bzw. nach rechts, kann man jeweils die erste Richtungsangabe der Form der ausgehenden Kanten und die letzte Richtungsangabe der Form der eingehenden Kanten aus den Zeichenketten entfernen (vgl. Abb. 6.6). Diese Transformation kann folgendermaßen interpretiert werden: Bei der Formzuweisung an einem Kreuzungsknoten entscheidet man sich für eine Kante, die gerade verlaufen soll, die andere knickt. Angenommen e ist die knickende Kante. Hätte man sich bei der Formzuweisung entschieden, die Kante e0 knicken zu lassen, dann entspräche die Form der Kreuzungskanten, nachdem die in Tabelle 6.1 vorgestellten Vereinfachungen vorgenommen wurden, der Form der Kreuzungskanten, die durch die vorgestellte Transformation entstanden ist. Aus dieser Interpretation folgt, dass die Aufwärtsrichtung 6.2. DER BASISALGORITHMUS e1 e4 e1 c e3 63 e4 e2 c e4 e3 c e3 e3 e2 e1 e4 c e2 e2 e1 Abbildung 6.6: Entfernen von Knicken bei Kreuzungsknoten. der Kanten durch die Transformation nicht zerstört werden kann. Durch die Transformation werden ungünstige Entscheidungen bei der Formgebung an den Kreuzungsknoten korrigiert. Es sind weitere Transformationen möglich, die auf diesem Prinzip basieren. Das nachträgliche Tauschen der knickenden Kante an einem Kreuzungsknoten ist allgemein nur dann sinnvoll, wenn nach der Transformation Kanten durch die einfache Knickreduzierung vereinfacht werden können und keine beabsichtigte Form zerstört wird. In Abb. 6.7(a) wäre eine Transformation unsinnig. Falls drei Kanten an einem Kreuzungsknoten in dieselbe Richtung knicken, wie in Abb. 6.7(b), kann eine Transformation sinnvoll sein. Wie zu sehen ist, bekommt hier eine Kante einen zusätzlichen Knick. Die Anzahl der Knicke wird also nur um zwei reduziert. e1 e4 e3 c e1 e4 c e3 e2 (a) e1 e4 e2 e3 c e1 e4 c e2 e3 e2 (b) Abbildung 6.7: Weitere Transformationen bei Kreuzungsknoten. Für die Laufzeit der vorgestellten Knickreduzierung gilt folgendes: Man läuft alle Kreuzungsknoten ab und schaut, ob die Kreuzung vereinfacht werden kann. Merkt man sich die Kreuzungsknoten in der Einbettungsphase, kann das in O(c) erledigt werden. Danach geht man alle Kanten durch, vergleicht deren Form mit den Mustern und weist ihnen gegebenfalls eine neue Form zu. Da der Graph planar ist, geht dies in O(|V | + c). Daraus resultiert eine Gesamtlaufzeit von O(|V | + c). KAPITEL 6. EIN LAYOUTALGORITHMUS FÜR UML-KLASSENDIAGRAMME 64 6.2.3 Umsetzung der vorgegebenen Form durch das KandinskyNetzwerk In diesem Abschnitt werden die Modifikationen am Kandinsky-Netzwerk vorgestellt, die notwendig sind, um Winkel zwischen Kanten sowie Kantenknicke vorgeben zu können, die dann durch den Netzwerkfluss realisiert werden sollen. Anschließend wird beschrieben, wie die Form, die bei der Formzuweisung ermittelt wurde, auf das Netzwerk transformiert werden kann. Unter Einbehaltung der vorgegebenen Form, muss dann die Form der ungerichteten Kanten bestimmt werden. Der folgende Abschnitt basiert im wesentlichen auf den in [3] beschriebenen Modifikationen. Modifikation des Netzwerks Um die Größe von Winkeln vorgeben zu können, müssen zusätzliche Knoten und Kanten in das Kandinsky-Netzwerk N (P ) aufgenommen werden. Für jeden vorgegebenen Winkel zwischen zwei aufeinanderfolgenden Kanten e1 und e2 des Knotens v wird ein Winkelknoten ave1 ,e2 in das Netzwerk eingefügt. Die Menge der Winkelknoten von v wird mit UA (v) bezeichnet. Ein Knoten v wird im Netzwerk durch den Knoten uv repräsentiert. Für jeden Knoten av ∈ UA (v) werden die Kanten (uv , av ) und (av , uv ) mit den Kosten ca und unbeschränkter Kapazität in das Netzwerk eingefügt. Für einen Winkelknoten ave1 ,e2 sei uf der Netzwerkknoten, der das Face f repräsentiert, welches von den beiden Kanten e1 und e2 begrenzt wird. Die Kanten (uv , uf ) und (Hfv , uv ) müssen nun durch die Kanten (av , uf ) und (Hfv , av ) ersetzt werden. Auf der Menge der Winkelknoten UA ist eine Funktion angle : UA → {−1, 0, 1, 2, 3} definiert, die die Größe des Winkels vorgibt. Ein Winkelknoten av soll für einen Winkel von 1 + angle(av ) · 90 Grad sorgen. Um die vorgegebenen Winkel umsetzen zu können, müssen zusätzlich folgende Kanten in das Netzwerk N (P ) eingefügt werden: • Kanten (s, av ) von der Quelle s zum Winkelknoten av ∈ UA (v), falls angle(av ) > 0. Diese Kanten haben die Kosten 0 und die Kapazität angle(av ). • Kanten (av , t) vom Winkelknoten av ∈ UA (v) zur Senke t, falls angle(av ) < 0. Diese Kanten haben die Kosten 0 und die Kapazität −angle(av ). Außerdem muss der Wert angle(av ) für jeden Winkelknoten av ∈ UA (v) vom Fluss in den Knoten uv abgezogen werden. Für das Flussangebot (supply) am Knoten uv gilt somit: supply(uv ) = 4 − δ(v) − X av ∈UA (v) angle(av ). 6.2. DER BASISALGORITHMUS e1 uf ug v Hf uv e1 e1 uh v Hh 65 (1, c b) (1,0) (2,0) u b’ u b v Hg ug (a) ug (1, c b) (1,0) (1,2c) uf s e2 w,l He e2 (2,0) (2,0) (2,0) s e3 uf w,r He 2 e2 w (b) (c) 2 Abbildung 6.8: Änderungen am Kandinsky-Netzwerks. Neu hinzugefügte Knoten sind gelb gezeichnet, neu hinzugefügte Kanten haben eine transparente Pfeilspitze und veränderte Kanten sind gepunktet dargestellt. Für die einzufügenden Kanten (s, uv ) und (uv , t) gilt nun: Falls supply(uv ) ≥ 0, wird eine Kante (s, uv ) mit der Kapazität supply(v) und den Kosten 0 erzeugt. Falls supply(v) < 0, wird eine Kante (uv , t) mit der Kapazität −supply(uv ) und den Kosten 0 erzeugt. Damit vorgegebene Winkel eingehalten werden können, muss die Größe der Winkel konsistent sein. Es können beispielsweise keine zwei 270 Grad Winkel an einem Knoten entstehen. Falls ein Winkel nicht eingehalten werden kann, entstehen Kosten von mindestens ca , da mindestens eine Flusseinheit über eine Kante (uv , av ) oder (av , uv ) fließen muss. Abb. 6.8(a) zeigt ein Beispiel für die beschriebene Modifikation. Zwischen den Kanten e1 und e2 sowie zwischen den Kanten e2 und e3 soll ein vorgegebener Winkel realisiert werden. Dazu werden, wie beschrieben, zwei Winkelknoten in N (P ) eingefügt und die entsprechenden Kanten erzeugt. Die Winkelknoten sind gelb dargestellt, die neuen Kanten durch eine transparente Pfeilspitze und die geänderten Kanten durch eine gepunktete Linie. Der Übersicht halber wurden die Kanten mit Endpunkt s oder t weggelassen. Um neben Winkeln auch Knicke von Kanten vorgeben zu können, sind folgende Modifikationen nötig: Für jeden Knick einer Kante e wird die Kante durch einen Knickknoten b aufgeteilt, wodurch die Kanten e1 und e2 entstehen. Seien uf und ug die Netzwerkknoten, die die, von der Kante e getrennten, Faces f und g repräsentieren. Dann muss das Flussangebot an den Knoten uf und ug zusätzlich um eine Einheit je Knickknoten verringert werden. Das Face g sei das Face, indem der Knick einen rechten Winkel bilden 66 KAPITEL 6. EIN LAYOUTALGORITHMUS FÜR UML-KLASSENDIAGRAMME soll. Für jeden Knickknoten b werden die Knoten ub und ub0 und folgende Kanten in das Netzwerk N (P ) eingefügt (vgl. Abb. 6.8(b)): • Eine Kante (s, ub ) von der Quelle s zum Knoten ub . Die Kante hat die Kosten 0 und die Kapazität 2. • Eine Kante (ub , uf ) vom Knoten ub zum Knoten uf . Die Kante hat die Kosten 0 und die Kapazität 2. • Eine Kante (ub0 , ug ) vom Knoten ub0 zum Knoten ug . Die Kante hat die Kosten cb und die Kapazität 1. • Eine Kante (ub , ub0 ) vom Knoten ub zum Knoten ub0 . Diese Kante hat die Kosten 0 und die Kapazität 1. Der Zweck dieser Kante wird weiter unten erläutert. Zusätzlich erhalten die Kanten zwischen den Faces die Kosten cf > cb , damit der Fluss, der vom Knoten ub in den Knoten uf fließt, nicht über die Kante (uf , ug ) fließen kann. Die Interpretation der Modifikation ist folgendermaßen: Der Knoten ub muss einen Fluss der Höhe 2 auf seine ausgehenden Kanten verteilen. Dazu gibt es folgende Möglichkeiten: Entweder fließen beide Einheiten über (ub , uf ) wodurch ein Winkel von 270 Grad zwischen den Kanten e1 und e2 im Face f entsteht, oder es fließt nur eine Flusseinheit über (ub , uf ) und eine über die Kanten (ub , ub0 ) und (ub0 , ug ), wobei die Kosten cb entstehen und der Knick nicht eingehalten wird. Der erste und der letzte Knick einer Kante sind mögliche KandinskyKnicke. Diese werden speziell behandelt. In Abb. 6.8(c) stellt w einen gewöhnlichen Knoten dar, der über die Kante e2 mit dem Knickknoten b verbunden ist. Die Kante e2 kann am Knoten w einen Kandinsky-Knick erhalten. Deshalb wird eine extra Kante (ub0 , Hew,l 2 ), falls der gewünschte Knick w,r 0 nach links gehen soll, bzw. (ub , He2 ), falls der Knick nach rechts gehen soll, eingefügt. Diese Kante hat die Kosten 2c und die Kapazität 1. Durch sie wird gewährleistet, dass der Kandinsky-Knick, der zu einem Knick in die gewünschte Richtung führt, ohne Kosten realisiert werden kann. Denn, falls der negative Zykel noch nicht gesättigt ist, sind die Kosten des KandinskyKnicks 2c − c − c = 0. Es besteht also die Möglichkeit, dass nur eine Einheit über (ub , uf ) fließt, wodurch ein Winkel von 180 Grad zwischen den Kanten e1 und e2 entsteht, aber der Knick dennoch durch den Kandinsky-Knick, w,r der durch Fluss über die Kante (ub0 , Hew,l 2 ) bzw. (ub0 , He2 ) verursacht wurde, eingehalten wird. Die Kante (ub , ub0 ) sorgt dafür, dass mindestens eine Einheit in den Knoten uf fließt. Ansonsten würde eine inkonsistente Form entstehen. 6.2. DER BASISALGORITHMUS 67 Transformation der vorgegebenen Form auf das Netzwerk Die endgültige Form aller Kanten wird durch den Min-Cost-Flow des Netzwerks bestimmt. Damit die vorgegebene Form der aufwärtsgerichteten Kanten beibehalten wird, muss diese entsprechend durch das Netzwerk formuliert werden. Um dies zu erreichen, geht man folgendermaßen vor: Für jeden Knick einer Kante wird ein Knickknoten b in den Graphen eingefügt, der die Kante aufteilt. Schließlich besitzen alle aufwärtsgerichteten Kanten nur noch eine einfache Form. Nun wird das Kandinsky-Netzwerk erstellt, wobei für Knickknoten nur die Knoten und Kanten aus Abb. 6.8(b) erzeugt werden müssen. Ist der Knickknoten mit einem gewöhnlichen Knoten benachbart, wird die zusätzliche Kante für mögliche Kandinsky-Knicke entsprechend eingefügt (vgl. Abb. 6.8(c)). Für je zwei aufeinanderfolgende aufwärtsgerichtete Kanten eines gewöhnlichen Knotens, muss ein Winkelknoten und die dazugehörigen Kanten erzeugt werden. Die Größe des Winkels kann durch die Form der betreffenden Kanten bestimmt werden. Liegen zwischen zwei aufwärtsgerichteten Kanten ungerichtete Kanten, dann werden diese, wie in Abbildung 6.9 dargestellt, behandelt. Vom Flussangebot des Winkelknotens muss dann außerdem die Anzahl der ungerichteten Kanten, die zwischen den beiden aufwärtsgerichteten Kanten liegen, abgezogen werden. e1 uh uf e3 ug e2 Abbildung 6.9: Behandlung von ungerichteten Kanten bei der Abbildung auf das Netzwerk. Die Kante e2 stellt eine ungerichtete Kante dar. Aufwärtsgerichtete Kanten dürfen außer den vorgegebenen Knicken keine weiteren Knicke erhalten, da sonst die Aufwärtsrichtung zerstört werden kann. Deshalb werden ihnen höhere Knickkosten zugewiesen. Um mit unterschiedlichen Knickkosten der Kanten arbeiten zu können, geht man folgendermaßen vor: Knicke, die keine Kandinsky-Knicke sind, werden durch Fluss zwischen zwei Faces verursacht. Knicke können, wie in [30] beschrieben, einer beliebigen Kante zugeordnet werden, die die beiden Faces abgrenzt. Bis jetzt besitzen all diese Kanten die Kosten cf . Man legt nun eine Kostenfunktion fest, die den Kanten abhängig vom Kantentyp unterschiedliche Kosten zu- 68 KAPITEL 6. EIN LAYOUTALGORITHMUS FÜR UML-KLASSENDIAGRAMME weist. Dabei sollte die billigste Kante mindestens cf Kosten. Eine mögliche Zuordnung wäre z.B.: M · cf falls e ∈ E↑ , cost(e) = cf sonst. Die Kante (uf , ug ) zwischen den Faces f und g bekommt jetzt die Kosten der billigsten Kante e zugewiesen, die die beiden Faces abgrenzt. Fließt Fluss über (uf , ug ), dann können die Knicke alle der Kante e zugewiesen werden. Neben den Kosten für Face-Knicke müssen auch die Kosten der KandinskyKnicke erhöht werden. Die Kosten für den Kandinsky-Knick einer Kante e betragen 2c + cost(e). Wenn man M = ∞ wählt, ist gewährleistet, dass eine aufwärtsgerichtete Kante niemals zusätzliche Knicke erhält. Nachdem das Min-Cost-Flow-Problem gelöst wurde, kann die quasi-orthogonale Repräsentation bestimmt werden. Nun besitzen alle Kanten eine Form. Die Knickknoten können jetzt wieder aus dem Graphen entfernt und durch die ursprünglichen Kanten ersetzt werden. Die Form der ursprünglichen Kanten setzt sich dabei aus den Formen der entsprechenden Kantenteile zusammen. Sei |E 0 | die Anzahl der Kanten des eingebetteten Graphen. Die Anzahl der vorgegebenen Winkel ist ≤ |E 0 | und die Anzahl der vorgegebenen Knicke ist ≤ 4|E 0 |. Da es sich um einen planaren Graphen handelt, kann die Transformation in O(|V | + c) stattfinden. Außerdem ist die Anzahl der Knoten im Netzwerk weiterhin O(|V | + c). Das Lösen des Netzwerkflussproblems kann 2 somit weiterhin in O (|V | + c) log(|V | + c) erfolgen. 6.2.4 Einheitliche Ausrichtung der aufwärtsgerichteten Kanten Bei der Formzuweisung der aufwärtsgerichteten Kanten wurde angenommen, dass der Subgraph G↑ zusammenhängend ist. Diese Annahme wird für die einheitliche Ausrichtung der aufwärtsgerichteten Kanten benötigt. Die Ausrichtung der Kanten ist immer relativ zu den jeweiligen Endpunkten, d.h. an einem Knoten zeigen alle aufwärtsgerichteten Kanten in dieselbe Richtung. Sind zwei Knoten durch eine aufwärtsgerichtete Kante verbunden, garantiert die Formzuweisung, dass die Knoten dieselbe Ausrichtung besitzen. Die aufwärtsgerichteten Kanten der beiden Knoten zeigen somit alle in dieselbe Richtung. Induzieren die Kanten der Menge E↑ keinen zusammenhängenden Subgraphen G↑ von G, dann sind die einzelnen Zusammenhangskomponenten von G↑ nicht gegeneinander ausgerichtet, da sie nur durch ungerichtete Kanten verbunden sind. Deren Form wird nicht vorgegeben, sondern durch den Netzwerkfluss bestimmt. Im folgenden wird ein Algorithmus vorgestellt, der gewährleistet, dass der Subgraph G↑ zusammenhängend ist. Handelt es sich bei dem Eingabegraph G um einen ungerichteten Graphen, d.h. E↑ = ∅, dann spielt die Ausrichtung der Kanten keine Rolle. An- 6.2. DER BASISALGORITHMUS 69 sonsten kann das Problem durch das Aufwärtsrichten ungerichteter Kanten wie folgt gelöst werden: • Zuerst wird auf den Kanten des Graphen G = (V, E) eine Kostenfunktion cost : E → {0, 1} definiert, wobei gilt: 0 falls e ∈ E↑ , cost(e) = 1 sonst. • Nun wird ein Spannbaum TG = (V, E 0 ) von G ermittelt, der bezüglich der Kostenfunktion cost minimale Kosten besitzt (vgl. Abb. 6.10(b)). Der Spannbaum enthält also möglichst wenige ungerichtete Kanten. • Sind alle Kanten des Spannbaumes aufwärtsgerichtet, ist die einheitliche Ausrichtung der Kanten gewährleistet, da G↑ dann zusammenhängend ist. Also müssen alle Kanten e = (v, w) für die gilt e ∈ E 0 und e ∈ / E↑ aufwärtsgerichtet werden. Es spielt dabei keine Rolle, ob die dann aufwärtsgerichtete Kante von v nach w oder von w nach v zeigt, da keine gerichteten Zyklen entstehen können (s. Satz 4). Nach dem Aufwärtsrichten dieser Kanten ist die korrekte Ausrichtung gewährleistet und es gilt: E 0 ⊆ E↑ . Satz 4 Sei TG = (V, E 0 ) ein Spannbaum von G mit minimalen Kosten bezüglich der Kostenfunktion cost. Durch das Aufwärtsrichten einer ungerichteten Kante e ∈ E 0 können keine gerichteten Zyklen in G entstehen. Beweis: Angenommen durch das Aufwärtsrichten der ungerichteten Kante e = (v, w) entsteht ein gerichteter Zyklus in G. Da ein Spannbaum per Definition keine Zykel enthalten kann, müssen aufwärtsgerichtete Kanten e0 ∈ E↑ \ E 0 existieren, die an dem gerichteten Zyklus beteiligt sind. Wenn man die Kante e aus dem Spannbaum entfernt, zerfällt dieser in zwei Komponenten Tv und Tw , wobei v ∈ Tv und w ∈ Tw . Auf dem gerichteten Zykel existiert nun eine Kante e0 = (v 0 , w0 ) ∈ E↑ \ E 0 , für die gilt: w0 ∈ Tv und v 0 ∈ Tw . Durch die Hinzunahme dieser Kante entsteht ein Spannbaum, dessen Kosten um eine Einheit geringer sind, als die Kosten von TG . Der Spannbaum TG besitzt also keine minimalen Kosten, was ein Widerspruch zur Annahme darstellt. Die folgende Beobachtung kann zur Verbesserung des Algorithmus verwendet werden: Nur Knoten mit aufwärtsgerichteten Kanten benötigen eine einheitliche Ausrichtung. Es genügt also, wenn alle Kanten eines zusammenhängenden Subgraphs, der all diese Knoten enthält, aufwärtsgerichtet werden. Der Algorithmus berechnet aber einen minimalen Spannbaum des Graphen G. Ausgehend von dem minimalen Spannbaum kann der Subgraph KAPITEL 6. EIN LAYOUTALGORITHMUS FÜR UML-KLASSENDIAGRAMME 70 1 1 1 0 0 2 2 3 1 3 2 3 1 4 0 1 5 4 6 0 8 6 4 6 1 7 5 8 7 5 8 7 1 9 9 (a) (b) 9 (c) Abbildung 6.10: Bestimmung eines zusammenhängenden Subgraphs, der alle Knoten mit aufwärtsgerichteten Kanten enthält. Die markierten Kanten sind ungerichtete Kanten, die aufwärtsgerichtet werden müssen. (a) zeigt den Ausgangsgraph und die dazugehörigen Kantenkosten. (b) stellt den dazugehörigen minimalen Spannbaum dar und (c) den zusammenhängenden Subgraph. folgendermaßen ermittelt werden: Falls ein Blatt des Spannbaumes eine ungerichtete Kante besitzt, kann diese entfernt werden. Dadurch entstehen eventuell neue Blätter. Besitzt ein neues Blatt ebenfalls eine ungerichtete Kante, kann auch diese entfernt werden. Der Vorgang wird solange wiederholt, bis der Subgraph nur noch Blätter mit aufwärtsgerichteten Kanten besitzt. Aus dem minimalen Spannbaum aus Abb. 6.10(b) entsteht so der Subgraph aus Abb. 6.10(c). Algorithmus 1 berechnet den Subgraph. Aus folgenden Gründen lohnt sich diese Verbesserung: • Aufwärtsgerichtete Kanten verursachen oft zusätzliche Kreuzungen und Knicke, deshalb sollte deren Zahl nicht unnötig erhöht werden. • Da in UML-Klassendiagrammen häufig die Zahl der Assoziationsbeziehungen dominiert, existieren oft viele ungerichtete Kanten, die durch diese Verbesserung nicht aufwärtsgerichtet werden müssen. Die Gesamtlaufzeit setzt sich wie folgt zusammen: Die Zuweisung der Kantengewichte geht in O(|E|). Da der Layoutalgorithmus für jede Zusammenhangskomponente eines Graphen ausgeführt wird, ist der Graph G zusammenhängend. Ein minimaler Spannbaum (minimum spanning tree) kann 6.3. VERBESSERUNGEN DES BASISALGORITHMUS 71 Algorithmus 1 : Verbesserung des Orientierungsalgorithmus. Eingabe: TG = (V , E 0 ), ein minimaler Spannbaum von G E↑ , die Menge der aufwärtsgerichteten Kanten Ausgabe: Kantenmenge E 0 , die einen zusammenhängenden Subgraph von G induziert, der alle Knoten mit aufwärtsgerichteten Kanten enthält Leaves ← {v ∈ V : δE 0 (v) = 1} while Leaves 6= ∅ do v ← Element aus Leaves e ← die zu v inzidente Kante if e ∈ / E↑ then w ← der Nachbarknoten von v E 0 ← E 0 \ {e} if δE 0 (w) = 1 then Leaves ← Leaves ∪ {w} fi fi Leaves ← Leaves \ {v} od so mit Prim’s Algorithmus in O(|E| log |V |) berechnet werden. Das Aufwärtsrichten der ungerichteten Kanten kann in O(|E|) erledigt werden. Die Laufzeit des Algorithmus 1 setzt sich wie folgt zusammen: Bestimmung der Knoten mit Grad 1 geht in O(|V |). Ein Spannbaum besitzt |V | − 1 Kanten. Jeder Knoten wird höchstens einmal in Leaves aufgenommen. Das Bestimmen, ob ein Knoten Grad 1 besitzt, geht in O(1). Also ergibt sich für die Verbesserung eine Laufzeit von O(|V |) und somit eine Gesamtlaufzeit von O(|E| log |V |). 6.3 Verbesserungen des Basisalgorithmus Im vorherigen Abschnitt wurde der Basisalgorithmus vorgestellt. In diesem Abschnitt werden Verbesserungen für den Basisalgorithmus erläutert. 6.3.1 Einbettung Die Einbettung basiert auf der in Abschnitt 5.2 beschriebenen Vorgehensweise. Anstatt alle gerichteten Kanten aufwärtsplanar einzubetten, ist das nur für Kanten aus E↑ nötig. Die im folgenden beschriebenen Erweiterungen zielen darauf ab, die Kanten aus ETree möglichst schön darzustellen. Dazu müssen folgende Punkte erfüllt werden: KAPITEL 6. EIN LAYOUTALGORITHMUS FÜR UML-KLASSENDIAGRAMME 72 1. Kreuzungen zwischen Baumkanten sollten möglichst vermieden werden, da der Baum sonst nicht zufriedenstellend dargestellt werden kann. 2. Die Bäume sollten so eingebettet werden, dass sie möglichst wenig Kreuzungen mit anderen Kanten besitzen. Der erste Punkt kann durch eine Modifikation der GT-Heuristik realisiert werden und der zweite Punkt durch unterschiedliche Gewichte beim Routen der Kanten. Änderung an der GT-Heuristik Um zu verhindern, dass sich Baumkanten gegenseitig kreuzen, sollten sie möglichst alle im initialen planaren Subgraphen enthalten sein. Beim nachträglichen Routen der Baumkanten über den Routinggraph kann die Überkreuzungsfreiheit nicht garantiert werden. Durch die hier vorgestellte Modifikation der ersten Phase der GT-Heuristik wird eine Knotenfolge erzeugt, die zusammen mit einer geeigneten Kantengewichtung bei der Berechnung der Maximum Independent Sets in der zweiten Phase, zu einem planaren Subgraphen mit möglichst vielen Baumkanten führen soll. Dazu folgender Satz: Satz 5 Sei T = (V, E) ein Baum mit Wurzel r und Π die Knotenfolge, die bei einer Tiefensuche von r aus entsteht. Dann gibt es keine Kantenpaare e1 , e2 ∈ E, die sich bezüglich der Knotenfolge Π schneiden (vgl. Abschnitt 5.2.1). Beweis: Angenommen es gibt eine Überschneidung zweier Kanten aus E, dann gibt es Baumknoten a, b, c, d und Kanten e1 = (a, c), e2 = (b, d) für die gilt: e1 überkreuzt e2 (vgl. Abb. 6.11). Da b nach a und vor c steht und c Kind von a ... b ... c ... d Abbildung 6.11: Zwei Kanten die sich bezüglich der Knotenfolge überschneiden. a ist, muss b wegen der DFS-Ordnung ein Nachfolger von a sein. Da a direkt mit c verbunden ist, kann c nicht Nachfolger von b sein. Da d in der Knotenfolge hinter c steht, kann d wegen der DFS-Ordnung kein Nachfolger von b und somit auch kein Kind von b sein, was ein Widerspruch zur Annahme darstellt. 6.3. VERBESSERUNGEN DES BASISALGORITHMUS 73 Da die aufwärtsgerichteten Kanten in UML-Graphen zur Wurzel zeigen, darf ein Baumknoten v erst dann in die Knotenfolge aufgenommen werden, wenn schon alle Kinder von v in der Knotenfolge enthalten sind. Wird die Knotenfolge, die bei einer Tiefensuche entsteht, umgedreht, ist diese Bedingung erfüllt und Satz 5 immer noch anwendbar. Eine solche Knotenfolge führt dazu, dass alle Kanten des Baumes in die Maximum Independent Sets aufgenommen werden können. Unter der Annahme ETree = E↑ trifft nun folgendes zu: Enthält ETree mehrere Bäume, dann kann die Knotenfolge durch Aneinanderketten der Knotenfolgen der einzelnen Bäume erzeugt werden. Das ist möglich, da die Bäume in ETree als Knotendisjunkt angenommen wurden. Die Knotenfolge enthält nun alle Baumknoten. Die restlichen Knoten können mit der ursprünglichen Heuristik, die in Abschnitt 5.2.1 vorgestellt wurde, in die Knotenfolge mitaufgenommen werden. Damit nun alle Baumkanten in die Maximum Independent Sets aufgenommen werden, müssen diese, wie in Abschnitt 5.2.1 beschrieben, bezüglich des maximalen Gewichts der enthaltenen Kanten bestimmt werden. Wenn man den Baumkanten ein entsprechend höheres Gewicht (z.B. das |E|-fache) als den anderen Kanten zuweist, befinden sich alle Baumkanten in den Maximum Independent Sets und können sich somit nicht gegenseitig überkreuzen. Im allgemeinen Fall trifft die Annahme ETree = E↑ nicht zu. Dann kann es passieren, dass ein Baumknoten nicht in die Knotenfolge aufgenommen werden kann, da Knoten w mit (w, v) ∈ E↑ existieren, die noch nicht in der Knotenfolge enthalten sind. Der Baumknoten ist dann so lange blockiert, bis alle Knoten w in die Knotenfolge aufgenommen wurden. Dadurch kann nicht mehr gewährleistet werden, dass die Knoten eines Baumes nacheinander, in der Reihenfolge einer Tiefensuche, in der Knotenfolge erscheinen. In solchen Fällen kann es passieren, dass Kreuzungen zwischen Baumkanten unvermeidlich sind. Ein Algorithmus, der auch für den allgemeinen Fall eine gültige Knotenfolge erzeugt, stellt Algorithmus 2 dar. Er ordnet die Knoten zunächst so an, dass für jedes Knotenpaar v,w gilt: (v, w) ∈ E↑ ⇒ π(w) < π(v), wobei π(u) die Position des Knotens u in der Knotenfolge angibt. Diese Modifikation wird auch auf die ursprüngliche Heuristik übertragen. Dadurch wird die Berechnung der Reihenfolge der Baumknoten vereinfacht, da die Bäume von der Wurzel aus durchlaufen werden können. Nachdem die gesamte Knotenfolge ermittelt wurde, wird diese einfach umgedreht, womit wieder die ursprüngliche Bedingung (v, w) ∈ E↑ ⇒ π(v) < π(w) erfüllt ist. Ein Knoten wird als frei bezeichnet, wenn er von keinem anderen Knoten blockiert wird und noch nicht in der Knotenfolge Order enthalten ist. Auf den Stack werden alle Wurzeln der Bäume aus ETree gelegt. Wird ein Baumknoten v vom Stack geholt, gilt folgendes: • Ist der Baumknoten v frei, dann wird er in die Knotenfolge aufgenommen und seine Kinder werden in zufälliger Reihenfolge auf den Stack 74 KAPITEL 6. EIN LAYOUTALGORITHMUS FÜR UML-KLASSENDIAGRAMME Algorithmus 2 : Berechnung der modifizierten Knotenfolge (1.Phase GT). Eingabe: G = (V , E) ETree , die Menge der Baumkanten E↑ , die Menge der aufwärtsgerichteten Kanten Ausgabe: Order, die modifizierte Knotenfolge v ist frei ⇒ @ w : (v, w) ∈ E↑ ∧ w ∈ / Order VTree ← v : ∃ e ∈ ETree für die v Endpunkt ist Order ← ∅ Stack ← die Wurzeln der Bäume von ETree in zufälliger Reihenfolge forall v ∈ VTree do seen[v] ← false od while ∃ v ∈ / Order do while Stack 6= ∅ do v ← hole oberstes Element von Stack runter seen[v] ← true if v ist frei then füge v in Order ein lege alle Kinder von v in zufälliger Reihenfolge auf den Stack forall w ∈ VTree : (w, v) ∈ E↑ ∧ w ist frei ∧ seen[w] do lege w auf den Stack od fi od while Stack = ∅ ∧ ∃ v ∈ V \ VTree : v ∈ / Order do GSub ← von V \ Order induzierter Subgraph von G if N eighbours = ∅ then Candidates ← freie nicht Baumknoten mit minimalem Grad in GSub else Candidates ← freie nicht Baumknoten mit minimalem Grad in GSub die in N eighbours sind fi v ← zufällig gewählter Knoten aus Candidates füge v in Order ein N eighbours ← alle freien Nachbarn von v die keine Baumknoten sind forall w ∈ VTree : w ist frei do lege w auf den Stack od do do drehe Order um 6.3. VERBESSERUNGEN DES BASISALGORITHMUS 75 gelegt. Wird dadurch ein anderer Baumknoten w frei, der bereits auf dem Stack war (seen[w]), dann wird dieser erneut auf den Stack gelegt. • Ist der Baumknoten v nicht frei, holt der Algorithmus den nächsten Baumknoten vom Stack. Sobald der Knoten v frei wird, wird er wieder auf den Stack gelegt. Falls ETree = E↑ entsprechen die Knotenfolgen der einzelnen Bäume einer Tiefensuche. Befinden sich keine Baumknoten auf dem Stack, weil gerade alle blockieren oder schon alle in Order enthalten sind, dann werden so lange Nicht-Baumknoten in die Knotenfolge Order eingefügt, bis ein blockierter Baumknoten frei wird oder alle Nicht-Baumknoten in Order eingefügt wurden. Das Einfügen der Nicht-Baumknoten erfolgt dabei mit der bestehenden Heuristik. Der Algorithmus terminiert, da der durch die Kantenmenge E↑ induzierte Subgraph von G azyklisch ist, wodurch immer ein nicht blockierender Knoten gefunden werden kann. Da die Liste Neighbours nur freie Nicht-Baumknoten enthält, ändert sich deren Inhalt nicht, wenn zwischendurch Baumknoten bearbeitet werden. Algorithmus 2 ist recht einfach gehalten. Durch die Verwendung der in Abschnitt 5.2.1 beschriebenen Randomisierung erzielt er in der Praxis aber gute Ergebnisse und produziert nur selten Überkreuzungen zwischen zwei Baumkanten. Wegen der Randomisierung werden die Wurzeln der Bäume und die Kinder eines Baumknotens in zufälliger Reihenfolge auf den Stack gelegt. Außerdem wird der Nicht-Baumknoten aus Candidates zufällig gewählt. Für den vorgestellten Algorithmus gilt folgendes: • Der Algorithmus produziert eine Knotenfolge für die gilt: (v, w) ∈ E↑ ⇒ v steht vor w in der Knotenfolge. Dies ist notwendig, um die Kantenmenge E↑ aufwärtsplanar einbetten zu können. • Falls ETree = E↑ existieren keine Baumkanten, die sich überkreuzen. • Falls E↑ = ∅ entspricht die Knotenfolge der Knotenfolge der ursprünglichen Heuristik. Lemma 2 Algorithmus 2 berechnet die Knotenfolge in der Laufzeit O(|V |2 + |E|). Beweis: Der Grad der Knoten im Eingabegraph sowie die Wurzeln der Bäume können in O(|V | + |E|) bestimmt werden. Beim Einfügen eines Knotens in Order , muss der Grad sämtlicher Nachbarn des Knotens korrigiert werden, was O(|V |) benötigt. Für jeden freien Baumknoten werden dessen Kinder auf den Stack gelegt, was ebenfalls in O(|V |) erledigt werden kann. Wird ein 76 KAPITEL 6. EIN LAYOUTALGORITHMUS FÜR UML-KLASSENDIAGRAMME Baumknoten vom Stack genommen, weil er blockiert, dann kommt er erst wieder auf den Stack, nachdem er frei geworden ist. Ein Baumknoten wird also höchstens zweimal auf den Stack gelegt. Die Berechnung der Knotenmenge Candidates und Neighbours benötigt die Laufzeit O(|V |) je Iteration. Es gibt maximal O(|V |) Iterationen, da in jeder Iteration ein Nicht-Baumknoten in Order eingefügt wird. Also ergibt sich eine Gesamtlaufzeit von O(|V |2 +|E|). Wenn man den initialen planaren Subgraphen durch einen minimalen Spannbaum bestimmt, wobei die Kantenkosten so gewählt werden, dass alle Baumkanten im minimalen Spannbaum enthalten sind, kann auf jeden Fall erreicht werden, dass sich keine Baumkanten überkreuzen. Da der planare Subgraph dann aber in der Regel deutlich weniger Kanten besitzt, müssen sehr viele Kanten nachträglich geroutet werden, was die reale Laufzeit deutlich erhöhen kann. Änderungen beim Routing Nachdem der initiale planare Subgraph ermittelt wurde, werden die Restkanten in den Graphen geroutet. Dabei wählt man immer eine Route, die am wenigsten Kosten verursacht. Um zu erreichen, dass Baumkanten möglichst wenige Kreuzungen mit anderen Kanten besitzen, werden deren Kreuzungskosten entsprechend erhöht. Falls nicht alle Baumkanten im planaren Subgraph enthalten sind, wird dadurch außerdem erreicht, dass sich zwei Baumkanten wegen der hohen Kosten nur dann kreuzen, wenn keine billigere Route gefunden werden kann. Das Zuweisen der hohen Kreuzungskosten geschieht folgendermaßen: Für das Routen der aufwärtsgerichteten Kanten wird der Routinggraph verwendet. Für zwei benachbarte Faces f und g, die sich auf derselben Ebene i befinden, enthält der Routinggraph die gerichteten Kanten (vf,i , vg,i ) und (vg,i , vf,i ) (vgl. Abschnitt 5.2.2). Ist die Kante, die die beiden Faces f und g auf der Ebene i abgrenzt, eine normale aufwärtsgerichtete Kante, besitzt sie die Kosten 1. Handelt es sich bei der Kante um eine Baumkante, wird dieser einfach ein höheres Gewicht zugewiesen. Für das Routen der ungerichteten Kanten wird der duale Graph verwendet, dessen Kanten normalerweise die Kosten 1 besitzen. Da jede Kante des dualen Graphs eine Kante des zugrundeliegenden Graphs repräsentiert, können die Kosten für Kanten, die Baumkanten repräsentieren, einfach entsprechend erhöht werden. Durch die Erhöhung der Knickkosten der Baumkanten entsprechen die Kosten der billigsten Route im allgemeinen nicht mehr der Anzahl der entstehenden Kreuzungen beim Einfügen einer Kante. Die Laufzeit für das Routen der Kanten verschlechtert sich durch diese Modifikation aber nicht. 6.3. VERBESSERUNGEN DES BASISALGORITHMUS 6.3.2 77 Höhenkanten Ein Ästhetikkriterium für hierarchische Darstellungen ist die Positionierung von Geschwisterknoten auf gleicher Höhe. Bei UML-Klassendiagrammen bietet sich das Kriterium für die Darstellung von Vererbungsbeziehungen an. Zusammen mit den Vererbungsgabeln entstehen dann klare, schnell zu erfassende Vererbungshierarchien. Eine einheitliche Höhe von Geschwisterknoten kann allerdings nicht immer erzielt werden, da andere Kriterien, wie z.B. die Aufwärtsrichtung von Kanten, Vorrang haben. Die hier vorgestellte Vorgehensweise basiert darauf, „künstliche“ Kanten zwischen benachbarten Geschwisterknoten einzufügen, die dann für eine einheitliche Höhe sorgen sollen. Diese Kanten werden deshalb Höhenkanten genannt. v u1 v u3 u1 u2 u3 u2 Abbildung 6.12: Erzeugen von Höhenkanten zwischen Geschwisterknoten. Oft sollen nur die Geschwisterknoten einer bestimmten Kantenmenge auf gleicher Höhe gezeichnet werden. Für den Layoutalgorithmus sind das alle Geschwisterknoten der von der Kantenmenge ETree ∩ EHyp induzierten Bäume. Durch diese Festlegung sind Hyperkanten-Hilfsknoten die einzigsten Knoten, die Kinder besitzen, die auf gleicher Höhe platziert werden sollen. Wenn man davon ausgeht, dass ein Hyperkanten-Hilfsknoten immer nur gleichartige Kanten zusammenfasst, kann man folgendermaßen vorgehen: Für jeden Hyperkanten-Hilfsknoten v ∈ VDummy , der Baumkanten zusammenfasst, werden einfach alle aufeinanderfolgenden Kinderpaare durch eine Höhenkante verbunden, wie es in Abb. 6.12 dargestellt wird. Für jede eingefügte Höhenkante entsteht dabei ein neues Face. Wenn die Höhenkanten horizontal und ohne Knick zwischen den Geschwisterknoten liegen, besitzen diese eine einheitliche Höhe. Die Höhenkanten werden nach der Kompaktierung wieder aus dem Graphen entfernt. Es gibt einige Besonderheiten, die beim Einfügen von Höhenkanten beachtet werden müssen, damit ein zufriedenstellendes Ergebnis erzielt werden kann. Werden Höhenkanten ungünstig eingefügt, führt das oft zu schlechten Layouts. In einigen Fällen ist es sogar besser, auf eine Höhenkante zwischen zwei Geschwisterknoten zu verzichten. Ein Knick einer Höhenkante führt dazu, dass die entsprechenden Geschwisterknoten nicht auf gleicher Höhe liegen, womit die Höhenkante ihren Zweck nicht erfüllt. Deshalb erhalten die Höhenkanten während der Orthogo- 78 KAPITEL 6. EIN LAYOUTALGORITHMUS FÜR UML-KLASSENDIAGRAMME nalisierung höhere Knickkosten als normale ungerichtete Kanten. Dazu wird die Kostenfunktion von Abschnitt 6.2.3 so erweitert, dass jede Höhenkante die Kosten cf + 1 erhält. Wird eine Höhenkante knickfrei gezeichnet, sorgt sie für eine einheitliche Höhe der dazugehörigen Geschwisterknoten, da sie dann horizontal zwischen ihren Endpunkten liegen muss. Eine knickfreie Höhenkante kann nicht vertikal zwischen ihren Endpunkten liegen, da die ausgehenden Baumkanten der Geschwisterknoten höhere Kosten besitzen und die Höhenkante somit einen Kandinsky-Knick bekommen würde. Die Höhenkanten können erst nach der Einbettung der aufwärtsgerichteten Kanten eingefügt werden, da die Ordnung der Geschwisterknoten feststehen muss. Beim Einfügen einer Höhenkante sollte vermieden werden, dass das innere Face, das durch die beiden Kanten von den Geschwisterknoten zum Vater und der Höhenkante begrenzt wird, Knoten enthält. Ansonsten führt die Höhenkante dazu, dass die Geschwisterknoten weiter entfernt von ihrem Vater platziert werden und die Vererbungshierarchie dadurch unübersichtlicher wird. Um die Höhenkanten geeignet einfügen zu können, routet man sie deshalb nicht über den dualen Graph, sondern fügt sie durch direkte Modifikation der betreffenden Faces ein. Für alle benachbarten Geschwisterknoten, die auf einer einheitlichen Höhe platziert werden sollen, geht man folgendermaßen vor: • Falls einer der beiden Geschwisterknoten neben der Vererbungskante noch eine weitere ausgehende, aufwärtsgerichtete Kante besitzt, sollte keine Höhenkante eingefügt werden. Dies hat folgenden Grund: Wegen der kreuzungsminimalen Einbettung werden die aufwärtsgerichteten Kanten oft seitlich an der Vererbungsstruktur vorbeigeführt. Wie Abb. 6.13(a) zeigt, könnte dann eine Höhenkante zwischen den Knoten u1 und u2 auf keinen Fall ihren Zweck erfüllen. Eine Höhenkante zwischen den Knoten u2 und u3 würde dazu führen, dass die Knoten u3 und u4 weiter weg vom Vaterknoten platziert würden. Dieser Effekt würde auch eintreten, falls die aufwärtsgerichtete Kante von u2 nicht seitlich an der Vererbungsstruktur vorbeigeführt wird, sondern unter dieser liegt. Die einzigste Ausnahme, wo eine Höhenkante sinnvoll wäre, ist, wenn der Knoten mit der aufwärtsgerichteten Kante am Rand liegt und die Kante an der entsprechenden Seite vorbeigeführt wird, wie beim Knoten u5. • Existiert schon eine ungerichtete Kante zwischen zwei benachbarten Geschwisterknoten im Eingabegraph, dann sollte keine zusätzliche Höhenkante eingefügt werden. Ansonsten würden Knicke entstehen, da im Kandinsky-Modell keine Kanten mit denselben Endpunkten vollständig parallel verlaufen können. Die bestehende Kante stellt in diesem Fall schon eine Art „natürliche“ Höhenkante dar (vgl. Abb. 6.13(b)). Man weist solchen Kanten deshalb dieselben Knickkosten zu wie den 6.3. VERBESSERUNGEN DES BASISALGORITHMUS 79 Höhenkanten. Da die ungerichteten Kanten aber über den dualen Graph geroutet werden, kann nicht gewährleistet werden, dass diese „günstig“ eingebettet werden. v w2 w3 w1 v u5 u1 u3 u4 u1 u2 (a) v w1 u1 u2 w2 (c) w3 u3 (b) w1 u3 u2 u1 v v u2 w2 (d) u3 u1 u2 u3 w (e) Abbildung 6.13: Verschiedene Fälle, die beim Einfügen von Höhenkanten auftreten können. Die Höhenkanten sind gestrichelt gezeichnet, die aufwärtsgerichteten Kanten besitzen einen Pfeil und die Baumkanten sind zusätzlich dick gezeichnet. Die restlichen Kanten werden durch normale Linien repräsentiert. Ein schwarzer Punkt kennzeichnet eine Kreuzung. • Wenn auf die Höhenkante nicht schon wegen einer der beiden vorherigen Punkte verzichtet wurde, fügt man sie so ein, dass ein Face aus den Kanten der beiden Geschwisterknoten zu ihrem Vater und der Höhenkante entsteht. Weitere inzidente Kanten der Geschwisterknoten liegen damit außerhalb des Faces (vgl. Abb. 6.13(c)). Solche Faces können nur erzeugt werden, wenn die beiden Kanten von den Geschwisterknoten zum Vater keine Kreuzungen besitzen. Wird eine der beiden Kanten gekreuzt, verzichtet man auf eine Höhenkante (Abb. 6.13(d)). Solche Fälle treten aufgrund der gewählten Kreuzungskosten aber eher selten auf. Kann die Höhenkante entsprechend eingefügt werden, ist die einheitliche Höhe der Geschwisterknoten gewährleistet, falls keine nachfolgend 80 KAPITEL 6. EIN LAYOUTALGORITHMUS FÜR UML-KLASSENDIAGRAMME geroutete Kante mehr das Face verändert. Damit Höhenkanten möglichst selten gekreuzt werden, erhalten sie höhere Kreuzungskosten als normale ungerichtete Kanten (vgl. Abschnitt 6.3.1). Die Laufzeit der vorgestellten Vorgehensweise setzt sich folgendermaßen zusammen: Der Algorithmus läuft alle Knoten v ∈ VDummy , die Baumkanten zusammenfassen, ab und schaut sich deren Kindknoten an. Vor dem Einfügen einer Höhenkante zwischen zwei benachbarten Geschwisterknoten muss an beiden Knoten überprüft werden, ob eine weitere ausgehende, aufwärtsgerichtete Kante existiert, ob die ausgehende Baumkante von einer anderen Kante gekreuzt wird und ob schon eine ungerichtete Kante zwischen den Geschwisterknoten existiert. Die Überprüfungen gehen in O(|V | + c). Es existieren maximal O(|V |) benachbarte Geschwisterpaare. Das Teilen des Faces beim Einfügen einer Höhenkante geht in der Laufzeit O(|V |+c). Da eine Höhenkante durch Kreuzungen geteilt sein kann, müssen nach der Kompaktierung O(|V | + c) Kanten aus dem Graph entfernt werden. Die Gesamtlaufzeit beträgt somit O(|V |2 + |V | · c). Bis jetzt wurde das Konzept nur auf Geschwisterknoten, der von der Kantenmenge ETree ∩ EHyp induzierten Bäume angewendet. Sollen dagegen alle Geschwisterknoten, der von der Kantenmenge ETree induzierten Bäume, auf einer einheitlichen Höhe positioniert werden, können nicht mehr einfach alle benachbarten Geschwisterknoten durch eine Höhenkante verbunden werden. Es existieren jetzt nämlich auch Geschwisterknoten, die nicht durch Kanten aus ETree entstanden sind und somit nicht auf der gleichen Höhe gezeichnet werden sollen. Dadurch wird das geschickte Einfügen von Höhenkanten erschwert. Abb. 6.13(e) zeigt eine Möglichkeit, wie man in diesem Fall die Höhenkante einfügen kann. Da dieser Fall häufig auftreten kann, können die Höhenkanten nicht einfach weggelassen werden. Soll das Konzept auf alle Geschwisterknoten, des von der Kantenmenge E↑ induzierten Graphen, angewendet werden, muss außerdem folgendes beachtet werden: Da der Subgraph im allgemeinen keinen Baum darstellt, kann ein Knoten mehrere ausgehende, aufwärtsgerichtete Kanten und somit auch Geschwister von verschiedenen Vätern besitzen. Das Konzept kann dann nicht mehr ohne weiteres angewendet werden. Da die Knoten unterschiedliche Größen besitzen und sie jeweils mit ihrem Mittelpunkt auf dem Gitter angeordnet werden, bedeutet eine einheitliche Höhe von Geschwisterknoten also eine einheitliche Höhe der Mittelpunkte der Knoten. Wenn die einheitliche Höhe von Geschwisterknoten in der Kompaktierungsphase realisiert wird, kann das Problem besser gelöst werden, da die Kompaktierung die unterschiedliche Größe der Knoten berücksichtigt. Auch die anderen aufgetretenen Probleme können eventuell besser in der Kompaktierungsphase gelöst werden. 6.3. VERBESSERUNGEN DES BASISALGORITHMUS 6.3.3 81 Behandlung von Selbstschleifen Für die Bestimmung des planaren Subgraphen durch die GT-Heuristik werden die Selbstschleifen aus dem Graphen genommen. Danach werden sie normalerweise wie gewöhnliche ungerichtete Kanten, die sich noch nicht im planaren Subgraph befinden, in den Graphen geroutet. Während der Orthogonalisierung wird ihre Form durch den Netzwerkfluss bestimmt. Diese Vorgehensweise hat folgenden Nachteil: Bei einer ungünstigen Einbettung kann es vorkommen, dass die Selbstschleifen ein schlechtes Layout mit vielen Knicken bekommen (vgl. Abb. 6.14(a)). Gerade wenn sich mehrere Selbstschleifen an einem Knoten befinden, was bei UML-Klassendiagrammen durchaus üblich ist, enstehen dann unleserliche Zeichnungen. Um solche Layouts zu verhindern, kann man die Selbstschleifen erst nach der Orthogonalisierung einfügen, bevor die Zeichnung kompaktiert wird. Durch diese Vorgehensweise ergeben sich folgende Vorteile: 4 3 4 3 1 1 2 (a) 2 (b) Abbildung 6.14: Zwei alternative Platzierungen einer Selbstschleife. • Während der Einbettungsphase müssen weniger ungerichtete Kanten in den Graphen geroutet werden. • Das zu lösende Netzwerkflussproblem enthält weniger Knoten und Kanten (jede Selbstschleife erzeugt ein neues Face). • Da die Form der restlichen Kanten nach der Orthogonalisierung bereits feststeht, kann die Selbstschleife an einer geeigneten Stelle am Knoten, mit einer geeigneten Form, platziert werden (vgl. Abb. 6.14(b)). KAPITEL 6. EIN LAYOUTALGORITHMUS FÜR UML-KLASSENDIAGRAMME 82 O0 O1 O2 O0 L2 R0 L1 R1 L0 R2 O1 O2 L2 R0 L1 R1 L0 U2 U1 (a) U0 R2 U2 U1 U0 (b) Abbildung 6.15: Aufteilung der Kanten auf die Ports und mögliche Anordnung der Selbstschleifen. Bevor der modifizierte Einfügealgorithmus vorgestellt wird, wird der Begriff „Port“ erläutert. Ein Port ist ein Anschluss eines Knotens, an dem sich Kanten befinden können (vgl. Abb. 6.15). Jede Knotenseite besitzt drei Ports. Die drei Ports der oberen Knotenseite werden mit O0, O1 und O2 bezeichnet. An den Ports O1, R1, U1 und L1 liegt die nicht knickendene Mittelkante. An den Ports O0, R0, U0 und L0 liegen die Kanten, die vom Knoten aus gesehen nach links knicken, an den Ports O2, R2, U2 und L2 die Kanten die nach rechts knicken. Natürlich müssen nicht alle Ports belegt sein. Der nun beschriebene Einfügealgorithmus für Selbstschleifen verwendet die vier verschiedenen Positionierungsmöglichkeiten, die in Abb. 6.15(b) zu sehen sind. Er nutzt dabei folgende Eigenschaft der Selbstschleifen aus: Eine Selbstschleife kann stets, unabhängig von den anderen Kanten des Knotens, an einer beliebigen Ecke des Knotens platziert werden, ohne dass dabei Überkreuzungen mit anderen Kanten entstehen. Durch eine solche Platzierung besitzt jede Selbstschleife genau drei Knicke, was der minimalen Anzahl von Knicken einer Selbstschleife im Kandinsky-Modell entspricht. Um die günstigste Ecke für eine Selbstschleife zu finden, wird Algorithmus 3 verwendet. Mit O werden die drei Ports O0, O1 und O2 an der Oberseite des Knotens bezeichnet. Analog werden die drei Ports der anderen Seiten mit L, U und R bezeichnet. |O0| gibt die Anzahl der Kanten an, die den Port O0 belegen, |O| die Anzahl aller Kanten, die von der Oberseite ausgehen. Es gilt also |O|=|O0|+|O1|+|O2|. Außerdem ist |O2+R0| eine Abkürzung für |O2|+|R0|. |Ecke| bzw. |Seiten| gibt die Anzahl der Kanten an, die an den Ports der entsprechenden Variablen liegen. Der Algorithmus platziert eine Selbstschleife an einer Ecke mit möglichst wenigen Kanten. Zur Bestimmung einer geeigneten Ecke wird neben der Anzahl der Kanten an der Ecke, auch die Anzahl der Kanten an den beiden Seiten der Ecke berücksichtigt. Der Algorithmus versucht also eine gleichmäßige 6.3. VERBESSERUNGEN DES BASISALGORITHMUS 83 Algorithmus 3 : Platzierung einer Selbstschleife. Eingabe: die Ports eines Knotens v und deren Kardinalität Ausgabe: Ecke, enthält günstigste Position für die Selbstschleife Ecke ← O2,R0 Seiten ← O,R if |Ecke| > |R2+U0| ∨ |Ecke| = |R2+U0| ∧ |Seiten| > |R+U| then Ecke ← R2,U0 Seiten ← R,U fi if |Ecke| > |U2+L0| ∨ |Ecke| = |U2+L0| ∧ |Seiten| > |U+L| then Ecke ← U2,L0 Seiten ← U,L fi if |Ecke| > |L2+O0| ∨ |Ecke| = |L2+O0| ∧ |Seiten| > |L+O| then Ecke ← L2,O0 Seiten ← L,O fi Kantenverteilung um den Knoten zu erreichen, da diese zu übersichtlicheren Zeichnungen führt. Die Variable Ecke beinhaltet die beiden Ports, an denen die Selbstschleife platziert werden soll. Beim Einfügen einer Selbstschleife muss die orthogonale Repräsentation entsprechend modifiziert werden. Jede Selbstschleife erzeugt dabei ein neues Face. Die Form der Selbstschleife entspricht je nach Platzierung einer der Formen aus Abb. 6.15(b). Für Knoten mit mehreren Selbstschleifen existieren zwei verschiedene Vorgehensweisen: • Alle Selbstschleifen eines Knotens werden an derselben Ecke platziert. • Für jede Selbstschleife eines Knotens wird die geeignetste Position von neuem bestimmt. Es wird angenommen, dass sich die Anzahl der Mehrfachkanten linear zu O(|V |) verhält. Das Finden und Entfernen der Selbstschleifen aus dem Eingabegraph benötigt O(|E|), was mit O(|V |+c) abgeschätzt werden kann. Das Bestimmen der Anzahl der Kanten an den Ports der Knoten geht in O(|V | + c). Das Bestimmen der Position einer Selbstschleife geht in O(1) und das Einfügen sämtlicher Selbstschleifen in O(|V | + c). Somit ergibt sich eine Gesamtlaufzeit von O(|V | + c). KAPITEL 6. EIN LAYOUTALGORITHMUS FÜR UML-KLASSENDIAGRAMME 84 6.4 Der gesamte Algorithmus Im folgenden wird ein Überblick über die einzelnen Schritte des entwickelten Layoutalgorithmus gegeben. Anschließend erfolgt die Ermittlung der Laufzeit des Algorithmus. 6.4.1 Überblick Der folgende Überblick unterscheidet die Phasen Vorverarbeitung, Planarisierung, Orthogonalisierung, Kompaktierung und Nachverarbeitung. Jeder modifizierte Schritt enthält einen Verweis auf den Abschnitt, in dem die Änderungen erläutert wurden. Der entwickelte Layoutalgorithmus besteht aus folgenden Schritten: Vorverarbeitung: • Zerlegung des Eingabegraphen in seine Zusammenhangskomponenten, für die der Algorithmus dann separat durchgeführt wird. Die folgenden Schritte beziehen sich immer auf den durch eine Zusammenhangskomponente gegebenen Graph. • Transformation der Hyperkanten (→ Abschnitt 6.1). • Aufwärtsrichten von ungerichteten Kanten, um eine einheitliche Orientierung der aufwärtsgerichteten Kanten zu gewährleisten (→ Abschnitt 6.2.4). • Entfernen der Selbstschleifen aus dem Graphen. Planarisierung: • Entfernen der Mehrfachkanten. • Erstellen des planaren Subgraphen mit der modifizierten GTHeuristik (→ Abschnitt 6.3.1). • Wiedereinfügen der Mehrfachkanten. • Routen der aufwärtsgerichteten Kanten, die nicht im planaren Subgraphen enthalten sind (→ Abschnitt 6.3.1). • Einfügen der Höhenkanten (→ Abschnitt 6.3.2). • Routen der restlichen Kanten, die noch nicht im planaren Subgraphen sind (→ Abschnitt 6.3.1). 6.4. DER GESAMTE ALGORITHMUS 85 Orthogonalisierung: • Zuweisung der Kantenform für die aufwärtsgerichteten Kanten (→ Abschnitt 6.2.1). • Entfernen unnötiger Knicke (→ Abschnitt 6.2.2). • Aufstellen des Kandinsky-Netzwerks, unter Berücksichtigung der vorgegebenen Winkel und Knicke (→ Abschnitt 6.2.3). • Lösen des Netzwerkflussproblems und Erstellen der quasi-orthogonalen Repräsentation. • Einfügen der Selbstschleifen (→ Abschnitt 6.3.3). Kompaktierung: • Kompaktieren der orthogonalen Repräsentation und Platzierung der Beschriftungen. Nachbearbeitung: • Entfernung der zusätzlich in den Graphen eingefügten Knoten und Kanten. Darunter fallen Kreuzungsknoten, Höhenkanten und Hyperkanten-Hilfsknoten. • Anordnung der einzelnen Zusammenhangskomponenten des Eingabegraphen durch einen entsprechenden Algorithmus. 6.4.2 Laufzeit Wenn man vom Zerlegen des Eingabegraphen in die Zusammenhangskomponenten und von deren Wiederzusammenfügen absieht, ergibt sich für das Layouten eines zusammenhängenden Graphen G = (V, E) mit dem hier vorgestellten Algorithmus folgende Laufzeit: Die Vorverarbeitung wird durch das Berechnen des minimalen Spannbaumes für die einheitliche Ausrichtung der aufwärtsgerichteten Kanten dominiert und benötigt somit O(|E| log |V |). Die Planarisierung besitzt die Laufzeit O |V ||E|2 + |E| · (|V | + c)2 , wobei c die Anzahl der Kantenkreuzungen angibt. Die Laufzeit der Orthogonalisie rung beträgt O (|V | + c)2 log (|V | + c) , die der Kompaktierung O |V | + c . Die Nachverarbeitung benötigt die Laufzeit O |V | + c . Daraus resultiert eine Gesamtlaufzeit von O |V ||E|2 + |E| · (|V | + c)2 . In der Praxis hat sich gezeigt, dass der entwickelte Layoutalgorithmus für Graphen mit bis zu 100 Knoten schnell genug ist, um ein Klassendiagramm ohne größere Verzögerung zu layouten. Dabei wird allerdings von 86 KAPITEL 6. EIN LAYOUTALGORITHMUS FÜR UML-KLASSENDIAGRAMME einem dünnen Graphen ausgegangen (|E| = O(|V |)), was auf die meisten UML-Graphen zutrifft. Damit die Klassendiagramme übersichtlich bleiben, wird normalerweise für jedes Paket ein extra Diagramm erzeugt. Die meisten UML-Klassendiagramme besitzen deshalb weniger als 100 Knoten und lassen sich mit dem entwickelten Layoutalgorithmus zufriedenstellend layouten. Kapitel 7 Implementierung Die Implementierung des Layoutalgorithmus erfolgt in der Programmiersprache Java unter Verwendung der yFiles-Klassenbibliothek. Die yFilesKlassenbibliothek von yWorks1 stellt eine in Java implementierte, effiziente Klassenbibliothek zur Graphenvisualisierung dar, die Datenstrukturen, Algorithmen und Funktionalität für Graphen bereitstellt [33]. Der Layoutalgorithmus wurde in den Jar-Inspector2 integriert. Der JarInspector ist ein Tool zum Visualisieren von UML-Klassendiagrammen. Die Klassendiagramme werden durch die Analyse von Java-Bytecode erstellt, der in Form von class- oder jar-Dateien (Java Archive) vorliegen kann. Der Jar-Inspector dient vor allem der Demonstration von verschiedenen Layoutalgorithmen und besitzt deswegen nur eine eingeschränkte Funktionalität. Er unterscheidet Klassen, Schnittstellen und Pakete, sowie folgende Beziehungen: Klassen- und Schnittstellenvererbung, Schnittstellenimplementierung, Abhängigkeiten zwischen Paketen und Assoziationen, die durch die Attribute der Klassen definiert werden. Ein Diagramm zeigt den Inhalt eines Pakets an. Ein Paket kann wiederum andere Pakete enthalten. Durch Klicken auf eines dieser Pakete kann der Benutzer interaktiv durch die unterschiedlichen Klassendiagramme der Pakethierarchie navigieren. Abb. 7.1 zeigt die graphische Oberfläche des Jar-Inspectors. Im nächsten Abschnitt wird zunächst das Design des Layoutalgorithmus beschrieben. Anschließend werden einige Details für dessen Verwendung im Jar-Inspector erläutert. 7.1 Design des Layoutalgorithmus In diesem Abschnitt werden die wesentlichen Klassen, aus denen der Layoutalgorithmus besteht, kurz beschrieben und deren Zusammenwirken aufgezeigt. Der Übersicht halber werden dabei keine Schnittstellen und Klassen, 1 2 http://www.yworks.com http://www-pr.informatik.uni-tuebingen.de/c/forschung/uml/jarinspector.xml 88 KAPITEL 7. IMPLEMENTIERUNG Abbildung 7.1: Grafische Oberfläche des Jar-Inspectors. die lediglich Datenstrukturen repräsentieren, berücksichtigt. Abb. 7.2 zeigt ein Klassendiagramm der beschriebenen Klassen. Die Klasse ConstrainedKandisky bildet die Rahmenklasse des Layoutalgorithmus. Sie verwendet die Klasse GroupingManager, um die Hyperkantenmodellierung für die Vererbungsgabeln und die einheitliche Ausrichtung der aufwärtsgerichteten Kanten vorzunehmen. Die Ablaufsteuerung des Layoutvorganges wird an die Klasse KandinskyFramework delegiert. Zur Realisierung der drei Phasen des Topology-Shape-Metrics Ansatzes verwendet diese die Klassen MixedCombinatorialEmbedder, UpwardKandinskyLayouter und KanCompactor. Die Klasse SelfLoopTool wird verwendet, um die Selbstschleifen zu entfernen bzw. nach der Orthogonalisierung wieder einzufügen. Existieren mehrere Selbstschleifen an einem Knoten, werden diese alle an derselben Ecke platziert. Die Klasse MixedCombinatorialEmbedder ermittelt eine aufwärtsplanare Einbettung des Eingabegraphen. Die Verwaltung der Mehrfachkanten wird dabei von der Klasse MixedMultipleEdgeTool realisiert. Die Bestimmung des planaren Subgraphen erfolgt mit der GT-Heuristik und wird an die Klasse MixedGT delegiert. Diese verwendet die Klasse MixedVertexOrder, um die Knotenfolge der ersten Phase zu ermitteln. Das Einfügen und Entfernen der Höhenkanten übernimmt die Klasse HeightConstraints. 7.1. DESIGN DES LAYOUTALGORITHMUS 89 ConstrainedKandinsky GroupingManager MixedCombinatorialEmbedder MixedGT HeightConstraints KandinskyFramework KanCompactor MixedMultipleEdgeTool UpwardKandinskyLayouter Shape2ConstraintsTransformer SelfLoopTool ConstrainedLayouter MixedVertexOrder Abbildung 7.2: UML-Klassendiagramm der verwendeten Klassen. Die Orthogonalisierung erfolgt durch die Klasse UpwardKandinskyLayouter. Diese legt die Form der aufwärtsgerichteten Kanten fest und führt die Knickreduzierung durch. Anschließend wird die ermittelte Form durch die Klasse Shape2ConstraintTransformer auf die dazugehörigen Winkel und Knicke transformiert. Das Aufstellen und Lösen des Min-Cost-FlowProblems, sowie das Erzeugen der quasi-orthogonalen Repräsentation wird in der Klasse ConstrainedLayouter implementiert. Die Klasse KanCompactor ist für die Kompaktierung der Zeichnung und die Zuweisung der Koordinaten zuständig. Die Klassen KandinskyFramework, MixedCombinatorialEmbedder, MixedGT und KanCompactor waren bereits implementiert und mussten nur noch entsprechend modifiziert werden. Die Klasse ConstrainedLayouter basiert auf einer bestehenden Klasse, die das ursprüngliche Kandinsky-Netzwerk implementierte. Zusätzlich können jetzt auch Winkel zwischen Kanten sowie Kantenknicke vorgegeben werden. Ein Layoutalgorithmus kann nun die gewünschte Form in die dazugehörigen Winkel und Knicke umwandeln und diese dann der Klasse ConstrainedLayouter vorgeben. Die Klasse UpwardKandinskyLayouter verwendet für diese Transformation die Klasse Shape2ConstraintTransformer. Die Klassen ConstrainedKandisky, GroupingManager, UpwardKandinskyLayouter und Shape2ConstraintTransformer befinden sich im Paket yext.layout.orthogonal.mixed. Die Klassen MixedCombinatorialEmbedder, MixedMultipleEdgeTool, HeightConstraints, MixedGT und MixedVertexOrder werden für die aufwärtsplanare Einbettung benötigt und sind deshalb im Paket yext.layout.orthogonal.upwardplanar unterge- 90 KAPITEL 7. IMPLEMENTIERUNG bracht. Das Paket y.layout.orthogonal.kandinsky enthält Klassen, die vom allgemeinen Kandinsky-Modell verwendet werden. Dazu gehören u.a. die Klassen KandinskyFramework, KanCompactor, SelfLoopTool und ConstrainedLayouter. 7.2 Anwendung des Layoutalgorithmus Nachdem der Jar-Inspector gestartet wurde, kann man durch Drücken der linken Schaltfläche auf der Registerkarte „Project“ (die mit „a“ markierte Schaltfläche aus Abb. 7.3), einen Dateidialog öffnen. Sobald ein Verzeichnis oder eine jar-Datei ausgewählt wurde, anaylsiert der Jar-Inspector den Bytecode und erzeugt das Klassendiagramm der obersten Ebene. Damit das Klassendiagramm mit dem entwickelten Layoutalgorithmus gezeichnet wird, muss das Auswahlfeld in der Werkzeugleiste auf „Orthogonal“ gesetzt werden (das mit „b“ markierte Auswahlfeld). Durch das Drücken der Schaltfläche rechts neben dem Auswahlfeld (die mit „c“ markierte Schaltfläche), wird der Layoutvorgang manuell gestartet. Durch das Klicken auf ein Paket, wird ein neues Klassendiagramm erzeugt, das den Inhalt des Pakets darstellt. Um wieder auf die höhere Ebene zurückzukehren, klickt man einfach auf den Hintergrund. Abbildung 7.3: Bedienung des Jar-Inspectors. 7.2. ANWENDUNG DES LAYOUTALGORITHMUS 91 Für das Layouten von UML-Klassendiagrammen mit dem entwickelten Algorithmus, bietet der Jar-Inspector außerdem folgende Wahlmöglichkeiten: • Eine Auswahl, welche Beziehungsarten dargestellt werden sollen. Die Auswahl findet über den Menüpunkt „Diagram“→ „Diagram Options“ statt (mit „e“ markiert). • Eine Auswahl, ob Methoden und Attribute angezeigt werden sollen. Auch diese Auswahl findet über den Menüpunkt „Diagram“→„Diagram Options“ statt. • Für jede Art von Vererbungsbeziehung kann festgelegt werden, ob die betreffenden Kanten aufwärtsgerichtet gezeichnet werden sollen. Außerdem können die Kanten als Vererbungsgabeln oder gewöhnlich dargestellt werden. Sollen die Kanten als Vererbungsgabeln aber nicht unbedingt aufwärtsgerichtet dargestellt werden, werden sie erst nach der Ausrichtung aufwärtsgerichtet. Dadurch können Vererbungsgabeln entstehen, die nicht ausgerichtet sind (vgl. Abb. 7.4). Zu der Auswahl gelangt man durch Drücken der rechtesten Schaltfläche der Werkzeugleiste (die mit „d“ markierte Schaltfläche). «interface» IIOParamController ImageWriteParam −controller IIOParam ImageReadParam ImageTypeSpecifier −destinationType type ImageIO.CanEncodeImageAndFormatFilter −defaultController ImageTypeSpecifier.Interleaved ImageTypeSpecifier.Banded ImageTypeSpecifier.Indexed ImageTypeSpecifier.Packed ImageTypeSpecifier.Grayscale Abbildung 7.4: Nicht ausgerichtete Vererbungsgabeln. 92 KAPITEL 7. IMPLEMENTIERUNG Kapitel 8 Zusammenfassung und Bewertung In dieser Diplomarbeit wurde ein Layoutalgorithmus für UML-Klassendiagramme vorgestellt, der auf dem Topology-Shape-Metrics Ansatz basiert. Die Anforderungen an den Layoutalgorithmus wurden aus der UML-Notation und den ermittelten Ästhetikkriterien abgeleitet. Der Schwerpunkt dieser Arbeit lag dabei auf dem aufwärtsgerichteten Zeichnen von Kanten sowie der Verwendung von Vererbungsgabeln zur Darstellung der Vererbungshierarchie. Es wurde gezeigt welche Form den aufwärtsgerichteten Kanten dazu zugewiesen werden muss und wie diese durch das Netzwerk umgesetzt werden kann. Dabei wurde auch ein Algorithmus zur Knickreduzierung und zur einheitlichen Ausrichtung der aufwärtsgerichteten Kanten vorgestellt. Der Layoutalgorithmus wurde außerdem durch die Verwendung einer optimierten Einbettung, das Einfügen von Höhenkanten und einer speziellen Behandlung der Selbstschleifen verbessert. Die Implementierung erfolgte in der Programmiersprache Java unter Verwendung der yFiles-Klassenbibliothek. Schließlich wurde gezeigt, wie der Layoutalgorithmus im Jar-Inspector verwendet werden kann. Der entwickelte Layoutalgorithmus ermittelt eine quasi-orthogonale Git tereinbettung des Eingabegraphen in der Laufzeit O |V ||E|2 +|E|·(|V |+c)2 . Er unterscheidet die Kantenmengen E↑ , ETree und EHyp , wobei die Kanten aus EHyp als Vererbungsgabeln und die Kanten aus E↑ aufwärtsgerichtet dargestellt werden. Kanten aus ETree sind Baumkanten, die besonders hervorgehoben werden sollen und deshalb bei der Einbettung und der Formgebung bevorzugt behandelt werden. Die Zuordnung der Kantenmengen eines UML-Graphs zu diesen drei Kantenmengen ist flexibel. Es muss sich lediglich um veträgliche Kantenmengen handeln. Dadurch besteht die Möglichkeit, z.B. nur die Klassenvererbung aufwärtsgerichtet zu zeichnen oder alle Implementierungsbeziehungen durch Vererbungsgabeln darzustellen. Werden keine Kanten auf die Menge der aufwärtsgerichteten Kanten abgebildet, produziert 94 KAPITEL 8. ZUSAMMENFASSUNG UND BEWERTUNG der Algorithmus eine gewöhnliche orthogonale Zeichnung. Der Layoutalgorithmus kann also verschiedenen Ästhetikpräferenzen berücksichtigen. Um den Eingabegraphen einzubetten, berechnet der entwickelte Layoutalgorithmus zuerst einen planaren Subgraphen. Dabei kommt eine modifizierten Version der GT-Heuristik zum Einsatz. Anschließend werden die Restkanten in den Subgraphen geroutet. Die Orthogonalisierung basiert auf dem Kandinsky-Modell. Für die Kompaktierung wurden keine speziellen Anpassungen durchgeführt. Der Algorithmus berücksichtigt die wesentlichen, ermittelten Ästhetikkriterien. Die Kanten der Menge E↑ besitzen eine einheitliche Kantenrichtung und die Vererbungshierarchie kann durch Vererbungsgabeln dargestellt werden. Die Minimierung der Anzahl der Kreuzungen und die Minimierung der Anzahl der Knicke, erfolgt unter Berücksichtigung der zuvor genannten Kriterien. Durch die Kompaktierung wird die Fläche der gegebenen Form möglichst klein gehalten. Falls möglich, werden Geschwisterknoten in Vererbungshierarchien auf derselben Höhe gezeichnet. Der vorgestellte Algorithmus erzeugt keine Überlappungen zwischen Knoten. Um n-fach Beziehungen darzustellen, kann das hier vorgestellte Hyperkantenkonzept entsprechend erweitert werden. Kommentarknoten v mit δ(v) = 1 werden bereits ohne zusätzliche Modifikation nahe am dazugehörigen Knoten platziert. Die Qualität des Layouts hängt von mehreren Faktoren ab. Ein wesentlicher Faktor ist die Anzahl der aufwärtsgerichteten Kanten, da diese zusätzliche Kantenkreuzungen und Kantenknicke verursachen. Je weniger Kantenknicke und Winkel vorgeschrieben werden, desto besser verhält sich der Algorithmus bezüglich dieser Kriterien. Ein weiterer Faktor ist die Dichte des Graphen. Sehr dichte Graphen mit vielen Kanten pro Knoten führen oft zu unübersichtlichen Zeichnungen. Da im verwendeten Kandinsky-Modell maximal eine Kante pro Knotenseite gerade gezeichnet werden kann, enthält die Zeichnung dann schon viele Kandinsky-Knicke. Die Minimierung der Anzahl der Kreuzungen erfolgt in der ersten Phase des Topology-Shape-Metrics Ansatzes. Knicke werden erst in der zweiten Phase bestimmt. Dies führt zu einigen unschönen Zeichnungen, da eine Kante unter Umständen mehrere Knicke erhält, die durch eine zusätzliche Kreuzung hätten verhindert werden können. Wegen der Trennung der beiden Phasen, kann man solche Effekte kaum verhindern. Sie stellen eine Schwäche des Topology-Shape-Metrics Ansatzes dar. Durch eine Art Rerouting nach der Orthogonalisierung könnte man versuchen das Resultat eventuell zu verbessern. Abb. 8.1(a) zeigt eine Schwäche der verwendeten Einbettung. Die markierte Kante muss nicht aufwärtsgerichtet gezeichnet werden und kann deshalb auch an einer anderen Seite des Knotens platziert werden. Dann könnte die Kante ohne Knick gezeichnet werden. Abb. 8.1(b) zeigt eine weitere Schwäche. Würde sich die markierte eingehende Kante rechts von der anderen eingehenden Kante befinden, dann könnte sie mit wenigeren Knicken +core +coreLayouter +coreLayouter 95 gezeichnet werden. Eine Einbettung, die bestimmte Regeln anwendet und die Struktur um die einzufügende Kante berücksichtigt, könnte in beiden Fällen zumindest zu lokalen Verbesserungen führen. «implements» LabelLayoutTranslator «implements» AbstractLayoutStage BendConverter BufferedLayouter ComponentLayouter SelfLoopLayouter SubgraphLayouter ParallelEdgeLayouter «interface» LayoutOrientation +this$0 OrientationLayouter.PortTransformer «implements» OrientationLayouter (a) «interface» ProfitModel «implements» «implements» LabelLayoutDataRefinement CompositeLayoutStage BufferedLayouter LabelRanking +this$0 LabelLayoutDataRefinement.SemiSliderProfitModel (b) Abbildung 8.1: Schwächen der Einbettung. Die erzeugten Zeichnungen können überflüssige Knicke besitzen. Dies liegt daran, dass der Algorithmus, der die Formzuweisung berechnet, zum Zeitpunkt der Zuweisung der Kantenform keine Informationen über die Lage der anderen Knoten berücksichtigt. Der Knickreduzierungsalgorithmus entfernt außerdem nur Knicke, die immer entfernt werden können. Hier liegt also noch Verbesserungspotential. Durch Algorithmen, die auch topologische Eigenschaften der anderen Knoten berücksichtigen, können noch einige Knicke verhindert werden. Es bietet sich auch an, eine Art Knickreduzierung nach der Orthogonalisierung durchzuführen, da dann die Form aller Kanten feststeht. Da maximal eine Kante pro Knotenseite gerade gezeichnet werden kann, führt das Kandinsky-Modell zu mehreren Knicken, auch wenn das Aufgrund der unterschiedlichen Knotengrößen nicht immer erforderlich ist. Eine Schwäche des allgemeinen orthogonalen Netzwerks zeigt Abb. 8.2. Die Zeichnung ist kreuzungs- und knickminimal. Beim Realisieren der Winkel schickt ein Knoten beide Einheiten in dasselbe Face, wodurch ein 270 Grad Winkel entsteht. Das liegt daran, dass beim Berechnen des minimalen 96 KAPITEL 8. ZUSAMMENFASSUNG UND BEWERTUNG Kostenflusses immer möglichst viel Fluss entlang eines billigsten Pfades geschickt wird. Durch ein leichtes Erhöhen der Kosten der zweiten Flusseinheit, könnte man das abändern. 2 3 6 7 1 10 9 5 8 4 Abbildung 8.2: Entstandene Schneckenform. Für die Kompaktierung wurden keine speziellen Anpassungen vorgenommen. Es würde sich jedoch z.B. anbieten, die einheitliche Höhe von Geschwisterknoten in der Kompaktierungsphase zu realisieren. Der entwickelte Algorithmus kann auch zur Darstellung anderer Diagrammarten eingesetzt werden. Durch die flexible Zuordnung der Kanten des zu zeichnenden Graphs auf die Kantenmengen E↑ , ETree und EHyp , können einige Diagrammarten bereits ohne weitere Modifikationen ansprechend gezeichnet werden. Die meisten der erläuterten Konzepte sind allgemein anwendbar. Die hier vorgestellte Behandlung der Selbstschleifen bringt sogar schon für allgemeine Graphen eine Verbesserung. Die Vorgehensweise zur Erzielung der Aufwärtsplanarität von teilgerichteten Graphen im Kandinsky-Modell kann ebenfalls häufig eingesetzt werden. Da außerdem viele Diagrammarten versuchen Hierarchien zu veranschaulichen, kann auch die spezielle Behandlung der Baumkanten oftmals verwendet werden. Für solche Diagrammarten bietet sich dann auch der Einsatz von Höhenkanten an. Auch das vorgestellte Hyperkantenkonzept kann für viele Diagrammarten sinnvoll eingesetzt werden. Die Form, die der Algorithmus den aufwärtsgerichteten Kanten zuweist, kann für andere Diagrammarten entsprechend angepasst werden. Der Algorithmus, der die Formzuweisung berechnet, stellt die spezifischte Änderung dar. Die Kosten für Knicke und Kreuzungen wurden bis jetzt immer für ganze Kantenmengen festgelegt. Wenn man den Algorithmus so modifiziert, dass man jeder Kante eigene Knick- und Kreuzungskosten zuweisen kann, dann bietet sich eine sehr flexible Handhabung für andere Diagrammarten. Das erweiterte Netzwerk, das die Vorgabe von Winkeln und Knicken erlaubt, kann, wie in [3] beschrieben, auch dazu verwendet werden, um aus einer Skizze einer Zeichnung eine orthogonale Zeichnung zu erstellen. Für den Layoutalgorithmus bieten sich außerdem folgende Erweiterungsmöglichkeiten an: 97 • Berücksichtigung von dynamischen Ästhetikkriterien. • Clustern von zusammengehörigen Elementen. 98 KAPITEL 8. ZUSAMMENFASSUNG UND BEWERTUNG Anhang A Beispieldiagramme IOHandler ImageOutputHandler JPGIOHandler LinkMap +references ImageMapOutputHandler TGFIOHandler YGFIOHandler GMLIOHandler GIFIOHandler (a) IOHandler ImageOutputHandler ImageMapOutputHandler TGFIOHandler YGFIOHandler GMLIOHandler +references JPGIOHandler GIFIOHandler LinkMap (b) Abbildung A.1: Klassendiagramm, das ohne einheitliche Höhe der Geschwisterknoten (a) bzw. mit einheitlicher Höhe der Geschwisterknoten (b) gezeichnet wurde. 100 ANHANG A. BEISPIELDIAGRAMME «interface» YCursor «implements» «interface» YList.ListCursorImpl EdgeCursor «interface» NodeCursor «implements» «implements» «implements» «implements» Node.EdgeCursorImpl Node.SemiEdgeCursorImpl EdgeList.EdgeListCursorImpl «interface» GraphObjectCursor NodeList.NodeListCursorImpl «implements» «implements» Node.NodeCursorImpl «implements» GraphObjectList.GraphObjectCursorImpl Node.SemiNodeCursorImpl (a) «interface» YCursor «implements» «interface» YList.ListCursorImpl EdgeCursor «implements» «implements» «implements» «interface» EdgeList.EdgeListCursorImpl Node.SemiEdgeCursorImpl NodeCursor Node.EdgeCursorImpl «implements» «interface» Node.SemiNodeCursorImpl GraphObjectCursor «implements» «implements» Node.NodeCursorImpl «implements» GraphObjectList.GraphObjectCursorImpl NodeList.NodeListCursorImpl (b) Abbildung A.2: Klassendiagramm, das mit einem hierarchischen (a) bzw. mit dem entwickelten Layoutalgorithmus (b) gezeichnet wurde. 101 «interface» «interface» IInformation IUMLInformation edgeinfo 0..1 Edge 0..1 nodeinfo Node «interface» Graph IMetaObject UMLAssociationInfo UMLInheritanceInfo «interface» INodeInformation associationClass UMLNodeInfo * attributs methods associationClass «interface» IEdgeInformation UMLClassMethodInfo 1 UMLClassAttributInfo 1 represents 1 1 1 UMLEdge MetaClassAttribut represents 1 * 1 UMLNode MetaClassMethod 1 represents UMLGraph 1 MetaObject MetaNode represents 1 MetaEdge represents 1 MetaGraph nodes 1 MetaPackage nodes 1 MetaCluster IUMLEdgeInformation (a) «interface» IMetaObject Graph «implements» MetaObject MetaClassAttribut MetaEdge MetaCluster MetaClassMethod MetaPackage UMLGraph MetaNode MetaStereodef «interface» IInformation «interface» «interface» IEdgeInformation INodeInformation «implements» «implements» UMLClassMethodInfo Edge «implements» IUMLEdgeInformation «implements» Node UMLEdge UMLClassAttribugInfo UMLNodeInfo UMLNode «interface» IUMLInformation «implements» «implements» UMLAssociationInfo UMLInheritanceInfo (b) Abbildung A.3: Klassendiagramm, das mit einem in [11] vorgestellten hierarchischen Ansatz (a) bzw. mit dem entwickelten Layoutalgorithmus (b) gezeichnet wurde. MetaGraph MetaStereodef 102 ANHANG A. BEISPIELDIAGRAMME «interface» IIOParamController ImageWriteParam −controller IIOParam ImageReadParam ImageTypeSpecifier −destinationType type ImageIO.CanEncodeImageAndFormatFilter −defaultController ImageTypeSpecifier.Interleaved ImageTypeSpecifier.Banded ImageTypeSpecifier.Indexed ImageTypeSpecifier.Packed ImageTypeSpecifier.Grayscale (a) ImageTypeSpecifier ImageIO.CanEncodeImageAndFormatFilter type −destinationType «interface» IIOParamController IIOParam −controller ImageWriteParam ImageReadParam −defaultController ImageTypeSpecifier.Interleaved ImageTypeSpecifier.Banded ImageTypeSpecifier.Indexed ImageTypeSpecifier.Packed ImageTypeSpecifier.Grayscale (b) Abbildung A.4: Klassendiagramm, das ohne einheitliche Ausrichtung der aufwärtsgerichteten Kanten (a) bzw. mit einheitlicher Ausrichtung der aufwärtsgerichteten Kanten (b) gezeichnet wurde. Die markierte Kante stellt die künstlich gerichtete Kante dar. 103 «implements» −computeKernel −computeKernel GenericPolygon AbstractComputeKernel HomPolygon YPolygon +YKERNEL «interface» Kernel HomComputeKernel +defaultKernel «implements» YKernel «implements» HomKernel SlowDoubleKernel (a) «implements» −computeKernel −computeKernel GenericPolygon +w AbstractComputeKernel +y YPolygon HomPolygon «interface» HomComputeKernel Kernel +defaultKernel «implements» «implements» YKernel +YKERNEL HomKernel SlowDoubleKernel (b) Abbildung A.5: Klassendiagramm, das mit der herkömmlichen (a) bzw. mit der modifizierten (b) Behandlung der Selbstschleifen gezeichnet wurde. 104 ANHANG A. BEISPIELDIAGRAMME Servant «interface» DynamicImplementation ServantManagerOperations «interface» «interface» ServantManager ServantActivatorOperations «interface» ServantLocatorOperations «implements» «implements» «interface» ServantActivatorPOA ServantActivator ServantLocatorPOA «implements» _ServantActivatorStub «interface» ServantLocator «implements» _ServantLocatorStub (a) Servant «interface» DynamicImplementation ServantManagerOperations «interface» «interface» «interface» ServantManager ServantActivatorOperations ServantLocatorOperations «implements» «interface» ServantActivator «implements» ServantActivatorPOA ServantLocatorPOA «implements» _ServantActivatorStub «interface» ServantLocator «implements» _ServantLocatorStub (b) Abbildung A.6: Klassendiagramm, das ohne die spezielle Behandlung der Baumkanten (a) bzw. mit der speziellen Behandlung der Baumkanten (b) gezeichnet wurde. Literaturverzeichnis [1] Balzert, H.: Lehrbuch der Objektmodellierung. Analyse und Entwurf . Spektrum Akademischer Verlag, Juli 1999. [2] Binucci, C., W. Didimo, G. Liotta und M. Nonato: Labeling Heuristics for Orthogonal Drawings. In: Proceedings of the 9th International Symposium on Graph Drawing (GD’2001), Bd. 2275 d. Reihe LNCS , S. 139–153, 2001. [3] Brandes, U., M. Eiglsperger, M. Kaufmann und D. Wagner: Sketch-Driven Orthogonal Graph Drawing. In: Proceedings of the 10th International Symposium on Graph Drawing (GD’2002), Bd. 2528, S. 1–12. Springer, 2002. [4] Bronštein, I. N., K. A. Semendâev, G. Musiol und H. Mühlig: Taschenbuch der Mathematik . Verlag Harri Deutsch, Frankfurt am Main, Fourth Aufl., 1999. [5] Cimikowski, R.: An analysis of heuristics for the maximum planar subgraph problem. In: Proceedings of the 6th ACM-SIAM Symposium of Discrete Algorithms, S. 322–331, 1995. [6] Coleman, M. K. und D. S. Parker: Aesthetics-based Graph Layout for Human Consumption. Software – Practice and Experience, 26(12):1415–1438, 1996. [7] Corman, T. H., C. E. Leiserson und R. L. Rivest: Introduction to Algorithms. MIT Press/McGraw-Hill, 1990. [8] Di Battista, G., W. Didimo, M. Patrignani und M. Pizzonia: Orthogonal and Quasi-upward Drawings with Vertices of Prescribed Size. In: Kratochvil, J. (Hrsg.): Proceedings of the 7th International Symposium on Graph Drawing (GD’99), Bd. 1731 d. Reihe LNCS , S. 297–310. Springer, 1999. [9] Di Battista, G., P. Eades, R. Tamassia und I. G. Tollis: Graph Drawing: Algorithms for the Visualization of Graphs. Prentice Hall, 1999. 106 LITERATURVERZEICHNIS [10] Eades, P., W. Lai, K. Misue und K. Sugiyama: Preserving the Mental Map of a Diagram. In: Proceedings of Compugraphics ’91 , S. 24–33, 1991. [11] Eichelberger, H.: Automatisches Zeichnen von UML Klassendiagrammen mit dem Sugiyama-Algorithmus in Tagungsband des GIWorkshops Softwarevisualisierung 2000 . Techn. Ber. A/01/2000, Universität des Saarlandes, 2000. [12] Eichelberger, H.: Aesthetics of Class Diagrams. In: Proc. of the First IEEE International Workshop on Visualizing Software for Understanding and Analysis, Vissoft 2002 , S. 23–31, 2002. [13] Eiglsperger, M., S. Fekete und G. Klau: Orthogonal Graph Drawing. In: Kaufmann, M. und D. Wagner (Hrsg.): Drawing Graphs: Methods and Models, LNCS Tutorial, S. 121–171. Springer, 2001. [14] Eiglsperger, M. und M. Kaufmann: An Approach for Mixed Upward Planarization. In: Proceedings of the 7th International Workshop on Algorithms and Datastructures (WADS 2001), S. 352–364. Springer, 2001. [15] Eiglsperger, M. und M. Kaufmann: Fast Compaction for Orthogonal Drawings with Vertices of Prescribed Size. In: Graph Drawing, S. 124–138, 2001. [16] Eiglsperger, M., M. Kaufmann und M. Siebenhaller: A Topology-Shape-Metrics Approach for the Automatic Layout of UML Class Diagram. ACM Symp. on Software Visualization’2003, to appear. [17] Eppinger, F.: Kombinatorische Einbettung teilgerichteter Graphen. Diplomarbeit, Wilhelm-Schickard-Institut für Informatik, Arbeitsbereich für Paralleles Rechnen, Universität Tübingen, April 2001. [18] Fößmeier, U. und M. Kaufmann: Drawing high degree graphs with low bend numbers. In: Brandenburg, F. (Hrsg.): Graph Drawing (Proc. GD ’95), Bd. 1027 d. Reihe LNCS , S. 254–266. Springer, 1996. [19] Fowler, M. und K. Scott: UML Distilled: Applying the Standard Object Modeling Language. Addison-Wesley, 1997. [20] Gibbons, A.: Algorithmic Graph Theory. Cambridge University Press, 1985. [21] Goldschmidt, O. und A. Takvorian: An Efficient Graph Planarization Two-Phase Heuristic. Networks, 24:69–73, 1994. LITERATURVERZEICHNIS 107 [22] Klau, G. W. und P. Mutzel: Combining Graph Labeling and Compaction. In: Kratochvil, J. (Hrsg.): Proceedings of the 7th International Symposium on Graph Drawing (GD’99), Nr. 1731 in LNCS , S. 27–37. Springer, 1999. [23] Klein, P. N., S. Rao, M. Rauch und S. Subramanian: Faster shortest-path algorithms for planar graphs. In: Proceedings ACM Symp. on Theory of Computing, 1994. [24] OMG: Unified Modeling Language. Specification v1.4, Object Management Group, 2001. http://www.omg.org/uml/. [25] Purchase, H. C.: Which Aesthetic has the Greatest Effect on Human Understanding? . In: Proceedings of the 5th International Symposium on Graph Drawing (GD’97), Bd. 1353 d. Reihe LNCS , S. 248–261, 1997. [26] Purchase, H. C., J.-A. Allder und D. Carrington: Graph Layout Aesthetics in UML Diagrams: User Preferences. Journal of Graph Algorithms and Applications, 2002. [27] Purchase, H. C., L. Colpoys, M. McGill, D. Carrington und C. Britton: UML Class Diagram Syntax: An Empirical Study of Comprehension. In: Proceedings of the Australian Symposium on Information Visualisation, Sydney, Australia, 2001. Australian Computer Society Inc. [28] Purchase, H. C., M. McGill, L. Colpoys und D. Carrington: Graph Drawing Aesthetics and the Comprehension of UML Class Diagrams: An Empirical Study. In: Proceedings of the Australian Symposium on Information Visualisation, Sydney, Australia, 2001. Australian Computer Society Inc. [29] Resende, M. und C. Ribeiro: A GRASP for graph planarization. Networks, 29:173–189, 1997. [30] Tamassia, R.: On Embedding a Graph in the Grid with the Minimum Number of Bends. SIAM Journal on Computing, 16(3):421–444, 1987. [31] Tamassia, R.: Graph Drawing. In: Goodman, J. E. und J. O’Rourke (Hrsg.): CRC Handbook of Discrete and Computational Geometry. CRC Press, 1997. [32] Tamassia, R., G. D. Battista und C. Batini: Automatic graph drawing and readability of diagrams. IEEE Transactions on Systems, Man and Cybernetics, 18(1):61–79, 1988. 108 LITERATURVERZEICHNIS [33] Wiese, R., M. Eiglsperger und M. Kaufmann: yFiles: Visualization and Automatic Layout of Graphs. In: Proceedings of the 9th International Symposium on Graph Drawing (GD’01), LNCS, S. 453–454. Springer, 2001.