Open
Graph Drawing
Framework

 v.2012.05
 

ClusterGraph.h
Go to the documentation of this file.
00001 /*
00002  * $Revision: 2299 $
00003  * 
00004  * last checkin:
00005  *   $Author: gutwenger $ 
00006  *   $Date: 2012-05-07 15:57:08 +0200 (Mon, 07 May 2012) $ 
00007  ***************************************************************/
00008  
00043 #ifdef _MSC_VER
00044 #pragma once
00045 #endif
00046 
00047 
00048 #ifndef OGDF_CLUSTER_GRAPH_H
00049 #define OGDF_CLUSTER_GRAPH_H
00050 
00051 #include <ogdf/basic/NodeArray.h>
00052 #include <ogdf/basic/Stack.h>
00053 #include <ogdf/basic/GraphObserver.h>
00054 
00055 
00056 namespace ogdf {
00057 
00058 class OGDF_EXPORT ClusterGraph;
00059 class OGDF_EXPORT ClusterGraphObserver;
00060 
00062 
00065 class OGDF_EXPORT ClusterElement : private GraphElement {
00066 
00067     friend class OGDF_EXPORT ClusterGraph;
00068     friend class GraphList<ClusterElement>;
00069 
00070     int                     m_id;         
00071     int                     m_depth;      
00072     List<node>              m_entries;    
00073     List<ClusterElement*>   m_children;   
00074     ClusterElement          *m_parent;    
00075     ClusterElement          *m_pPrev;     
00076     ClusterElement          *m_pNext;     
00077     ListIterator<ClusterElement*> m_it;   
00078 
00079     List<adjEntry>          m_adjEntries; 
00080                                           // Don't use a GraphList ! 
00081                                           // This messes with the adjacency 
00082                                           // list of the underlying graph
00083 
00084     #ifdef OGDF_DEBUG
00085     // we store the graph containing this cluster for debugging purposes
00086     const ClusterGraph *m_pClusterGraph;
00087     #endif
00088 
00089     
00090     void init(List<node> &nodes) {
00091         while (!nodes.empty())
00092             m_entries.pushBack(nodes.popFrontRet());
00093     }
00094 
00095     List<ClusterElement*> &getChildren(){
00096         return m_children;
00097     }
00098 
00099     List<node> &getNodes(){
00100         return m_entries;
00101     }
00102     
00104 
00107     void getClusterInducedNodes(List<node> &clusterNodes);
00108     void getClusterInducedNodes(NodeArray<bool> &clusterNode, int& num);
00109 
00110 
00111 public:
00112 
00114     #ifdef OGDF_DEBUG
00115     ClusterElement(const ClusterGraph *pClusterGraph,int id):
00116         m_id(id),m_depth(0),m_parent(0),m_pPrev(0),m_pNext(0),m_it(0),      
00117         m_pClusterGraph(pClusterGraph) {};
00118     #else
00119     ClusterElement(int id):
00120         m_id(id), m_depth(0),m_parent(0),m_pPrev(0),m_pNext(0),m_it(0) {};
00121     #endif
00122 
00123 
00124     #ifdef OGDF_DEBUG
00125     const ClusterGraph *graphOf() const { return m_pClusterGraph; }
00126     #endif
00127 
00128     
00130     int index() const { return m_id; }
00132     int depth() const { return m_depth; }
00133     int& depth()      { return m_depth; }
00135     ClusterElement* succ() const { return (ClusterElement*)m_next; }
00137     ClusterElement* pred() const { return (ClusterElement*)m_prev; }
00138 
00140     ClusterElement* pSucc() const { return m_pNext; }
00142     ClusterElement* pPred() const { return m_pPrev; }
00143 
00144     // Iteration over tree structures.
00145 
00147     ListConstIterator<ClusterElement*> cBegin() const{ return m_children.begin();}
00149     ListConstIterator<ClusterElement*> crBegin() const{ return m_children.rbegin();}
00151     int cCount(){ return m_children.size();}
00153     ListIterator<node> nBegin(){ return m_entries.begin();}
00155     ListConstIterator<node> nBegin() const{ return m_entries.begin();}
00157     int nCount(){ return m_entries.size();}
00158 
00160     ClusterElement* parent(){return m_parent;}
00161 
00162 
00164     ListConstIterator<adjEntry> firstAdj() const { return m_adjEntries.begin();  }
00166     ListIterator<adjEntry> firstAdj() { return m_adjEntries.begin();  }
00168     ListConstIterator<adjEntry> lastAdj () const { return m_adjEntries.rbegin(); }
00170     ListIterator<adjEntry> lastAdj () { return m_adjEntries.rbegin(); }
00171 
00173 
00176     void getClusterNodes(List<node> &clusterNodes);
00183     int getClusterNodes(NodeArray<bool> &clusterNode);
00184 
00185     OGDF_NEW_DELETE
00186 
00187 };// class ClusterElement
00188 
00189 
00190 
00191 
00192 typedef ClusterElement *cluster; 
00193 
00194 
00195 #define forall_cluster_adj(adj,c)\
00196 for(ogdf::ListIterator<adjEntry> ogdf_loop_var=(c)->firstAdj();\
00197     ogdf::test_forall_adj_entries_of_cluster(ogdf_loop_var,(adj));\
00198     ogdf_loop_var=ogdf_loop_var.succ())
00199 
00200 #define forall_cluster_rev_adj(adj,c)\
00201 for(ogdf::ListIterator<adjEntry> ogdf_loop_var=(c)->lastAdj();\
00202     ogdf::test_forall_adj_entries_of_cluster(ogdf_loop_var,(adj));\
00203     ogdf_loop_var=ogdf_loop_var.pred())
00204 
00205 #define forall_cluster_adj_edges(e,c)\
00206 for(ogdf::ListIterator<adjEntry> ogdf_loop_var=(c)->firstAdj();\
00207     ogdf::test_forall_adj_edges_of_cluster(ogdf_loop_var,(e));\
00208     ogdf_loop_var=ogdf_loop_var.succ())
00209 
00210 
00211 
00212 inline bool test_forall_adj_entries_of_cluster(ListIterator<adjEntry> &it, adjEntry &adj)
00213 {
00214     if (it.valid()) { adj = (*it);return true; }
00215     else return false;
00216 }
00217 
00218 inline bool test_forall_adj_edges_of_cluster(ListIterator<adjEntry> &it, edge &e)
00219 {
00220     adjEntry adj = (*it);
00221     if (adj) { e = adj->theEdge(); return true; }
00222     else return false;
00223 }
00224 
00225 inline bool test_forall_adj_edges_of_cluster(adjEntry &adj, edge &e)
00226 {
00227     if (adj) { e = adj->theEdge(); return true; }
00228     else return false;
00229 }
00230 
00231 
00232 class ClusterArrayBase;
00233 template<class T>class ClusterArray;
00234 
00235 //---------------------------------------------------------
00236 // iteration macros
00237 //---------------------------------------------------------
00238 
00240 #define forall_clusters(c,C) for((c)=(C).firstCluster(); (c); (c)=(c)->succ())
00241 
00242 #define forall_postOrderClusters(c,C)\
00243 for((c)=(C).firstPostOrderCluster(); (c); (c)=(c)->pSucc())
00244 
00245 
00246 
00247 
00249 
00253 class OGDF_EXPORT ClusterGraph : public GraphObserver
00254 {
00255     GraphList<ClusterElement> m_clusters; 
00256 
00257     const Graph *m_pGraph;            
00258 
00259     int     m_nClusters;              
00260     int     m_clusterIdCount;         
00261     int     m_clusterArrayTableSize;  
00262     
00263     mutable cluster m_postOrderStart; 
00264     cluster m_rootCluster;            
00265 
00266     bool    m_adjAvailable;       
00267     bool    m_allowEmptyClusters; 
00268 
00269     NodeArray<cluster> m_nodeMap; 
00270 
00271     NodeArray<ListIterator<node> >  m_itMap;   
00272     
00273     mutable ListPure<ClusterArrayBase*> m_regClusterArrays; 
00274     mutable ListPure<ClusterGraphObserver*> m_regObservers; 
00275 
00276 public:
00277 
00279     ClusterGraph();
00280 
00282 
00285     ClusterGraph(const Graph &G);
00286 
00288     ClusterGraph(const ClusterGraph &C);
00289 
00291 
00294     ClusterGraph(const ClusterGraph &C,Graph &G);
00295 
00297 
00302     ClusterGraph(
00303         const ClusterGraph &C,
00304         Graph &G,
00305         ClusterArray<cluster> &originalClusterTable,
00306         NodeArray<node> &originalNodeTable);
00307 
00309 
00314     ClusterGraph(
00315         const ClusterGraph &C,
00316         Graph &G,
00317         ClusterArray<cluster> &originalClusterTable,
00318         NodeArray<node> &originalNodeTable,
00319         EdgeArray<edge> &edgeCopy);
00320 
00321     virtual ~ClusterGraph();
00322 
00324     int maxClusterIndex() const { return m_clusterIdCount-1; }
00325 
00327     void clear();
00328 
00330     void semiClear();
00331 
00333     void init(const Graph &G);
00334     
00336     operator const Graph &() const { return *m_pGraph; }
00337 
00339     ClusterGraph &operator=(const ClusterGraph &C);
00340 
00342     void clearClusterTree(cluster C);
00343 
00345     //TODO should be named getConstGraph
00346     const Graph & getGraph() const {return *m_pGraph;}
00347 
00349     cluster newCluster(cluster parent, int id = -1);
00350 
00352     cluster createEmptyCluster(const cluster parent = 0, int clusterId = -1);
00353 
00355 
00363     cluster createCluster(SList<node>& nodes, const cluster parent = 0);
00364 
00366 
00370     void delCluster(cluster c);
00371 
00373     cluster rootCluster() const {return m_rootCluster;};
00374 
00376     inline cluster clusterOf(node v) const{ 
00377         OGDF_ASSERT(v->graphOf() == m_pGraph)
00378         return m_nodeMap[v];
00379     }
00380 
00382     int numberOfClusters() const { return m_nClusters; }
00384     int clusterIdCount() const { return m_clusterIdCount;} 
00385 
00387     int clusterArrayTableSize() const { return m_clusterArrayTableSize; }
00388 
00390     void moveCluster(cluster c, cluster newParent);
00391     
00392 
00394     void reassignNode(node v, cluster c);
00395 
00397     //inserted mainly for use in gmlparser.
00398     void reInit(Graph& G) 
00399     {
00400         reinitGraph(G);
00401     }
00402 
00403     //---------------------------
00404     //tree queries / depth issues
00405 
00407     void setUpdateDepth(bool b) const 
00408     {
00409         m_updateDepth = b;
00410         //make sure that depth cant be used anymore
00411         //(even if it may still be valid a little while)
00412         if (!b) m_depthUpToDate = false;
00413     }
00414 
00416     void pullUpSubTree(cluster c);
00417 
00419     //maybe later we should provide a permanent depth member update
00420     int treeDepth() const
00421     {
00422         //initialize depth at first call
00423         if (m_updateDepth && !m_depthUpToDate)
00424             computeSubTreeDepth(rootCluster());
00425         if (!m_updateDepth) OGDF_THROW(AlgorithmFailureException);
00426         int l_depth = 1;
00427         cluster c;
00428         forall_clusters(c, *this)
00429         {
00430             if (c->depth() > l_depth) l_depth = c->depth();
00431         }
00432 
00433         return l_depth;
00434     }
00436     void computeSubTreeDepth(cluster c) const;
00438     //should be called instead of direct c->depth call to assure
00439     //valid depth
00440     int& clusterDepth(cluster c) const 
00441     {
00442         // updateDepth must be set to true if depth info shall be used
00443         OGDF_ASSERT(m_updateDepth);
00444 
00445         //initialize depth at first call
00446         if (!m_depthUpToDate)
00447             computeSubTreeDepth(rootCluster());
00448         OGDF_ASSERT(c->depth() != 0)
00449         return c->depth();
00450     }
00451 
00453     cluster commonCluster(SList<node>& nodes);
00454 
00456 
00459     cluster commonCluster(node v, node w) const;
00460 
00462     cluster commonClusterLastAncestors(
00463         node v, 
00464         node w,
00465         cluster& c1,
00466         cluster& c2) const;
00468 
00469     cluster commonClusterPath(
00470         node v,
00471         node w,
00472         List<cluster>& eL) const;
00473 
00475     cluster commonClusterAncestorsPath(
00476         node v, 
00477         node w,
00478         cluster& c1,
00479         cluster& c2,
00480         List<cluster>& eL) const;
00481 
00483     ListIterator<ClusterArrayBase*> registerArray(ClusterArrayBase *pClusterArray) const;
00484 
00486     void unregisterArray(ListIterator<ClusterArrayBase*> it) const;
00487 
00489     ListIterator<ClusterGraphObserver*> registerObserver(ClusterGraphObserver *pObserver) const;
00490     
00492     void unregisterObserver(ListIterator<ClusterGraphObserver*> it) const;
00493     
00495 
00502     void emptyClusters(SList<cluster>& emptyCluster, SList<cluster>* checkCluster = 0);
00503 
00505     inline bool emptyOnNodeDelete(cluster c) //virtual?
00506     {
00507         //if (!c) return false; //Allows easy use in loops
00508         return (c->nCount() == 1) && (c->cCount() == 0);
00509     }
00510 
00512     inline bool emptyOnClusterDelete(cluster c) //virtual?
00513     {
00514         //if (!c) return false; //Allows easy use in loops
00515         return (c->nCount() == 0) && (c->cCount() == 1);
00516     }
00517 
00519     cluster firstCluster() const { return m_clusters.begin (); }
00521     cluster lastCluster () const { return m_clusters.rbegin(); }
00523     cluster firstPostOrderCluster() const { 
00524         if (!m_postOrderStart) postOrder();
00525         return m_postOrderStart; 
00526     }
00527 
00529     template<class CLUSTERLIST>
00530     void allClusters(CLUSTERLIST &clusters) const {
00531         clusters.clear();
00532         for (cluster c = m_clusters.begin(); c; c = c->succ())
00533             clusters.pushBack(c);
00534     }
00535 
00537     template<class NODELIST>
00538     void collaps(NODELIST &nodes,Graph &G){
00539         OGDF_ASSERT(&G == m_pGraph);
00540         m_adjAvailable = false;
00541 
00542         m_postOrderStart = 0;
00543         node v = nodes.popFrontRet();
00544         while (!nodes.empty())
00545         {
00546             node w = nodes.popFrontRet();
00547             adjEntry adj = w->firstAdj();
00548             while (adj !=0)
00549             {
00550                 adjEntry succ = adj->succ();
00551                 edge e = adj->theEdge();
00552                 if (e->source() == v || e->target() == v)
00553                     G.delEdge(e);
00554                 else if (e->source() == w)
00555                     G.moveSource(e,v);
00556                 else
00557                     G.moveTarget(e,v);
00558                 adj = succ;
00559             }
00560             //because nodes can already be unassigned (they are always
00561             //unassigned if deleted), we have to check this
00562             /*
00563             if (m_nodeMap[w])
00564             {
00565                 cluster c = m_nodeMap[w];
00566                 c->m_entries.del(m_itMap[w]);
00567             }
00568             */
00569             //removeNodeAssignment(w);
00570             G.delNode(w);
00571         }
00572     }
00573 
00575     template<class EDGELIST>
00576     void adjEdges(cluster c, EDGELIST &edges) const {
00577         edges.clear();
00578         edge e;
00579         if (m_adjAvailable)
00580         {
00581             forall_cluster_adj_edges(e,c)
00582                 edges.pushBack(e);
00583         }
00584     }
00585 
00587     template<class ADJLIST>
00588     void adjEntries(cluster c, ADJLIST &entries) const {
00589         entries.clear();
00590         adjEntry adj;
00591         if (m_adjAvailable)
00592         {
00593             forall_cluster_adj(adj,c)
00594                 entries.pushBack(adj);
00595         }
00596     }
00597 
00599     template<class LISTITERATOR>
00600     void makeAdjEntries(cluster c,LISTITERATOR start){
00601         adjEntry adj;
00602         c->m_adjEntries.clear();
00603         LISTITERATOR its;
00604         for (its = start; its.valid(); its++)
00605         {
00606             adj = (*its);
00607             c->m_adjEntries.pushBack(adj);
00608         }
00609     }
00610 
00611     //**************************
00612     //file output
00613 
00615     void writeGML(const char *fileName);
00616 
00618     void writeGML(ostream &os);
00619 
00620 
00621     //**************************
00622     //file input
00624     bool readClusterGML(const char* fileName, Graph& G);
00626     bool readClusterGML(istream& is, Graph& G);
00627 
00628     // read Cluster Graph from OGML file
00629     //bool readClusterGraphOGML(const char* fileName, ClusterGraph& CG, Graph& G);
00630 
00632     // (for debugging purposes only)
00633     bool consistencyCheck();
00634 
00636     // (for debugging purposes only)
00637     bool representsCombEmbedding();
00638 
00640     void adjAvailable(bool val){ m_adjAvailable = val;};
00641 
00642 protected:
00645     cluster doCreateCluster(SList<node>& nodes, 
00646         const cluster parent, int clusterId = -1);
00649     cluster doCreateCluster(SList<node>& nodes, 
00650         SList<cluster>& emptyCluster,
00651         const cluster parent, int clusterId = -1);
00652 
00653     mutable ClusterArray<int>* m_lcaSearch; 
00654     mutable int m_lcaNumber;
00655     mutable ClusterArray<cluster>* m_vAncestor;
00656     mutable ClusterArray<cluster>* m_wAncestor;
00657 
00659     void copyLCA(const ClusterGraph &C, ClusterArray<cluster>* clusterCopy=0);
00660     //int m_treeDepth; //should be implemented and updated in operations?
00661 
00662     mutable bool m_updateDepth; 
00663     mutable bool m_depthUpToDate; 
00664 
00666     //we assume that c is inserted via pushback in newparent->children
00667     void updatePostOrder(cluster c, cluster oldParent, cluster newParent);
00668 
00670     //0 if c==root 
00671     cluster postOrderPredecessor(cluster c) const;
00673     cluster leftMostCluster(cluster c) const;
00674 
00675     //---------------------------------------
00676     //functions inherited from GraphObserver:
00677     //define how to cope with graph changes
00678     
00680     virtual void nodeDeleted(node v) 
00681     { 
00682         bool cRemove = false;
00683         cluster c = clusterOf(v);
00684         if (!c) return;
00685         //never allow totally empty cluster
00686         //if ((emptyOnNodeDelete(c)) &&
00687         //  (c != rootCluster()) ) cRemove = true;
00688         unassignNode(v); 
00689         if (cRemove && !m_allowEmptyClusters) //parent exists
00690         {
00691             cluster nonEmpty = c->parent();
00692             cluster cRun = nonEmpty;
00693             delCluster(c);
00694             while ((cRun != rootCluster()) && (cRun->nCount() + cRun->cCount() == 0))
00695             {
00696                 nonEmpty = cRun->parent();
00697                 delCluster(cRun);
00698                 cRun = nonEmpty;
00699             }
00700 
00701         }
00702     }
00704     virtual void nodeAdded(node v)   
00705     {
00706         assignNode(v, rootCluster());
00707     };
00709     virtual void edgeDeleted(edge /* e */) {};
00711     virtual void edgeAdded(edge /* e */)   {};
00713     virtual void reInit()            {};
00715     virtual void cleared()           
00716     {
00717         //we don't want a complete clear, as the graph still exists
00718         //and can be updated from input stream
00719         semiClear();
00720     };//Graph cleared
00721 
00722 private:
00724     void assignNode(node v, cluster C);
00725 
00727     void unassignNode(node v);
00728 
00731     void removeNodeAssignment(node v)
00732     {
00733         if (m_nodeMap[v]) //iff == 0, itmap == 0 !!?
00734         {
00735             cluster C2 = m_nodeMap[v];
00736             C2->m_entries.del(m_itMap[v]);
00737             m_nodeMap[v] = 0; 
00738             m_itMap[v] = 0;   
00739         }
00740     }
00741 
00744     void shallowCopy(const ClusterGraph &C);
00745 
00748     void deepCopy(const ClusterGraph &C,Graph &G);
00751     void deepCopy(const ClusterGraph &C,Graph &G,   
00752                   ClusterArray<cluster> &originalClusterTable,
00753                   NodeArray<node> &originalNodeTable);
00757     void deepCopy(const ClusterGraph &C,Graph &G,   
00758                   ClusterArray<cluster> &originalClusterTable,
00759                   NodeArray<node> &originalNodeTable,
00760                   EdgeArray<edge> &edgeCopy);
00761 
00762 
00763     void clearClusterTree(cluster c,List<node> &attached);
00764 
00765     void initGraph(const Graph &G);
00766 
00768     void reinitGraph(const Graph &G);
00769 
00771     cluster newCluster(int id);
00773     cluster newCluster();
00774 
00776     void postOrder() const;
00778     void checkPostOrder() const;
00779 
00780     void postOrder(cluster c,SListPure<cluster> &S) const;
00781 
00782     void reinitArrays();
00783 
00784 
00786     void writeCluster(ostream &os,
00787                       NodeArray<int> &nId,
00788                       ClusterArray<int> & cId,
00789                       int &nextId,
00790                       cluster c,
00791                       String ttt);
00792 
00794     void writeGraphWinCluster(ostream &os,
00795                       NodeArray<int> &nId,
00796                       NodeArray<String> &nStr,
00797                       ClusterArray<int> &cId,
00798                       ClusterArray<String> &cStr,
00799                       int &nextId,
00800                       cluster c,
00801                       String ttt);
00802 
00803 };
00804 
00805 
00806 
00807 
00808 
00809 ostream &operator<<(ostream &os, ogdf::cluster c);
00810 
00811 
00812 } // end namespace ogdf
00813 
00814 #endif