Software-Entwicklung für das OGDF - Die Struktur des Open Graph Drawing Framework - Carsten Gutwenger 31.10.2005 Universität Dortmund PG 478 Überblick 1. Historie 2. OGDF und GDE 3. Basisdatentypen 4. Graphen 5. Graph-Attribute 6. Algorithmen als Module 7. Layout-Verfahren Carsten Gutwenger: Software-Entwicklung für das OGDF 2 Historie 1995 DFG-Projekt „Design, Analyse, Implementierung und experimentelle Anwendung von Algorithmen zum Zeichnen von Graphen“ Saarbrücken, Köln, Halle, Passau 1997 AGD Algorithms for Graph Drawing 1999 OGDL & GDE Neuentwicklung, kommerzielle Vermarktung caesar, oreas GmbH 2005 OGDF Open Source, GPL Universität Dortmund, oreas GmbH Carsten Gutwenger: Software-Entwicklung für das OGDF 3 Historie Weitere Informationen: www.ads.tuwien.ac.at/AGD/ www.oreas.com www.caesar.de/graphdrawing0.0.html Carsten Gutwenger: Software-Entwicklung für das OGDF 4 OGDF & GDE Struktureller Aufbau: GDE Algorithmen und Datenstrukturen OGDF LP-Solver Qt GUI und graphische Darstellung Coin, Cplex, Abacus C/C++ Carsten Gutwenger: Software-Entwicklung für das OGDF 5 Basisdatentypen Grundlegende Funktionalität • globale Konstanten und Funktionen → basic.h Zufallszahlen File- und Directory-Handling Comparer<E>, BucketFunc<E> • Exception-Handling → exceptions.h • Memory-Management → memory.h • Zeichenketten String • Tupel → tuples.h Tuple2<E1,E2>, Tuple3<E1,E2,E3>, … Carsten Gutwenger: Software-Entwicklung für das OGDF 6 Basisdatentypen Debug vs. Release • zwei Arten von Builds Debug (→ OGDF_DEBUG definiert) Release (→ OGDF_DEBUG nicht definiert) • zusätzlicher Testcode in Debug-Build #ifdef OGDF_DEBUG … #endif kein Overhead in Release-Build! • Assertions → OGDF_ASSERT(…) Carsten Gutwenger: Software-Entwicklung für das OGDF 7 Basisdatentypen Container-Typen: • dynamische Felder Array<E>, Array2<E> • Stacks & Queues StackPure<E>, Stack<E>, QueuePure<E>, Queue<E> BoundedStack<E>, BoundedQueue<E> • einfach verkette Listen SListPure<E>, SList<E> • doppelt verkette Listen ListPure<E>, List<E> Carsten Gutwenger: Software-Entwicklung für das OGDF 8 Basisdatentypen #include <ogdf/List.h> using namespace ogdf; void main() { List<int> L; for(int i = 1; i <= 10; ++i) L.pushBack(i); int sum = 0; ListConstIterator<int> it; for(it = L.begin(); it.valid(); ++it) sum += *it; } Carsten Gutwenger: Software-Entwicklung für das OGDF 9 Basisdatentypen #include <ogdf/Array.h> #include <ogdf/SList.h> using namespace ogdf; void main() { Array<SListPure<double> > A(1,10); for(int i = 1; i <= 1000; ++i) { int index = randomNumber(1,10); double value = rand()*100.0; A[index].pushFront(value); } } Carsten Gutwenger: Software-Entwicklung für das OGDF 10 Basisdatentypen Weitere Container-Typen: • Skiplisten Skiplist<E> • Hash-Tabellen und Hashing-Felder Hashing<K,I>, HashingArray<I,E> Carsten Gutwenger: Software-Entwicklung für das OGDF 11 Graphen Multigraphen: • G=(V,E) V : Menge der Knoten E⊆V×V : (Multi-)Menge der Kanten • Adjazenzlistendarstellung • Mehrere Klassen notwendig Graph, Knoten, Kanten, … Carsten Gutwenger: Software-Entwicklung für das OGDF 12 Graphen GraphElement GraphElement *m_next GraphElement *m_prev NodeElement EdgeElement Graph GraphList<NodeElement> m_nodes GraphList<EdgeElement> m_edges int m_nodes int m_edges AdjElement typedef NodeElement *node; typedef EdgeElement *edge; typedef AdjElement *adjEntry; Carsten Gutwenger: Software-Entwicklung für das OGDF 13 Graphen v e w NodeElement GraphList<AdjElement> m_adjEdges int m_indeg int m_outdeg int m_id * AdjElement adjEntry m_twin edge m_edge node m_node int m_id 2 2 EdgeElement node m_src, m_tgt adjEntry m_adjSrc, m_adjTgt int m_id Carsten Gutwenger: Software-Entwicklung für das OGDF 14 Graphen Funktionalität der Graph-Klasse • Zugriffsfunktionen Anzahl Knoten und Kanten Knoten- und Kantenlisten, adjazente Kanten • Update-Funktionen Erzeugen / Löschen von Knoten und Kanten Splitten von Kanten Verschieben von Quell- / Zielknoten, Umdrehen von Kanten • Ein- und Ausgabe • Management von Node-, Edge-, AdjEntry-Feldern Carsten Gutwenger: Software-Entwicklung für das OGDF 15 Graphen #include <ogdf/Graph.h> using namespace ogdf; void main() { Graph G; node v1 = G.newNode(), v = v1; for(int i = 1; i <= 9; ++i, v = w) { node w = G.newNode(); G.newEdge(v,w); } G.newEdge(v1,v); } Carsten Gutwenger: Software-Entwicklung für das OGDF 16 Graphen #include <ogdf/graph_generators.h> using namespace ogdf; void main() { Graph G; randomGraph(G,10,20); for(node v = G.firstNode(); v; v = v->succ()) { cout << v << ": "; for(adjEntry adj = v->firstAdj(); adj; adj = adj->succ()) cout << " " << adj->theEdge(); cout << endl; } } Carsten Gutwenger: Software-Entwicklung für das OGDF 17 Graphen … node v; forall_nodes(v,G) { cout << v << ": "; adjEntry adj; forall_adj(adj,v) cout << " " << adj->theEdge(); cout << endl; } … Carsten Gutwenger: Software-Entwicklung für das OGDF 18 Graphen Forall-Makros (siehe Graph.h) • Alle Knoten des Graphen forall_nodes(v,G) forall_rev_nodes(v,G) • Alle Kanten des Graphen forall_edges(e,G) forall_rev_edges(e,G) • Alle Adjazenzeinträge eines Knotens forall_adj(adj,v) forall_rev_adj(adj,v) • Alle adjazenten Kanten eines Knotens forall_adj_edges(e,v) Carsten Gutwenger: Software-Entwicklung für das OGDF 19 Graphen Mit Graph-Ojekten indizierte Felder • NodeArray<E> • EdgeArray<E> • AdjEntryArray<E> #include <ogdf/NodeArray.h> #include <ogdf/graph_generators.h> using namespace ogdf; void main() { Graph G; NodeArray<int> deg(G); randomGraph(G,100,175); node v; forall_nodes(v,G) deg[v] = v->degree(); } Carsten Gutwenger: Software-Entwicklung für das OGDF 20 Graphen Algorithmen für Graphen • Basisalgorithmen → simple_graph_alg.h 1- / 2-Zusammenhang Self-Loops, Multi-Kanten Kreisfreiheit, Baum / Wald • Graph-Generatoren → graph_generators.h • Min-Cost-Flow MinCostFlowReinelt • SPQR-Bäume SPQRTree, PlanarSPQRTree, Skeleton, PertinentGraph Carsten Gutwenger: Software-Entwicklung für das OGDF 21 Graphen Cluster-Graphen: GraphElement ClusterElement cluster m_parent List<cluster> m_children int m_id … ClusterGraph GraphList<ClusterElement> int const Graph * NodeArray<cluster> m_clusters m_nClusters m_pGraph m_nodeMap typedef ClusterElement *cluster; Carsten Gutwenger: Software-Entwicklung für das OGDF 22 Graphen Makros für Cluster-Graphen • Alle Cluster des ClusterGraphen forall_clusters(c,C) forall_postOrderClusters(c,C) Mit Clustern indizierte Felder • ClusterArray<E> Carsten Gutwenger: Software-Entwicklung für das OGDF 23 Graphen Eingebettete Graphen f Carsten Gutwenger: Software-Entwicklung für das OGDF 24 Graphen Eingebettete Graphen GraphElement FaceElement adjEntry m_adjFirst int m_size int m_id ConstCombinatorialEmbedding GraphList<FaceElement> m_faces int m_nFaces const Graph * m_cpGraph AdjEntryArray<face> m_rightFace face m_externalFace CombinatorialEmbedding Graph * m_pGraph typedef FaceElement *face; Carsten Gutwenger: Software-Entwicklung für das OGDF 25 Graphen Makros für eingebettete Graphen • Alle Flächen des Graphen forall_faces(f,E) forall_rev_faces(f,E) • Alle Adjazenzeinträge einer Fläche forall_face_adj(adj,f) Mit Flächen indizierte Felder • FaceArray<E> Carsten Gutwenger: Software-Entwicklung für das OGDF 26 Graphen Planaritätstest und planare Einbettung • Graphen PlanarModule • Cluster-Graphen #include <ogdf/PlanarModule.h> using namespace ogdf; void main() { Graph G; … PlanarModule pm; pm.planarityTest(G); pm.planarEmbed(G); } CconnectClusterPlanar CconnectClusterPlanarEmbed Carsten Gutwenger: Software-Entwicklung für das OGDF 27 Graphen Graph-Kopien • Erzeugen Kopie des Graphen • Verwalten Abbildung Knoten ↔ Originalknoten Kante ↔ Originalkante → GraphCopySimple Pfad ↔ Originalkante → GraphCopy (Splitten von Kanten!) • Modifikation der Kopie möglich! Vgl. GraphReduction Carsten Gutwenger: Software-Entwicklung für das OGDF 28 Graphen Planarisierte Graphen Carsten Gutwenger: Software-Entwicklung für das OGDF 29 Graphen Graph GraphCopy const Graph * m_pGraph Originalgraph NodeArray<node> EdgeArray<edge> m_vOrig m_eOrig Kopie → Original NodeArray<node> m_vCopy EdgeArray<List<edge> > m_eCopy Original → Kopie PlanRep int int m_numCC m_currentCC Zusammenhangskomponenten Array<List<node> > m_nodesInCC Carsten Gutwenger: Software-Entwicklung für das OGDF 30 Graphen #include <ogdf/graph_generators.h> #include <ogdf/PlanRep.h> using namespace ogdf; void main() { Graph G; randomGraph(G,250,250); PlanRep P(G); for(int i = 0; i < P.numberOfCCs(); ++i) { P.initCC(i); cout << P.numberOfEdges() << endl; } } Carsten Gutwenger: Software-Entwicklung für das OGDF 31 Graph-Attribute Graph-Attribute • Speichern zusätzliche Informationen wie Größe von Knoten Koordinaten von Knoten, Knicke von Kanten Größe und Position von Clustern Knoten- und Kantenlabel Farben und Linienstile • Alle Attribute sind optional → m_attributes • Ein- / Ausgabe (GML-Format) Carsten Gutwenger: Software-Entwicklung für das OGDF 32 Graph-Attribute 2D-Geometrie → Geometric.h • Punkte → DPoint, IPoint • Linien und Linienzüge → DPolyline, DLine, DSegment • Rechtecke und Polygone → DRect, DPolygon • Skalierung → DScaler Carsten Gutwenger: Software-Entwicklung für das OGDF 33 Graph-Attribute GraphAttributes const Graph * m_pGraph long m_attributes NodeArray<double> NodeArray<double> m_x, m_y m_width, m_height EdgeArray<DPolyline> m_bends … ClusterGraphAttributes const ClusterGraph * m_pClusterGraph HashingArray<int,ClusterInfo> m_clusterInfo Carsten Gutwenger: Software-Entwicklung für das OGDF 34 Graph-Attribute Graph G; GraphAttributes A(G, GraphAttributes::nodeGraphics | GraphAttributes::edgeGraphics | GraphAttributes:: nodeColor); randomGraph(G,10,18); node v; forall_nodes(v,G) { A.width(v) = A.height(v) = 20.0; A.colorNode(v) = "#0000ff"; // blau A.colorLine(v) = "#000000"; // schwarz A.x(v) = randomDouble(0.0,200.0); A.y(v) = randomDouble(0.0,200.0); } A.writeGML("graph.gml"); Carsten Gutwenger: Software-Entwicklung für das OGDF 35 Graph-Attribute Spezielle Attribut-Klassen • Hilfsklassen für Sugiyama-Layout GraphCopyAttributes ClusterGraphCopyAttributes • Verwalten Zeiger auf Graph-Kopie (GraphCopy bzw. ExtendedNestingGraph) Attribute des Originalgraphen Layout-Informationen der Kopie • Abbildung des Layouts Kopie → Original Carsten Gutwenger: Software-Entwicklung für das OGDF 36 Algorithmen als Module Algorithmen als Klassen • Vorteil: Kapselung von Datenstrukturen und Funktionen Speicherung von Optionen Module • Viele Algorithmen für gleiche Funktionalität • Abstrakte Basisklasse definiert Schnittstelle (= Modultyp) • Konkrete Implementierungen leiten davon ab Carsten Gutwenger: Software-Entwicklung für das OGDF 37 Algorithmen als Module Modul-Optionen • „Rahmenalgorithmus“ verwaltet benutzte Algorithmen als Modul-Optionen → ModuleOption<M> Zugriff nur über Modul-Schnittstelle Default-Implementierung • Austausch der Implementierung während der Laufzeit möglich! • Neue Implementierungen müssen lediglich die Schnittstelle implementieren Carsten Gutwenger: Software-Entwicklung für das OGDF 38 Algorithmen als Module Beispiel: M ≡ LayoutModule ModuleOption<M> M* m_pModule bool valid() const void M& set(M *pM) get() LayoutModule virtual void call (GraphAttributes &A) = 0 SpringEmbedderFR GEMLayout DavidsonHarelLayout Carsten Gutwenger: Software-Entwicklung für das OGDF 39 Layout-Verfahren Überblick • Hierarchisches Layout SugiyamaLayout [Sugiyama, Tagawa, Toda ´81] • Planarisierungsmethode UMLPlanarizationLayout [Eiglsperger, Gutwenger et al. ´04] ClusterPlanarizationLayout [Di Battista, Didimo, Marcandalli ´02] • Kräftebasierte Verfahren SpringEmbedderFR [Fruchterman, Reingold ´91] GEMLayout [Frick, Ludwig, Mehldau ´95] DavidsonHarelLayout [Davidson, Harel ´96] Carsten Gutwenger: Software-Entwicklung für das OGDF 40 Layout-Verfahren Überblick (Forts.) • Zirkuläres Layout CircularLayout [Dogrusöz, B. Madden, P. Madden ´97] • Planare straight-line Verfahren PlanarStraightLayout [Gutwenger, Mutzel ´97] PlanarDrawLayout [Gutwenger, Mutzel ´97] • Baumzeichenverfahren TreeLayout [Buchheim, Jünger, Leipert ´02] RadialTreeLayout Carsten Gutwenger: Software-Entwicklung für das OGDF 41 Layout-Verfahren RankingModule SugiyamaLayout m_ranking m_crossMin m_layout m_clusterLayout TwoLayerCrossMin HierarchyLayoutModule FastHierarchyLayout OptimalHierarchyLayout HierarchyClusterLayoutModule OptimalHierarchyClusterLayout Carsten Gutwenger: Software-Entwicklung für das OGDF 42 Layout-Verfahren RankingModule LongestPathRanking m_subgraph OptimalRanking AcyclicSubgraphModule DfsAcyclicSubgraph m_subgraph GreedyCycleRemoval TwoLayerCrossMin BarycenterHeuristic MedianHeuristic Carsten Gutwenger: Software-Entwicklung für das OGDF 43 Layout-Verfahren … SugiyamaLayout sugi; OptimalHierarchyLayout *ohl = new OptimalHierarchyLayout; ohl->nodeDistance(10.0); ohl->layerDistance(10.0); sugi.setLayout(ohl); sugi.call(A); // A is of type GraphAttributes … Carsten Gutwenger: Software-Entwicklung für das OGDF 44 Layout-Verfahren UMLPlanarizationLayout m_subgraph m_inserter m_planarLayouter m_packer PlanarSubgraphModule FastPlanarSubgraph MaximalPlanarSubgraphSimple CCLayoutPackModule EdgeInsertionModule TileToRowsCCPacker FixedEmbeddingInserter UMLPlanarLayoutModule VariableEmbeddingInserter UMLOrthoLayout Carsten Gutwenger: Software-Entwicklung für das OGDF 45 Layout-Verfahren Orthogonales Zeichnen • Orthogonale Repräsentation → OrthoRep • Orthogonalisierung → OrthoFormerGENERIC • Kompaktierung Längste Wege: LongestPathCompaction Flußbasiert: FlowCompaction Carsten Gutwenger: Software-Entwicklung für das OGDF 46 Referenzen Hierarchisches Layout [Sugiyama, Tagawa, Toda ´81] Methods for Visual Understanding of Hierarchical Systems, IEEE Transactions on Systems, Man, and Cybernetics, Vol. 11(4), pp. 109-125, 1981 [Gansner, Koutsofios, North, Vo ´93] A Technique for Drawing Directed Graphs , IEEE Transactions on Software Engineering, pp. 214-230, Vol. 19(3), 1993 [Buchheim, Jünger, Leipert ´01] A Fast Layout Algorithm for k-Level Graphs, LNCS 1984, pp. 229-240, Springer, 2001 [Sander ´96] Layout of Compound Directed Graphs, Technical Report A/03/96, Universität des Saarlandes, 1996 Carsten Gutwenger: Software-Entwicklung für das OGDF 47 Referenzen [Schreiber ´01] Kapitel 6 aus: Visualisierung biochemischer Reaktionsnetze, Dissertation, Universität Passau, 2001 [Forster ´02] Applying Crossing Reduction Strategies to Layered Compound Graphs, LNCS 2528, pp. 276-284, Springer, 2002 [Di Battista, Eades, Tamassia, Tollis ´99] Kapitel 9.4 „Cycle Removal“ in: Graph Drawing — Algorithms for the Visualization of Graphs, Prentice-Hall, 1999 Carsten Gutwenger: Software-Entwicklung für das OGDF 48 Referenzen Planarisierungsmethode [Eiglsperger, Gutwenger et al. ´04] Eiglsperger, Gutwenger, Kaufmann, Kupke, Jünger, Klein, Leipert, Siebenhaller Automatic Layout of UML Class Diagrams in Orthogonal Style, Information Visualization 3(3) , 189-208, 2004 [Di Battista, Didimo, Marcandalli ´02] Planarization of Clustered Graphs, LNCS 2265, pp. 60-74, Springer, 2002 [Jünger, Leipert, Mutzel ´98] A Note on Computing a Maximal Planar Subgraph Using PQ-Trees, IEEE Transactions on Computer-Aided Design of Integrated Circuits and Systems, Vol. 17(7), pp. 609-612, 1998 [Gutwenger, Mutzel, Weiskircher ´05] Inserting an Edge Into a Planar Graph, Algorithmica 41(4), pp. 289-308, 2005 Carsten Gutwenger: Software-Entwicklung für das OGDF 49 Referenzen Orthogonales Zeichnen [Tamassia ´87] On Embedding a Graph in the Grid With the Minimum Number of Bends, SIAM J. Comput., 16(3), pp. 421-444, 1987 [Klau, Mutzel ´98] Quasi-orthogonal drawing of planar graphs , Technical Report MPI-I-98-1-013, Max-Planck-Institut für Informatik, Saarbrücken, 1998 [Klau, Mutzel ´99] Optimal Compaction of Orthogonal Grid Drawings, LNCS 1610, pp. 394-319, Springer, 1999 Carsten Gutwenger: Software-Entwicklung für das OGDF 50 Referenzen Kräftebasierte Verfahren [Davidson, Harel ´96] Drawing Graphs Nicely Using Simulated Annealing, ACM Transactions on Graphics, Vol. 15, pp. 301-331, 1996 [Fruchterman, Reingold ´91] Graph Drawing by Force-directed Placement, Software — Practice and Experience, Vol. 21(11), pp. 1129-1164, 1991 [Frick, Ludwig, Mehldau ´95] A Fast Adaptive Layout Algorithm for Undirected Graphs, LNCS 894, pp. 388-403, Springer, 1995 Carsten Gutwenger: Software-Entwicklung für das OGDF 51 Referenzen Sonstiges [Dogrusöz, B. Madden, P. Madden ´97] Circular Layout in the Graph Layout Toolkit, LNCS 1190, pp. 92-100, Springer, 1997 [Gutwenger, Mutzel ´97] Grid Embedding of Biconnected Planar Graphs, 1997 [Buchheim, Jünger, Leipert ´02] Improving Walker's Algorithm to Run in Linear Time, LNCS 2528, pp. 344-353, Springer, 2002 [Dogrusöz´02] Two-DimensionalPacking Algorithms for Layout of Disconnected Graphs, Information Sciences, Vol. 143, pp. 147-158, 2002 Carsten Gutwenger: Software-Entwicklung für das OGDF 52