File: ClusterGraph.h

package info (click to toggle)
bandage 0.9.0-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 15,684 kB
  • sloc: cpp: 45,359; sh: 491; makefile: 12
file content (825 lines) | stat: -rw-r--r-- 26,289 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
/*
 * $Revision: 2564 $
 *
 * last checkin:
 *   $Author: gutwenger $
 *   $Date: 2012-07-07 00:03:48 +0200 (Sa, 07. Jul 2012) $
 ***************************************************************/

/** \file
 * \brief Derived class of GraphObserver providing additional functionality
 * to handle clustered graphs.
 *
 * \author Sebastian Leipert, Karsten Klein
 *
 * \par License:
 * This file is part of the Open Graph Drawing Framework (OGDF).
 *
 * \par
 * Copyright (C)<br>
 * See README.txt in the root directory of the OGDF installation for details.
 *
 * \par
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * Version 2 or 3 as published by the Free Software Foundation;
 * see the file LICENSE.txt included in the packaging of this file
 * for details.
 *
 * \par
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * \par
 * You should have received a copy of the GNU General Public
 * License along with this program; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 *
 * \see  http://www.gnu.org/copyleft/gpl.html
 ***************************************************************/




#ifdef _MSC_VER
#pragma once
#endif


#ifndef OGDF_CLUSTER_GRAPH_H
#define OGDF_CLUSTER_GRAPH_H

#include "../basic/NodeArray.h"
#include "../basic/Stack.h"
#include "../basic/GraphObserver.h"


namespace ogdf {

class OGDF_EXPORT ClusterGraph;
class OGDF_EXPORT ClusterGraphObserver;

//! Representation of clusters in a clustered graph.
/**
 * \see ClusterGraph
 */
class OGDF_EXPORT ClusterElement : private GraphElement {

	friend class OGDF_EXPORT ClusterGraph;
	friend class GraphList<ClusterElement>;

	int						m_id;         //!< The index of this cluster.
	int						m_depth;      //!< The depth of this cluster in the cluster tree.
	List<node>				m_entries;    //!< The nodes in this cluster.
	List<ClusterElement*>	m_children;   //!< The child clusters of this cluster.
	ClusterElement			*m_parent;    //!< The parent of this cluster.
	ClusterElement			*m_pPrev;     //!< The postorder predecessor of this cluster.
	ClusterElement			*m_pNext;     //!< The postorder successor of this cluster.
	ListIterator<ClusterElement*> m_it;   //!< The position of this cluster within children list of its parent.

	List<adjEntry>			m_adjEntries;	//!< The adjacency list.
											// Don't use a GraphList !
											// This messes with the adjacency
											// list of the underlying graph

	#ifdef OGDF_DEBUG
	// we store the graph containing this cluster for debugging purposes
	const ClusterGraph *m_pClusterGraph;
	#endif


	void init(List<node> &nodes) {
		while (!nodes.empty())
			m_entries.pushBack(nodes.popFrontRet());
	}

	List<ClusterElement*> &getChildren(){
		return m_children;
	}

	List<node> &getNodes(){
		return m_entries;
	}

	//! Traverses the inclusion tree and adds nodes to \a clusterNodes.
	/**
	 * Invoked by public function getClusterNodes(List<node> &clusterNodes).
	 */
	void getClusterInducedNodes(List<node> &clusterNodes);
	void getClusterInducedNodes(NodeArray<bool> &clusterNode, int& num);


public:

	//! Creates a new cluster element.
	#ifdef OGDF_DEBUG
	ClusterElement(const ClusterGraph *pClusterGraph,int id):
		m_id(id),m_depth(0),m_parent(0),m_pPrev(0),m_pNext(0),m_it(0),
		m_pClusterGraph(pClusterGraph) { }
	#else
	ClusterElement(int id):
		m_id(id), m_depth(0),m_parent(0),m_pPrev(0),m_pNext(0),m_it(0) { }
	#endif


	#ifdef OGDF_DEBUG
	const ClusterGraph *graphOf() const { return m_pClusterGraph; }
	#endif


	//! Returns the (unique) index of the cluster.
	int index() const { return m_id; }
	//! Returns the depth of the cluster in the cluster tree.
	int depth() const { return m_depth; }
	int& depth()	  { return m_depth; }
	//! Returns the successor of the cluster in the list of all clusters.
	ClusterElement* succ() const { return (ClusterElement*)m_next; }
	//! Returns the predecessor of the cluster in the list of all clusters.
	ClusterElement* pred() const { return (ClusterElement*)m_prev; }

	//! Returns the postorder successor of the cluster in the list of all clusters.
	ClusterElement* pSucc() const { return m_pNext; }
	//! Returns the postorder predecessor of the cluster in the list of all clusters.
	ClusterElement* pPred() const { return m_pPrev; }

	// Iteration over tree structures.

	//! Returns the first element in the list of child clusters.
	ListConstIterator<ClusterElement*> cBegin() const{ return m_children.begin();}
	//! Returns the last element in the list of child clusters.
	ListConstIterator<ClusterElement*> crBegin() const{ return m_children.rbegin();}
	//! Returns the number of child clusters.
	int cCount(){ return m_children.size();}
	//! Returns the first element in list of child nodes.
	ListIterator<node> nBegin(){ return m_entries.begin();}
	//! Returns the first element in list of child nodes.
	ListConstIterator<node> nBegin() const{ return m_entries.begin();}
	//! Returns the number of child nodes.
	int nCount(){ return m_entries.size();}

	//! Returns the parent of the cluster.
	ClusterElement* parent(){return m_parent;}


	//! Returns the first adjacency entry in the list of outgoing edges.
	ListConstIterator<adjEntry> firstAdj() const { return m_adjEntries.begin();  }
	//! Returns the first adjacency entry in the list of outgoing edges.
	ListIterator<adjEntry> firstAdj() { return m_adjEntries.begin();  }
	//! Returns the last adjacency entry in the list of outgoing edges.
	ListConstIterator<adjEntry> lastAdj () const { return m_adjEntries.rbegin(); }
	//! Returns the last adjacency entry in the list of outgoing edges.
	ListIterator<adjEntry> lastAdj () { return m_adjEntries.rbegin(); }

	//! Returns the list of nodes in the cluster, i.e., all nodes in the subtree rooted at this cluster.
	/**
	 * Recursively traverses the cluster tree starting at this cluster.
	 */
	void getClusterNodes(List<node> &clusterNodes);
	//! Sets the entry for each node v to true if v is a member of
	//! the subgraph induced by the ClusterElement.
	//! All other entries remain unchanged!
	//! Returns the number of entries set to true.
	//! Precondition: clusterNode is a NodeArray initialized on the clustergraph
	//! the ClusterElement belongs to.
	int getClusterNodes(NodeArray<bool> &clusterNode);

	OGDF_NEW_DELETE

};// class ClusterElement




typedef ClusterElement *cluster; //!< The type of clusters.


#define forall_cluster_adj(adj,c)\
for(ogdf::ListIterator<adjEntry> ogdf_loop_var=(c)->firstAdj();\
	ogdf::test_forall_adj_entries_of_cluster(ogdf_loop_var,(adj));\
	ogdf_loop_var=ogdf_loop_var.succ())

#define forall_cluster_rev_adj(adj,c)\
for(ogdf::ListIterator<adjEntry> ogdf_loop_var=(c)->lastAdj();\
	ogdf::test_forall_adj_entries_of_cluster(ogdf_loop_var,(adj));\
	ogdf_loop_var=ogdf_loop_var.pred())

#define forall_cluster_adj_edges(e,c)\
for(ogdf::ListIterator<adjEntry> ogdf_loop_var=(c)->firstAdj();\
	ogdf::test_forall_adj_edges_of_cluster(ogdf_loop_var,(e));\
	ogdf_loop_var=ogdf_loop_var.succ())



inline bool test_forall_adj_entries_of_cluster(ListIterator<adjEntry> &it, adjEntry &adj)
{
	if (it.valid()) { adj = (*it);return true; }
	else return false;
}

inline bool test_forall_adj_edges_of_cluster(ListIterator<adjEntry> &it, edge &e)
{
	adjEntry adj = (*it);
	if (adj) { e = adj->theEdge(); return true; }
	else return false;
}

inline bool test_forall_adj_edges_of_cluster(adjEntry &adj, edge &e)
{
	if (adj) { e = adj->theEdge(); return true; }
	else return false;
}


class ClusterArrayBase;
template<class T>class ClusterArray;

//---------------------------------------------------------
// iteration macros
//---------------------------------------------------------

//! Iteration over all clusters \a c of cluster graph \a C.
#define forall_clusters(c,C) for((c)=(C).firstCluster(); (c); (c)=(c)->succ())
//! Iteration over all clusters \a c of cluster graph \a C (in postorder).
#define forall_postOrderClusters(c,C)\
for((c)=(C).firstPostOrderCluster(); (c); (c)=(c)->pSucc())




//! Representation of clustered graphs.
/**
 * This class is derived from GraphObserver and handles hierarchical
 * clustering of the nodes in a graph, providing additional functionality.
 */
class OGDF_EXPORT ClusterGraph : public GraphObserver
{
	GraphList<ClusterElement> m_clusters; //!< The list of all clusters.

	const Graph *m_pGraph;			  //!< The associated graph.

	int		m_nClusters;			  //!< The number of clusters.
	int		m_clusterIdCount;		  //!< The index assigned to the next created cluster.
	int		m_clusterArrayTableSize;  //!< The current table size of cluster arrays.

	mutable cluster m_postOrderStart; //!< The first cluster in postorder.
	cluster	m_rootCluster;			  //!< The root cluster.

	bool    m_adjAvailable;		  //! True if the adjacency list for each cluster is available.
	bool    m_allowEmptyClusters; //! Defines if empty clusters are deleted immediately if generated by operations.

	NodeArray<cluster> m_nodeMap; //!< Stores the cluster of each node.
	//! Stories for every node its position within the children list of its cluster.
	NodeArray<ListIterator<node> >  m_itMap;

	mutable ListPure<ClusterArrayBase*> m_regClusterArrays; //!< The registered cluster arrays.
	mutable ListPure<ClusterGraphObserver*> m_regObservers; //!< The registered graph observers.

public:

	//! Creates a cluster graph associated with no graph.
	ClusterGraph();

	//! Creates a cluster graph associated with graph \a G.
	/**
	 * All nodes in \a G are assigned to the root cluster.
	 */
	ClusterGraph(const Graph &G);

	//! Copy constructor.
	ClusterGraph(const ClusterGraph &C);

	//! Constructs a clustered graph that is a copy of clustered graph C.
	/**
	 * The underlying graph \a G is made a copy of C.getGraph().
	 */
	ClusterGraph(const ClusterGraph &C,Graph &G);

	//! Constructs a clustered graph that is a copy of clustered graph C.
	/**
	 * The underlying graph \a G is made a copy of C.getGraph(). Stores the
	 * new copies of the original nodes and clusters in the arrays
	 * \a originalNodeTable and \a originalClusterTable.
	 */
	ClusterGraph(
		const ClusterGraph &C,
		Graph &G,
		ClusterArray<cluster> &originalClusterTable,
		NodeArray<node> &originalNodeTable);

	//! Constructs a clustered graph that is a copy of clustered graph C.
	/**
	 * The underlying graph \a G is made a copy of C.getGraph(). Stores the
	 * new copies of the original nodes, edges, and clusters in the arrays
	 * \a originalNodeTable, \a edgeCopy, and \a originalClusterTable.
	 */
	ClusterGraph(
		const ClusterGraph &C,
		Graph &G,
		ClusterArray<cluster> &originalClusterTable,
		NodeArray<node> &originalNodeTable,
		EdgeArray<edge> &edgeCopy);

	virtual ~ClusterGraph();

	//! Returns the maximal used cluster index.
	int maxClusterIndex() const { return m_clusterIdCount-1; }

	//! Clears all cluster data.
	void clear();

	//! Clears all data but does not delete root cluster.
	void semiClear();

	//! Clears all cluster data and then reinitializes the instance with underlying graph \a G.
	void init(const Graph &G);

	//! Conversion to const Graph reference.
	operator const Graph &() const { return *m_pGraph; }

	//! Assignment operator.
	ClusterGraph &operator=(const ClusterGraph &C);

	//! Removes all clusters from the cluster subtree rooted at cluster C except for cluster C itself.
	void clearClusterTree(cluster C);

	//! Returns a reference to the underlying graph.
	//TODO should be named getConstGraph
	const Graph & getGraph() const {return *m_pGraph;}

	//! Inserts a new cluster; makes it a child of the cluster \a parent.
	cluster newCluster(cluster parent, int id = -1);

	//! Creates an empty cluster with index \a clusterId and parent \a parent.
	cluster createEmptyCluster(const cluster parent = 0, int clusterId = -1);

	//! Creates a new cluster containing the nodes given by \a nodes; makes it a child of the cluster \a parent.
	/**
	 * The nodes are reassigned to the new cluster. If you turn off
	 * \a m_allowEmptyclusters, an emptied cluster is deleted except if all
	 * nodes are put into the same cluster.
	 * @param nodes are the nodes that will be reassigned to the new cluster.
	 * @param parent is the parent of the new cluster.
	 * \return the created cluster.
	 */
	cluster createCluster(SList<node>& nodes, const cluster parent = 0);

	//! Deletes cluster \a c.
	/**
	 * All subclusters become children of parent cluster of \a c.
	 * \pre \a c is not the root cluster.
	 */
	void delCluster(cluster c);

	//! Returns the root cluster.
	cluster rootCluster() const { return m_rootCluster; }

	//! Returns the cluster to which a node belongs.
	inline cluster clusterOf(node v) const{
		OGDF_ASSERT(v->graphOf() == m_pGraph)
		return m_nodeMap[v];
	}

	//! Returns number of clusters.
	int numberOfClusters() const { return m_nClusters; }
	//! Returns upper bound for cluster indices.
	int clusterIdCount() const { return m_clusterIdCount;}

	//! Returns table size of cluster arrays associated with this graph.
	int clusterArrayTableSize() const { return m_clusterArrayTableSize; }

	//! Moves cluster \a c to a new parent \a newParent.
	void moveCluster(cluster c, cluster newParent);


	//! Reassigns node \a v to cluster \ c.
	void reassignNode(node v, cluster c);

	//! Clear cluster info structure, reinitializes with underlying graph \a G.
	//inserted mainly for use in gmlparser.
	void reInit(Graph& G)
	{
		reinitGraph(G);
	}

	//---------------------------
	//tree queries / depth issues

	//! Turns automatic update of node depth values on or off.
	void setUpdateDepth(bool b) const
	{
		m_updateDepth = b;
		//make sure that depth cant be used anymore
		//(even if it may still be valid a little while)
		if (!b) m_depthUpToDate = false;
	}

	//! Updates depth information in subtree after delCluster.
	void pullUpSubTree(cluster c);

	//! Computes depth of cluster tree, running time O(C).
	//maybe later we should provide a permanent depth member update
	int treeDepth() const
	{
		//initialize depth at first call
		if (m_updateDepth && !m_depthUpToDate)
			computeSubTreeDepth(rootCluster());
		if (!m_updateDepth) OGDF_THROW(AlgorithmFailureException);
		int l_depth = 1;
		cluster c;
		forall_clusters(c, *this)
		{
			if (c->depth() > l_depth) l_depth = c->depth();
		}

		return l_depth;
	}
	//! Computes depth of cluster tree hanging at \a c.
	void computeSubTreeDepth(cluster c) const;
	//! Returns depth of cluster c in cluster tree, starting with root depth 1.
	//should be called instead of direct c->depth call to assure
	//valid depth
	int& clusterDepth(cluster c) const
	{
		// updateDepth must be set to true if depth info shall be used
		OGDF_ASSERT(m_updateDepth);

		//initialize depth at first call
		if (!m_depthUpToDate)
			computeSubTreeDepth(rootCluster());
		OGDF_ASSERT(c->depth() != 0)
		return c->depth();
	}

	//! Returns lowest common cluster of nodes in list \a nodes.
	cluster commonCluster(SList<node>& nodes);

	//! Returns the lowest common cluster of \a v and \a w in the cluster tree
	/**
	 * \pre \a v  and \a w are nodes in the graph.
	 */
	cluster commonCluster(node v, node w) const;

	//! Returns the lowest common cluster lca and the highest ancestors on the path to lca.
	cluster commonClusterLastAncestors(
		node v,
		node w,
		cluster& c1,
		cluster& c2) const;
	//! Returns lca of \a v and \a w and stores corresponding path in \a eL.

	cluster commonClusterPath(
		node v,
		node w,
		List<cluster>& eL) const;

	//! Returns lca of \a v and \a w, stores corresponding path in \a eL and ancestors in \a c1, \a c2.
	cluster commonClusterAncestorsPath(
		node v,
		node w,
		cluster& c1,
		cluster& c2,
		List<cluster>& eL) const;

	//! Registers a cluster array.
	ListIterator<ClusterArrayBase*> registerArray(ClusterArrayBase *pClusterArray) const;

	//! Unregisters a cluster array.
	void unregisterArray(ListIterator<ClusterArrayBase*> it) const;

	//! Registers a ClusterGraphObserver.
	ListIterator<ClusterGraphObserver*> registerObserver(ClusterGraphObserver *pObserver) const;

	//! Unregisters a ClusterGraphObserver.
	void unregisterObserver(ListIterator<ClusterGraphObserver*> it) const;

	//! Returns the list of clusters that are empty or only contain empty clusters.
	/**
	 * The list is constructed in an order that allows deletion and reinsertion.
	 * We never set rootcluster to be one of the empty clusters!!
	 * if checkClusters is given, only list elements are checked
	 * to allow efficient checking in the case
	 * that you know which clusters were recently changed (e.g. node reass.)
	 */
	void emptyClusters(SList<cluster>& emptyCluster, SList<cluster>* checkCluster = 0);

	//! Returns true if cluster \a c has only one node and no children.
	inline bool emptyOnNodeDelete(cluster c) //virtual?
	{
		//if (!c) return false; //Allows easy use in loops
		return (c->nCount() == 1) && (c->cCount() == 0);
	}

	//! Returns true if cluster \a c has only one child and no nodes.
	inline bool emptyOnClusterDelete(cluster c) //virtual?
	{
		//if (!c) return false; //Allows easy use in loops
		return (c->nCount() == 0) && (c->cCount() == 1);
	}

	//! Returns the first cluster in the list of all clusters.
	cluster firstCluster() const { return m_clusters.begin (); }
	//! Returns the last cluster in the list of all cluster.
	cluster lastCluster () const { return m_clusters.rbegin(); }
	//! Returns the first cluster in the list of post ordered clusters.
	cluster firstPostOrderCluster() const {
		if (!m_postOrderStart) postOrder();
		return m_postOrderStart;
	}

	//! Returns the list of all clusters in \a clusters.
	template<class CLUSTERLIST>
	void allClusters(CLUSTERLIST &clusters) const {
		clusters.clear();
		for (cluster c = m_clusters.begin(); c; c = c->succ())
			clusters.pushBack(c);
	}

	//! Collapses all nodes in the list \a nodes to the first node; multi-edges are removed.
	template<class NODELIST>
	void collaps(NODELIST &nodes,Graph &G){
		OGDF_ASSERT(&G == m_pGraph);
		m_adjAvailable = false;

		m_postOrderStart = 0;
		node v = nodes.popFrontRet();
		while (!nodes.empty())
		{
			node w = nodes.popFrontRet();
			adjEntry adj = w->firstAdj();
			while (adj !=0)
			{
				adjEntry succ = adj->succ();
				edge e = adj->theEdge();
				if (e->source() == v || e->target() == v)
					G.delEdge(e);
				else if (e->source() == w)
					G.moveSource(e,v);
				else
					G.moveTarget(e,v);
				adj = succ;
			}
			//because nodes can already be unassigned (they are always
			//unassigned if deleted), we have to check this
			/*
			if (m_nodeMap[w])
			{
				cluster c = m_nodeMap[w];
				c->m_entries.del(m_itMap[w]);
			}
			*/
			//removeNodeAssignment(w);
			G.delNode(w);
		}
	}

	//! Returns the list of all edges adjacent to cluster \a c in \a edges.
	template<class EDGELIST>
	void adjEdges(cluster c, EDGELIST &edges) const {
		edges.clear();
		edge e;
		if (m_adjAvailable)
		{
			forall_cluster_adj_edges(e,c)
				edges.pushBack(e);
		}
	}

	//! Returns the list of all adjacency entries adjacent to cluster \a c in \a entries.
	template<class ADJLIST>
	void adjEntries(cluster c, ADJLIST &entries) const {
		entries.clear();
		adjEntry adj;
		if (m_adjAvailable)
		{
			forall_cluster_adj(adj,c)
				entries.pushBack(adj);
		}
	}

	//! Computes the adjacency entry list for cluster \a c.
	template<class LISTITERATOR>
	void makeAdjEntries(cluster c,LISTITERATOR start){
		adjEntry adj;
		c->m_adjEntries.clear();
		LISTITERATOR its;
		for (its = start; its.valid(); its++)
		{
			adj = (*its);
			c->m_adjEntries.pushBack(adj);
		}
	}

	//**************************
	//file output

	//! Writes the cluster graph in GML format to file \a fileName.
	void writeGML(const char *fileName);

	//! Writes the cluster graph in GML format to output stream \a os.
	void writeGML(ostream &os);


	//**************************
	//file input
	//! reading graph, attributes, cluster structure from file
	bool readClusterGML(const char* fileName, Graph& G);
	//! reading graph, attributes, cluster structure from stream
	bool readClusterGML(istream& is, Graph& G);

	// read Cluster Graph from OGML file
	//bool readClusterGraphOGML(const char* fileName, ClusterGraph& CG, Graph& G);

	//! Checks the consistency of the data structure.
	// (for debugging purposes only)
	bool consistencyCheck();

	//! Checks the combinatorial cluster planar embedding.
	// (for debugging purposes only)
	bool representsCombEmbedding();

	//! Sets the availability status of the adjacency entries.
	void adjAvailable(bool val){ m_adjAvailable = val; }

protected:
	//! Creates new cluster containing nodes in parameter list
	//! with index \a clusterid.
	cluster doCreateCluster(SList<node>& nodes,
		const cluster parent, int clusterId = -1);
	//! Creates new cluster containing nodes in parameter list and
	//! stores resulting empty clusters in list, cluster has index \a clusterid.
	cluster doCreateCluster(SList<node>& nodes,
		SList<cluster>& emptyCluster,
		const cluster parent, int clusterId = -1);

	mutable ClusterArray<int>* m_lcaSearch; //!< Used to save last search run number for commoncluster.
	mutable int m_lcaNumber;//!< Used to save last search run number for commoncluster.
	mutable ClusterArray<cluster>* m_vAncestor;//!< Used to save last search run number for commoncluster.
	mutable ClusterArray<cluster>* m_wAncestor;//!< Used to save last search run number for commoncluster.

	//! Copies lowest common ancestor info to copy of clustered graph.
	void copyLCA(const ClusterGraph &C, ClusterArray<cluster>* clusterCopy=0);
	//int m_treeDepth; //should be implemented and updated in operations?

	mutable bool m_updateDepth; //!< Depth of clusters is always updated if set to true.
	mutable bool m_depthUpToDate; //!< Status of cluster depth information.

	//! Adjusts the post order structure for moved clusters.
	//we assume that c is inserted via pushback in newparent->children
	void updatePostOrder(cluster c, cluster oldParent, cluster newParent);

	//! Computes new predecessor for SUBTREE at moved cluster c.
	//0 if c==root
	cluster postOrderPredecessor(cluster c) const;
	//! Leftmost cluster in subtree rooted at c, gets predecessor of subtree.
	cluster leftMostCluster(cluster c) const;

	//---------------------------------------
	//functions inherited from GraphObserver:
	//define how to cope with graph changes

	//! Implementation of inherited method: Updates data if node deleted.
	virtual void nodeDeleted(node v)
	{
		bool cRemove = false;
		cluster c = clusterOf(v);
		if (!c) return;
		//never allow totally empty cluster
		//if ((emptyOnNodeDelete(c)) &&
		//	(c != rootCluster()) ) cRemove = true;
		unassignNode(v);
		if (cRemove && !m_allowEmptyClusters) //parent exists
		{
			cluster nonEmpty = c->parent();
			cluster cRun = nonEmpty;
			delCluster(c);
			while ((cRun != rootCluster()) && (cRun->nCount() + cRun->cCount() == 0))
			{
				nonEmpty = cRun->parent();
				delCluster(cRun);
				cRun = nonEmpty;
			}

		}
	}
	//! Implementation of inherited method: Updates data if node added.
	virtual void nodeAdded(node v)
	{
		assignNode(v, rootCluster());
	}
	//! Implementation of inherited method: Updates data if edge deleted.
	virtual void edgeDeleted(edge /* e */) { }
	//! Implementation of inherited method: Updates data if edge added.
	virtual void edgeAdded(edge /* e */)   { }
	//! Currently does nothing.
	virtual void reInit()            { }
	//! Clears cluster data without deleting root when underlying graphs' clear method is called.
	virtual void cleared()
	{
		//we don't want a complete clear, as the graph still exists
		//and can be updated from input stream
		semiClear();
	}//Graph cleared

private:
	//! Assigns node \a v to cluster \a c (\a v not yet assigned!).
	void assignNode(node v, cluster C);

	//! Unassigns node \a v from its cluster.
	void unassignNode(node v);

	//! Remove the assignment entries for nodes.
	//! Checks if node is currently not assigned.
	void removeNodeAssignment(node v)
	{
		if (m_nodeMap[v]) //iff == 0, itmap == 0 !!?
		{
			cluster C2 = m_nodeMap[v];
			C2->m_entries.del(m_itMap[v]);
			m_nodeMap[v] = 0;
			m_itMap[v] = 0;
		}
	}

	//! Performs a copy of the cluster structure of C,
	//! the underlying graph stays the same.
	void shallowCopy(const ClusterGraph &C);

	//! Perform a deep copy on C, C's underlying
	//! graph is copied into G.
	void deepCopy(const ClusterGraph &C,Graph &G);

	//! Perform a deep copy on C, C's underlying
	//! graph is copied into G. Stores associated nodes in \a originalNodeTable.

	void deepCopy(
		const ClusterGraph &C,Graph &G,
		ClusterArray<cluster> &originalClusterTable,
		NodeArray<node> &originalNodeTable);

	//! Perform a deep copy on C, C's underlying
	//! graph is copied into G.  Stores associated nodes in \a originalNodeTable
	//! and edges in \a edgeCopy.
	void deepCopy(
		const ClusterGraph &C,Graph &G,
		ClusterArray<cluster> &originalClusterTable,
		NodeArray<node> &originalNodeTable,
		EdgeArray<edge> &edgeCopy);


	void clearClusterTree(cluster c,List<node> &attached);

	void initGraph(const Graph &G);

	//! Reinitializes instance with graph \a G.
	void reinitGraph(const Graph &G);

	//! Creates new cluster with given id, precondition: id not used
	cluster newCluster(int id);
	//! Creates new cluster.
	cluster newCluster();

	//! Create postorder information in cluster tree.
	void postOrder() const;
	//! Check postorder information in cluster tree.
//	void checkPostOrder() const;

	void postOrder(cluster c,SListPure<cluster> &S) const;

	void reinitArrays();


	//! Recursively write the cluster structure in GML.
	void writeCluster(
		ostream &os,
		NodeArray<int> &nId,
		ClusterArray<int> & cId,
		int &nextId,
		cluster c,
		String ttt);

	//! Recursively write the cluster structure in GraphWin GML.
	void writeGraphWinCluster(
		ostream &os,
		NodeArray<int> &nId,
		NodeArray<String> &nStr,
		ClusterArray<int> &cId,
		ClusterArray<String> &cStr,
		int &nextId,
		cluster c,
		String ttt);

};





ostream &operator<<(ostream &os, ogdf::cluster c);


} // end namespace ogdf

#endif