1 /** \file
2  * \brief Implementation of Graph class
3  *
4  * \author Carsten Gutwenger
5  *
6  * \par License:
7  * This file is part of the Open Graph Drawing Framework (OGDF).
8  *
9  * \par
10  * Copyright (C)<br>
11  * See README.md in the OGDF root directory for details.
12  *
13  * \par
14  * This program is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU General Public License
16  * Version 2 or 3 as published by the Free Software Foundation;
17  * see the file LICENSE.txt included in the packaging of this file
18  * for details.
19  *
20  * \par
21  * This program is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24  * GNU General Public License for more details.
25  *
26  * \par
27  * You should have received a copy of the GNU General Public
28  * License along with this program; if not, see
29  * http://www.gnu.org/copyleft/gpl.html
30  */
31 
32 #include <ogdf/basic/Math.h>
33 #include <ogdf/basic/Array.h>
34 #include <ogdf/basic/AdjEntryArray.h>
35 #include <ogdf/fileformats/GmlParser.h>
36 #include <ogdf/basic/simple_graph_alg.h>
37 
38 using std::mutex;
39 
40 #ifndef OGDF_MEMORY_POOL_NTS
41 using std::lock_guard;
42 #endif
43 
44 
45 #define MIN_NODE_TABLE_SIZE (1 << 4)
46 #define MIN_EDGE_TABLE_SIZE (1 << 4)
47 
48 
49 namespace ogdf {
50 
51 using Math::nextPower2;
52 
Graph()53 Graph::Graph()
54 {
55 	m_nodeIdCount = m_edgeIdCount = 0;
56 	resetTableSizes();
57 }
58 
59 
Graph(const Graph & G)60 Graph::Graph(const Graph &G)
61 {
62 	m_nodeIdCount = m_edgeIdCount = 0;
63 	copy(G);
64 	resetTableSizes();
65 }
66 
67 
~Graph()68 Graph::~Graph()
69 {
70 	restoreAllEdges();
71 
72 	while(!m_regNodeArrays.empty()) {
73 		m_regNodeArrays.popFrontRet()->disconnect();
74 	}
75 
76 	while(!m_regEdgeArrays.empty()) {
77 		m_regEdgeArrays.popFrontRet()->disconnect();
78 	}
79 
80 	while(!m_regAdjArrays.empty()) {
81 		m_regAdjArrays.popFrontRet()->disconnect();
82 	}
83 
84 	for (node v = nodes.head(); v; v = v->succ()) {
85 		v->adjEntries.~GraphObjectContainer<AdjElement>();
86 	}
87 }
88 
89 
operator =(const Graph & G)90 Graph &Graph::operator=(const Graph &G)
91 {
92 	clear();
93 	copy(G);
94 	reinitArrays();
95 
96 #ifdef OGDF_HEAVY_DEBUG
97 	consistencyCheck();
98 #endif
99 
100 	return *this;
101 }
102 
103 
assign(const Graph & G,NodeArray<node> & mapNode,EdgeArray<edge> & mapEdge)104 void Graph::assign(const Graph &G, NodeArray<node> &mapNode,
105 	EdgeArray<edge> &mapEdge)
106 {
107 	clear();
108 	copy(G,mapNode,mapEdge);
109 	reinitArrays();
110 }
111 
112 
construct(const Graph & G,NodeArray<node> & mapNode,EdgeArray<edge> & mapEdge)113 void Graph::construct(const Graph &G, NodeArray<node> &mapNode,
114 	EdgeArray<edge> &mapEdge)
115 {
116 	copy(G,mapNode,mapEdge);
117 	resetTableSizes();
118 }
119 
120 
copy(const Graph & G,NodeArray<node> & mapNode,EdgeArray<edge> & mapEdge)121 void Graph::copy(const Graph &G, NodeArray<node> &mapNode,
122 	EdgeArray<edge> &mapEdge)
123 {
124 	if (G.nodes.empty()) return;
125 
126 	mapNode.init(G,nullptr);
127 
128 	for(node vG : G.nodes) {
129 		node v = mapNode[vG] = pureNewNode();
130 		v->m_indeg = vG->m_indeg;
131 		v->m_outdeg = vG->m_outdeg;
132 	}
133 
134 	if (G.edges.empty()) return;
135 
136 	mapEdge.init(G,nullptr);
137 
138 	for(edge e : G.edges) {
139 		edge eC;
140 		edges.pushBack(eC = mapEdge[e] =
141 			new EdgeElement(
142 				mapNode[e->source()],mapNode[e->target()],m_edgeIdCount));
143 
144 		eC->m_adjSrc = new AdjElement(eC,m_edgeIdCount<<1);
145 		(eC->m_adjTgt = new AdjElement(eC,(m_edgeIdCount<<1)|1))
146 			->m_twin = eC->m_adjSrc;
147 		eC->m_adjSrc->m_twin = eC->m_adjTgt;
148 		m_edgeIdCount++;
149 	}
150 
151 	for(node vG : G.nodes) {
152 		node v = mapNode[vG];
153 		internal::GraphList<AdjElement> &adjEdges = vG->adjEntries;
154 		for (AdjElement *adjG = adjEdges.head(); adjG; adjG = adjG->succ()) {
155 			edge e = adjG->m_edge;
156 			edge eC = mapEdge[e];
157 
158 			adjEntry adj = adjG->isSource() ? eC->adjSource() : eC->adjTarget();
159 			v->adjEntries.pushBack(adj);
160 			adj->m_node = v;
161 		}
162 	}
163 }
164 
165 
copy(const Graph & G)166 void Graph::copy(const Graph &G)
167 {
168 	NodeArray<node> mapNode;
169 	EdgeArray<edge> mapEdge;
170 	copy(G,mapNode,mapEdge);
171 
172 #ifdef OGDF_HEAVY_DEBUG
173 	consistencyCheck();
174 #endif
175 }
176 
177 
constructInitByCC(const CCsInfo & info,int cc,NodeArray<node> & mapNode,EdgeArray<edge> & mapEdge)178 void Graph::constructInitByCC(
179 	const CCsInfo &info,
180 	int cc,
181 	NodeArray<node> &mapNode,
182 	EdgeArray<edge> &mapEdge)
183 {
184 	// clear
185 	for (node v = nodes.head(); v; v = v->succ()) {
186 		v->adjEntries.~GraphObjectContainer<AdjElement>();
187 	}
188 
189 	nodes.clear();
190 	edges.clear();
191 
192 	m_nodeIdCount = m_edgeIdCount = 0;
193 
194 	for(int i = info.startNode(cc); i < info.stopNode(cc); ++i)
195 	{
196 		node vG = info.v(i);
197 
198 #ifdef OGDF_DEBUG
199 		node v = new NodeElement(this,m_nodeIdCount++);
200 #else
201 		node v = new NodeElement(m_nodeIdCount++);
202 #endif
203 		mapNode[vG] = v;
204 		nodes.pushBack(v);
205 
206 		v->m_indeg  = vG->m_indeg;
207 		v->m_outdeg = vG->m_outdeg;
208 	}
209 
210 	for(int i = info.startEdge(cc); i < info.stopEdge(cc); ++i)
211 	{
212 		edge eG = info.e(i);
213 		node v = mapNode[eG->source()];
214 		node w = mapNode[eG->target()];
215 
216 		edge eC = mapEdge[eG] = new EdgeElement(v, w, m_edgeIdCount);
217 		edges.pushBack(eC);
218 
219 		adjEntry adjSrc = new AdjElement(eC,  m_edgeIdCount<<1   );
220 		adjEntry adjTgt = new AdjElement(eC, (m_edgeIdCount<<1)|1);
221 
222 		(eC->m_adjSrc = adjSrc)->m_twin = adjTgt;
223 		(eC->m_adjTgt = adjTgt)->m_twin = adjSrc;
224 
225 		adjSrc->m_node = v;
226 		adjTgt->m_node = w;
227 
228 		++m_edgeIdCount;
229 	}
230 
231 	for(int i = info.startNode(cc); i < info.stopNode(cc); ++i)
232 	{
233 		node vG = info.v(i);
234 		node v  = mapNode[vG];
235 
236 		for(adjEntry adjG : vG->adjEntries) {
237 			edge eG = adjG->theEdge();
238 			edge e = mapEdge[eG];
239 
240 			adjEntry adj = (adjG == eG->adjSource()) ? e->adjSource() : e->adjTarget();
241 			v->adjEntries.pushBack(adj);
242 		}
243 	}
244 
245 	reinitArrays();
246 
247 #ifdef OGDF_HEAVY_DEBUG
248 	consistencyCheck();
249 #endif
250 }
251 
252 
constructInitByNodes(const Graph & G,const List<node> & nodeList,NodeArray<node> & mapNode,EdgeArray<edge> & mapEdge)253 void Graph::constructInitByNodes(
254 	const Graph &G,
255 	const List<node> &nodeList,
256 	NodeArray<node> &mapNode,
257 	EdgeArray<edge> &mapEdge)
258 {
259 	// clear
260 	for (node v = nodes.head(); v; v = v->succ()) {
261 		v->adjEntries.~GraphObjectContainer<AdjElement>();
262 	}
263 
264 	nodes.clear();
265 	edges.clear();
266 
267 	m_nodeIdCount = m_edgeIdCount = 0;
268 	m_nodeArrayTableSize = MIN_NODE_TABLE_SIZE;
269 
270 
271 	// list of edges adjacent to nodes in nodeList
272 	SListPure<edge> adjEdges;
273 
274 	// create nodes and assemble list of adjEntries
275 	for(node vG : nodeList) {
276 		node v = mapNode[vG] = pureNewNode();
277 
278 		v->m_indeg = vG->m_indeg;
279 		v->m_outdeg = vG->m_outdeg;
280 
281 		for(adjEntry adjG : vG->adjEntries) {
282 			// corresponding adjacency entries differ by index modulo 2
283 			// the following conditions makes sure that each edge is
284 			// added only once to adjEntries
285 			if ((adjG->m_id & 1) == 0)
286 				adjEdges.pushBack(adjG->m_edge);
287 		}
288 	}
289 
290 	// create edges
291 	for (edge eG : adjEdges)
292 	{
293 		node v = mapNode[eG->source()];
294 		node w = mapNode[eG->target()];
295 
296 		edge eC = mapEdge[eG] = new EdgeElement(v, w, m_edgeIdCount);
297 		edges.pushBack(eC);
298 
299 		eC->m_adjSrc = new AdjElement(eC, m_edgeIdCount<<1);
300 		(eC->m_adjTgt = new AdjElement(eC, (m_edgeIdCount<<1)|1))
301 			->m_twin = eC->m_adjSrc;
302 		eC->m_adjSrc->m_twin = eC->m_adjTgt;
303 		++m_edgeIdCount;
304 	}
305 
306 	EdgeArray<bool> mark(G,false);
307 	for(node vG : nodeList) {
308 		node v = mapNode[vG];
309 
310 		for (adjEntry adjG: vG->adjEntries) {
311 			edge e = adjG->m_edge;
312 			edge eC = mapEdge[e];
313 
314 			adjEntry adj;
315 			if (eC->isSelfLoop()) {
316 				if (mark[e])
317 					adj = eC->m_adjTgt;
318 				else {
319 					adj = eC->m_adjSrc;
320 					mark[e] = true;
321 				}
322 			} else
323 				adj = (v == eC->m_src) ? eC->m_adjSrc : eC->m_adjTgt;
324 
325 			v->adjEntries.pushBack(adj);
326 			adj->m_node = v;
327 		}
328 	}
329 
330 	// set size of associated arrays and reinitialize all (we have now a
331 	// completely new graph)
332 	reinitArrays();
333 
334 #ifdef OGDF_HEAVY_DEBUG
335 	consistencyCheck();
336 #endif
337 }
338 
339 
340 //mainly a copy of the above code, remerge this again
constructInitByActiveNodes(const List<node> & nodeList,const NodeArray<bool> & activeNodes,NodeArray<node> & mapNode,EdgeArray<edge> & mapEdge)341 void Graph::constructInitByActiveNodes(
342 	const List<node> &nodeList,
343 	const NodeArray<bool> &activeNodes,
344 	NodeArray<node> &mapNode,
345 	EdgeArray<edge> &mapEdge)
346 {
347 	// clear
348 	for (node v = nodes.head(); v; v = v->succ()) {
349 		v->adjEntries.~GraphObjectContainer<AdjElement>();
350 	}
351 
352 	nodes.clear();
353 	edges.clear();
354 
355 	m_nodeIdCount = m_edgeIdCount = 0;
356 	m_nodeArrayTableSize = MIN_NODE_TABLE_SIZE;
357 
358 
359 	// list of edges adjacent to nodes in nodeList
360 	SListPure<edge> adjEdges;
361 
362 	// create nodes and assemble list of adjEntries
363 	// NOTE: nodeList is a list of ACTIVE nodes
364 	for(node vG : nodeList) {
365 		node v = mapNode[vG] = pureNewNode();
366 
367 		int inCount = 0;
368 		int outCount = 0;
369 		for(adjEntry adjG : vG->adjEntries)
370 		{
371 			// coresponding adjacency entries differ by index modulo 2
372 			// the following conditions makes sure that each edge is
373 			// added only once to adjEntries
374 			if (activeNodes[adjG->m_edge->opposite(vG)])
375 			{
376 				if ((adjG->m_id & 1) == 0)
377 				{
378 					adjEdges.pushBack(adjG->m_edge);
379 				}
380 				if (adjG->m_edge->source() == vG) outCount++;
381 					else inCount++;
382 			}
383 		}
384 		v->m_indeg = inCount;
385 		v->m_outdeg = outCount;
386 	}
387 
388 	// create edges
389 	for (edge eG : adjEdges)
390 	{
391 		node v = mapNode[eG->source()];
392 		node w = mapNode[eG->target()];
393 
394 		AdjElement *adjSrc = new AdjElement(v);
395 
396 		v->adjEntries.pushBack(adjSrc);
397 
398 		AdjElement *adjTgt = new AdjElement(w);
399 
400 		w->adjEntries.pushBack(adjTgt);
401 
402 		adjSrc->m_twin = adjTgt;
403 		adjTgt->m_twin = adjSrc;
404 
405 		adjTgt->m_id = (adjSrc->m_id = m_edgeIdCount << 1) | 1;
406 		edge e = new EdgeElement(v,w,adjSrc,adjTgt,m_edgeIdCount++);
407 
408 		edges.pushBack(e);
409 
410 		mapEdge[eG] = adjSrc->m_edge = adjTgt->m_edge = e;
411 	}
412 
413 	// set size of associated arrays and reinitialize all (we have now a
414 	// completely new graph)
415 	reinitArrays();
416 
417 #ifdef OGDF_HEAVY_DEBUG
418 	consistencyCheck();
419 #endif
420 }
421 
newNode()422 node Graph::newNode()
423 {
424 	if (m_nodeIdCount == m_nodeArrayTableSize) {
425 		m_nodeArrayTableSize <<= 1;
426 		for(NodeArrayBase *nab : m_regNodeArrays)
427 			nab->enlargeTable(m_nodeArrayTableSize);
428 	}
429 
430 #ifdef OGDF_DEBUG
431 	node v = new NodeElement(this,m_nodeIdCount++);
432 #else
433 	node v = new NodeElement(m_nodeIdCount++);
434 #endif
435 
436 	nodes.pushBack(v);
437 
438 	// notify all registered observers
439 	for(GraphObserver *obs : m_regStructures)
440 		obs->nodeAdded(v);
441 
442 	return v;
443 }
444 
445 
446 //what about negative index numbers?
newNode(int index)447 node Graph::newNode(int index)
448 {
449 	if(index >= m_nodeIdCount) {
450 		m_nodeIdCount = index + 1;
451 
452 		if(index >= m_nodeArrayTableSize) {
453 			m_nodeArrayTableSize = nextPower2(m_nodeArrayTableSize, index + 1);
454 			for(NodeArrayBase *nab : m_regNodeArrays)
455 				nab->enlargeTable(m_nodeArrayTableSize);
456 		}
457 	}
458 
459 #ifdef OGDF_DEBUG
460 	node v = new NodeElement(this,index);
461 #else
462 	node v = new NodeElement(index);
463 #endif
464 
465 	nodes.pushBack(v);
466 
467 	// notify all registered observers
468 	for(GraphObserver *obs : m_regStructures)
469 		obs->nodeAdded(v);
470 
471 	return v;
472 }
473 
474 
pureNewNode()475 node Graph::pureNewNode()
476 {
477 #ifdef OGDF_DEBUG
478 	node v = new NodeElement(this,m_nodeIdCount++);
479 #else
480 	node v = new NodeElement(m_nodeIdCount++);
481 #endif
482 
483 	nodes.pushBack(v);
484 
485 	// notify all registered observers
486 	for(GraphObserver *obs : m_regStructures)
487 		obs->nodeAdded(v);
488 
489 	return v;
490 }
491 
492 
493 // IMPORTANT:
494 // The indices of the two adjacency entries pointing to an edge differ
495 // only in the last bit (adjSrc/2 == adjTgt/2)
496 //
497 // This can be useful sometimes in order to avoid visiting an edge twice.
createEdgeElement(node v,node w,adjEntry adjSrc,adjEntry adjTgt)498 edge Graph::createEdgeElement(node v, node w, adjEntry adjSrc, adjEntry adjTgt)
499 {
500 	if (m_edgeIdCount == m_edgeArrayTableSize) {
501 		m_edgeArrayTableSize <<= 1;
502 
503 		for(EdgeArrayBase *eab : m_regEdgeArrays)
504 			eab->enlargeTable(m_edgeArrayTableSize);
505 
506 		for(AdjEntryArrayBase *aab : m_regAdjArrays)
507 			aab->enlargeTable(m_edgeArrayTableSize << 1);
508 	}
509 
510 	adjTgt->m_id = (adjSrc->m_id = m_edgeIdCount << 1) | 1;
511 	edge e = new EdgeElement(v,w,adjSrc,adjTgt,m_edgeIdCount++);
512 	edges.pushBack(e);
513 
514 	// notify all registered observers
515 	for(GraphObserver *obs : m_regStructures)
516 		obs->edgeAdded(e);
517 
518 	return e;
519 }
520 
521 
newEdge(node v,node w,int index)522 edge Graph::newEdge(node v, node w, int index)
523 {
524 	OGDF_ASSERT(v != nullptr);
525 	OGDF_ASSERT(w != nullptr);
526 	OGDF_ASSERT(v->graphOf() == this);
527 	OGDF_ASSERT(w->graphOf() == this);
528 
529 	AdjElement *adjSrc = new AdjElement(v);
530 
531 	v->adjEntries.pushBack(adjSrc);
532 	v->m_outdeg++;
533 
534 	AdjElement *adjTgt = new AdjElement(w);
535 
536 	w->adjEntries.pushBack(adjTgt);
537 	w->m_indeg++;
538 
539 	adjSrc->m_twin = adjTgt;
540 	adjTgt->m_twin = adjSrc;
541 
542 	if(index >= m_edgeIdCount) {
543 		m_edgeIdCount = index + 1;
544 
545 		if(index >= m_edgeArrayTableSize) {
546 			m_edgeArrayTableSize = nextPower2(m_edgeArrayTableSize, index + 1);
547 
548 			for(EdgeArrayBase *eab : m_regEdgeArrays)
549 				eab->enlargeTable(m_edgeArrayTableSize);
550 
551 			for(AdjEntryArrayBase *aab : m_regAdjArrays)
552 				aab->enlargeTable(m_edgeArrayTableSize << 1);
553 		}
554 	}
555 
556 	adjTgt->m_id = (adjSrc->m_id = index/*m_edgeIdCount*/ << 1) | 1;
557 	edge e = new EdgeElement(v,w,adjSrc,adjTgt,index);
558 	edges.pushBack(e);
559 
560 	// notify all registered observers
561 	for(GraphObserver *obs : m_regStructures)
562 		obs->edgeAdded(e);
563 
564 	return adjSrc->m_edge = adjTgt->m_edge = e;
565 }
566 
567 
newEdge(node v,node w)568 edge Graph::newEdge(node v, node w)
569 {
570 	OGDF_ASSERT(v != nullptr);
571 	OGDF_ASSERT(w != nullptr);
572 	OGDF_ASSERT(v->graphOf() == this);
573 	OGDF_ASSERT(w->graphOf() == this);
574 
575 	AdjElement *adjSrc = new AdjElement(v);
576 
577 	v->adjEntries.pushBack(adjSrc);
578 	v->m_outdeg++;
579 
580 	AdjElement *adjTgt = new AdjElement(w);
581 
582 	w->adjEntries.pushBack(adjTgt);
583 	w->m_indeg++;
584 
585 	adjSrc->m_twin = adjTgt;
586 	adjTgt->m_twin = adjSrc;
587 
588 	edge e = createEdgeElement(v,w,adjSrc,adjTgt);
589 
590 	return adjSrc->m_edge = adjTgt->m_edge = e;
591 }
592 
593 
newEdge(adjEntry adjStart,adjEntry adjEnd,Direction dir)594 edge Graph::newEdge(adjEntry adjStart, adjEntry adjEnd, Direction dir)
595 {
596 	OGDF_ASSERT(adjStart != nullptr);
597 	OGDF_ASSERT(adjEnd != nullptr);
598 	OGDF_ASSERT(adjStart->graphOf() == this);
599 	OGDF_ASSERT(adjEnd->graphOf() == this);
600 
601 	node v = adjStart->theNode(), w = adjEnd->theNode();
602 
603 	AdjElement *adjTgt = new AdjElement(w);
604 	AdjElement *adjSrc = new AdjElement(v);
605 
606 	if(dir == Direction::after) {
607 		w->adjEntries.insertAfter(adjTgt,adjEnd);
608 		v->adjEntries.insertAfter(adjSrc,adjStart);
609 	} else {
610 		w->adjEntries.insertBefore(adjTgt,adjEnd);
611 		v->adjEntries.insertBefore(adjSrc,adjStart);
612 	}
613 
614 	w->m_indeg++;
615 	v->m_outdeg++;
616 
617 	adjSrc->m_twin = adjTgt;
618 	adjTgt->m_twin = adjSrc;
619 
620 	edge e = createEdgeElement(v,w,adjSrc,adjTgt);
621 
622 	return adjSrc->m_edge = adjTgt->m_edge = e;
623 }
624 
newEdge(node v,adjEntry adjEnd)625 edge Graph::newEdge(node v, adjEntry adjEnd)
626 {
627 	OGDF_ASSERT(v != nullptr);
628 	OGDF_ASSERT(adjEnd != nullptr);
629 	OGDF_ASSERT(v->graphOf() == this);
630 	OGDF_ASSERT(adjEnd->graphOf() == this);
631 
632 	node w = adjEnd->theNode();
633 
634 	AdjElement *adjTgt = new AdjElement(w);
635 
636 	w->adjEntries.insertAfter(adjTgt,adjEnd);
637 	w->m_indeg++;
638 
639 	AdjElement *adjSrc = new AdjElement(v);
640 
641 	v->adjEntries.pushBack(adjSrc);
642 	v->m_outdeg++;
643 
644 	adjSrc->m_twin = adjTgt;
645 	adjTgt->m_twin = adjSrc;
646 
647 	edge e = createEdgeElement(v,w,adjSrc,adjTgt);
648 
649 	return adjSrc->m_edge = adjTgt->m_edge = e;
650 }
651 
652 //copy of above function with edge ending at v
newEdge(adjEntry adjStart,node v)653 edge Graph::newEdge(adjEntry adjStart, node v)
654 {
655 	OGDF_ASSERT(v != nullptr);
656 	OGDF_ASSERT(adjStart != nullptr);
657 	OGDF_ASSERT(v->graphOf() == this);
658 	OGDF_ASSERT(adjStart->graphOf() == this);
659 
660 	node w = adjStart->theNode();
661 
662 	AdjElement *adjSrc = new AdjElement(w);
663 
664 	w->adjEntries.insertAfter(adjSrc, adjStart);
665 	w->m_outdeg++;
666 
667 	AdjElement *adjTgt = new AdjElement(v);
668 
669 	v->adjEntries.pushBack(adjTgt);
670 	v->m_indeg++;
671 
672 	adjSrc->m_twin = adjTgt;
673 	adjTgt->m_twin = adjSrc;
674 
675 	edge e = createEdgeElement(w,v,adjSrc,adjTgt);
676 
677 	return adjSrc->m_edge = adjTgt->m_edge = e;
678 }
679 
move(edge e,adjEntry adjSrc,Direction dirSrc,adjEntry adjTgt,Direction dirTgt)680 void Graph::move(edge e,
681 	adjEntry adjSrc,
682 	Direction dirSrc,
683 	adjEntry adjTgt,
684 	Direction dirTgt)
685 {
686 	OGDF_ASSERT(e->graphOf() == this);
687 	OGDF_ASSERT(adjSrc->graphOf() == this);
688 	OGDF_ASSERT(adjTgt->graphOf() == this);
689 	OGDF_ASSERT(adjSrc != e->m_adjSrc);
690 	OGDF_ASSERT(adjSrc != e->m_adjTgt);
691 	OGDF_ASSERT(adjTgt != e->m_adjSrc);
692 	OGDF_ASSERT(adjTgt != e->m_adjTgt);
693 
694 	node v = adjSrc->m_node, w = adjTgt->m_node;
695 	adjEntry adj1 = e->m_adjSrc, adj2 = e->m_adjTgt;
696 	e->m_src->adjEntries.move(adj1, v->adjEntries, adjSrc, dirSrc);
697 	e->m_tgt->adjEntries.move(adj2, w->adjEntries, adjTgt, dirTgt);
698 
699 	e->m_src->m_outdeg--;
700 	e->m_tgt->m_indeg--;
701 
702 	adj1->m_node = e->m_src = v;
703 	adj2->m_node = e->m_tgt = w;
704 
705 	v->m_outdeg++;
706 	w->m_indeg++;
707 }
708 
709 
moveTarget(edge e,node v)710 void Graph::moveTarget(edge e, node v)
711 {
712 	OGDF_ASSERT(e->graphOf() == this);
713 	OGDF_ASSERT(v->graphOf() == this);
714 
715 	adjEntry adj = e->m_adjTgt;
716 	e->m_tgt->adjEntries.move(adj,v->adjEntries);
717 
718 	e->m_tgt->m_indeg--;
719 	adj->m_node = e->m_tgt = v;
720 	v->m_indeg++;
721 }
722 
moveTarget(edge e,adjEntry adjTgt,Direction dir)723 void Graph::moveTarget(edge e, adjEntry adjTgt, Direction dir)
724 {
725 	node v = adjTgt->theNode();
726 
727 	OGDF_ASSERT(e->graphOf() == this);
728 	OGDF_ASSERT(v->graphOf() == this);
729 
730 	adjEntry adj = e->m_adjTgt;
731 	e->m_tgt->adjEntries.move(adj, v->adjEntries, adjTgt, dir);
732 
733 	e->m_tgt->m_indeg--;
734 	adj->m_node = e->m_tgt = v;
735 	v->m_indeg++;
736 }
737 
738 // By Leipert
moveSource(edge e,node v)739 void Graph::moveSource(edge e, node v)
740 {
741 	OGDF_ASSERT(e->graphOf() == this);
742 	OGDF_ASSERT(v->graphOf() == this);
743 
744 	adjEntry adj = e->m_adjSrc;
745 	e->m_src->adjEntries.move(adj,v->adjEntries);
746 
747 	e->m_src->m_outdeg--;
748 	adj->m_node = e->m_src = v;
749 	v->m_outdeg++;
750 }
751 
moveSource(edge e,adjEntry adjSrc,Direction dir)752 void Graph::moveSource(edge e, adjEntry adjSrc, Direction dir)
753 {
754 	node v = adjSrc->theNode();
755 
756 	OGDF_ASSERT(e->graphOf() == this);
757 	OGDF_ASSERT(v->graphOf() == this);
758 
759 	adjEntry adj = e->m_adjSrc;
760 	e->m_src->adjEntries.move(adj, v->adjEntries, adjSrc, dir);
761 
762 	e->m_src->m_outdeg--;
763 	adj->m_node = e->m_src = v;
764 	v->m_outdeg++;
765 }
766 
split(edge e)767 edge Graph::split(edge e)
768 {
769 	OGDF_ASSERT(e != nullptr);
770 	OGDF_ASSERT(e->graphOf() == this);
771 
772 	node u = newNode();
773 	u->m_indeg = u->m_outdeg = 1;
774 
775 	adjEntry adjTgt = new AdjElement(u);
776 	adjTgt->m_edge = e;
777 	adjTgt->m_twin = e->m_adjSrc;
778 	e->m_adjSrc->m_twin = adjTgt;
779 
780 	// adapt adjacency entry index to hold invariant
781 	adjTgt->m_id = e->m_adjTgt->m_id;
782 
783 	u->adjEntries.pushBack(adjTgt);
784 
785 	adjEntry adjSrc = new AdjElement(u);
786 	adjSrc->m_twin = e->m_adjTgt;
787 	u->adjEntries.pushBack(adjSrc);
788 
789 	int oldId = e->m_adjTgt->m_id;
790 	edge e2 = createEdgeElement(u,e->m_tgt,adjSrc,e->m_adjTgt);
791 	resetAdjEntryIndex(e->m_adjTgt->m_id,oldId);
792 
793 	e2->m_adjTgt->m_twin = adjSrc;
794 	e->m_adjTgt->m_edge = adjSrc->m_edge = e2;
795 
796 	e->m_tgt = u;
797 	e->m_adjTgt = adjTgt;
798 	return e2;
799 }
800 
801 
unsplit(node u)802 void Graph::unsplit(node u)
803 {
804 	edge eIn = u->firstAdj()->theEdge();
805 	edge eOut = u->lastAdj()->theEdge();
806 
807 	if (eIn->target() != u)
808 		std::swap(eIn,eOut);
809 
810 	unsplit(eIn,eOut);
811 }
812 
813 
814 
unsplit(edge eIn,edge eOut)815 void Graph::unsplit(edge eIn, edge eOut)
816 {
817 	node u = eIn->target();
818 
819 	// u must be a node with exactly one incoming edge eIn and one outgoing
820 	// edge eOut
821 	OGDF_ASSERT(u->graphOf() == this);
822 	OGDF_ASSERT(u->indeg() == 1);
823 	OGDF_ASSERT(u->outdeg() == 1);
824 	OGDF_ASSERT(eOut->source() == u);
825 
826 	// none of them is a self-loop!
827 	OGDF_ASSERT(!eIn->isSelfLoop());
828 	OGDF_ASSERT(!eOut->isSelfLoop());
829 
830 	// we reuse these adjacency entries
831 	adjEntry adjSrc = eIn ->m_adjSrc;
832 	adjEntry adjTgt = eOut->m_adjTgt;
833 
834 	eIn->m_tgt = eOut->m_tgt;
835 
836 	// adapt adjacency entry index to hold invariant
837 	resetAdjEntryIndex(eIn->m_adjTgt->m_id,adjTgt->m_id);
838 	adjTgt->m_id = eIn->m_adjTgt->m_id; // correct id of adjacency entry!
839 
840 	eIn->m_adjTgt = adjTgt;
841 
842 	adjSrc->m_twin = adjTgt;
843 	adjTgt->m_twin = adjSrc;
844 
845 	adjTgt->m_edge = eIn;
846 
847 	// notify all registered observers
848 	for(GraphObserver *obs : m_regStructures)
849 		obs->edgeDeleted(eOut);
850 	for(GraphObserver *obs : m_regStructures)
851 		obs->nodeDeleted(u);
852 
853 	// remove structures that are no longer used
854 	edges.del(eOut);
855 	nodes.del(u);
856 }
857 
858 
insert(const Graph & G,NodeArray<node> & nodeMap)859 void Graph::insert(const Graph &G, NodeArray<node> &nodeMap)
860 {
861 	for (node v : G.nodes) {
862 		nodeMap[v] = newNode();
863 	}
864 
865 	for (edge e: G.edges) {
866 		newEdge(nodeMap[e->source()], nodeMap[e->target()]);
867 	}
868 }
869 
870 
insert(const Graph & G)871 void Graph::insert(const Graph &G)
872 {
873 	NodeArray<node> nodeMap(G);
874 	insert(G, nodeMap);
875 }
876 
877 
delNode(node v)878 void Graph::delNode(node v)
879 {
880 	OGDF_ASSERT(v != nullptr);
881 	OGDF_ASSERT(v->graphOf() == this);
882 
883 	// notify all registered observers
884 	for (GraphObserver *obs : m_regStructures)
885 		obs->nodeDeleted(v);
886 
887 	internal::GraphList<AdjElement> &adjEdges = v->adjEntries;
888 	AdjElement *adj;
889 	while((adj = adjEdges.head()) != nullptr)
890 		delEdge(adj->m_edge);
891 
892 	nodes.del(v);
893 }
894 
895 
delEdge(edge e)896 void Graph::delEdge(edge e)
897 {
898 	OGDF_ASSERT(e != nullptr);
899 	OGDF_ASSERT(e->graphOf() == this);
900 
901 	// notify all registered observers
902 	for(GraphObserver *obs : m_regStructures)
903 		obs->edgeDeleted(e);
904 
905 	node src = e->m_src, tgt = e->m_tgt;
906 
907 	src->adjEntries.del(e->m_adjSrc);
908 	src->m_outdeg--;
909 	tgt->adjEntries.del(e->m_adjTgt);
910 	tgt->m_indeg--;
911 
912 	edges.del(e);
913 }
914 
915 
clear()916 void Graph::clear()
917 {
918 	// tell all structures to clear their graph-initialized data
919 	for(GraphObserver *obs : m_regStructures)
920 		obs->cleared();
921 
922 	for (node v = nodes.head(); v; v = v->succ()) {
923 		v->adjEntries.~GraphObjectContainer<AdjElement>();
924 	}
925 
926 	nodes.clear();
927 	edges.clear();
928 
929 	m_nodeIdCount = m_edgeIdCount = 0;
930 	m_nodeArrayTableSize = MIN_NODE_TABLE_SIZE;
931 	reinitArrays(false);
932 
933 #ifdef OGDF_HEAVY_DEBUG
934 	consistencyCheck();
935 #endif
936 }
937 
938 
reverseEdge(edge e)939 void Graph::reverseEdge(edge e)
940 {
941 	OGDF_ASSERT(e != nullptr);
942 	OGDF_ASSERT(e->graphOf() == this);
943 	node &src = e->m_src, &tgt = e->m_tgt;
944 
945 	std::swap(src,tgt);
946 	std::swap(e->m_adjSrc,e->m_adjTgt);
947 	src->m_outdeg++; src->m_indeg--;
948 	tgt->m_outdeg--; tgt->m_indeg++;
949 }
950 
951 
reverseAllEdges()952 void Graph::reverseAllEdges()
953 {
954 	for (edge e = edges.head(); e; e = e->succ())
955 		reverseEdge(e);
956 
957 #ifdef OGDF_HEAVY_DEBUG
958 	consistencyCheck();
959 #endif
960 }
961 
962 
reverseAdjEdges()963 void Graph::reverseAdjEdges()
964 {
965 	for(node v : nodes)
966 		reverseAdjEdges(v);
967 }
968 
969 
chooseNode(std::function<bool (node)> includeNode,bool isFastTest) const970 node Graph::chooseNode(std::function<bool(node)> includeNode, bool isFastTest) const
971 {
972 	return *chooseIteratorFrom<internal::GraphObjectContainer<NodeElement>, node>(
973 			const_cast<internal::GraphObjectContainer<NodeElement>&>(nodes),
974 			[&](const node &v) { return includeNode(v); },
975 			isFastTest
976 	);
977 }
978 
979 
chooseEdge(std::function<bool (edge)> includeEdge,bool isFastTest) const980 edge Graph::chooseEdge(std::function<bool(edge)> includeEdge, bool isFastTest) const
981 {
982 	return *chooseIteratorFrom<internal::GraphObjectContainer<EdgeElement>, edge>(
983 			const_cast<internal::GraphObjectContainer<EdgeElement>&>(edges),
984 			[&](const edge &e) { return includeEdge(e); },
985 			isFastTest
986 	);
987 }
988 
989 
searchEdge(node v,node w,bool directed) const990 edge Graph::searchEdge(node v, node w, bool directed) const
991 {
992 	OGDF_ASSERT(v != nullptr);
993 	OGDF_ASSERT(v->graphOf() == this);
994 	OGDF_ASSERT(w != nullptr);
995 	OGDF_ASSERT(w->graphOf() == this);
996 
997 	bool swapped = false;
998 	if (w->degree() < v->degree()) {
999 		std::swap(v,w);
1000 		swapped = true;
1001 	}
1002 
1003 	for(adjEntry adj : v->adjEntries) {
1004 		if (adj->twinNode() == w &&
1005 		    (!directed || swapped != adj->isSource())) {
1006 			return adj->theEdge();
1007 		}
1008 	}
1009 	return nullptr;
1010 }
1011 
1012 
restoreAllEdges()1013 void Graph::restoreAllEdges()
1014 {
1015 	while (!m_hiddenEdgeSets.empty()) {
1016 		HiddenEdgeSet *set = m_hiddenEdgeSets.popFrontRet();
1017 		set->restore();
1018 		set->m_graph = nullptr;
1019 	}
1020 }
1021 
1022 
genus() const1023 int Graph::genus() const
1024 {
1025 	if (empty()) return 0;
1026 
1027 	int nIsolated = 0;
1028 	for(node v : nodes)
1029 		if (v->degree() == 0) ++nIsolated;
1030 
1031 	NodeArray<int> component(*this);
1032 	int nCC = connectedComponents(*this,component);
1033 
1034 	AdjEntryArray<bool> visited(*this,false);
1035 	int nFaceCycles = 0;
1036 
1037 	for(node v : nodes) {
1038 		for(adjEntry adj1 : v->adjEntries) {
1039 			if (visited[adj1]) continue;
1040 
1041 			adjEntry adj = adj1;
1042 			do {
1043 				visited[adj] = true;
1044 				adj = adj->faceCycleSucc();
1045 			} while (adj != adj1);
1046 
1047 			++nFaceCycles;
1048 		}
1049 	}
1050 
1051 	return (numberOfEdges() - numberOfNodes() - nIsolated - nFaceCycles + 2*nCC) / 2;
1052 }
1053 
1054 
registerArray(NodeArrayBase * pNodeArray) const1055 ListIterator<NodeArrayBase*> Graph::registerArray(
1056 	NodeArrayBase *pNodeArray) const
1057 {
1058 #ifndef OGDF_MEMORY_POOL_NTS
1059 	lock_guard<mutex> guard(m_mutexRegArrays);
1060 #endif
1061 	return m_regNodeArrays.pushBack(pNodeArray);
1062 }
1063 
1064 
registerArray(EdgeArrayBase * pEdgeArray) const1065 ListIterator<EdgeArrayBase*> Graph::registerArray(
1066 	EdgeArrayBase *pEdgeArray) const
1067 {
1068 #ifndef OGDF_MEMORY_POOL_NTS
1069 	lock_guard<mutex> guard(m_mutexRegArrays);
1070 #endif
1071 	return m_regEdgeArrays.pushBack(pEdgeArray);
1072 }
1073 
1074 
registerArray(AdjEntryArrayBase * pAdjArray) const1075 ListIterator<AdjEntryArrayBase*> Graph::registerArray(
1076 	AdjEntryArrayBase *pAdjArray) const
1077 {
1078 #ifndef OGDF_MEMORY_POOL_NTS
1079 	lock_guard<mutex> guard(m_mutexRegArrays);
1080 #endif
1081 	return m_regAdjArrays.pushBack(pAdjArray);
1082 }
1083 
registerStructure(GraphObserver * pStructure) const1084 ListIterator<GraphObserver*> Graph::registerStructure(
1085 	GraphObserver *pStructure) const
1086 {
1087 #ifndef OGDF_MEMORY_POOL_NTS
1088 	lock_guard<mutex> guard(m_mutexRegArrays);
1089 #endif
1090 	return m_regStructures.pushBack(pStructure);
1091 }
1092 
1093 
unregisterArray(ListIterator<NodeArrayBase * > it) const1094 void Graph::unregisterArray(ListIterator<NodeArrayBase*> it) const
1095 {
1096 #ifndef OGDF_MEMORY_POOL_NTS
1097 	lock_guard<mutex> guard(m_mutexRegArrays);
1098 #endif
1099 	m_regNodeArrays.del(it);
1100 }
1101 
1102 
unregisterArray(ListIterator<EdgeArrayBase * > it) const1103 void Graph::unregisterArray(ListIterator<EdgeArrayBase*> it) const
1104 {
1105 #ifndef OGDF_MEMORY_POOL_NTS
1106 	lock_guard<mutex> guard(m_mutexRegArrays);
1107 #endif
1108 	m_regEdgeArrays.del(it);
1109 }
1110 
1111 
unregisterArray(ListIterator<AdjEntryArrayBase * > it) const1112 void Graph::unregisterArray(ListIterator<AdjEntryArrayBase*> it) const
1113 {
1114 #ifndef OGDF_MEMORY_POOL_NTS
1115 	lock_guard<mutex> guard(m_mutexRegArrays);
1116 #endif
1117 	m_regAdjArrays.del(it);
1118 }
1119 
unregisterStructure(ListIterator<GraphObserver * > it) const1120 void Graph::unregisterStructure(ListIterator<GraphObserver*> it) const
1121 {
1122 #ifndef OGDF_MEMORY_POOL_NTS
1123 	lock_guard<mutex> guard(m_mutexRegArrays);
1124 #endif
1125 	m_regStructures.del(it);
1126 }
1127 
resetTableSizes()1128 void Graph::resetTableSizes()
1129 {
1130 	m_nodeArrayTableSize = nextPower2(MIN_NODE_TABLE_SIZE, m_nodeIdCount + 1);
1131 	m_edgeArrayTableSize = nextPower2(MIN_EDGE_TABLE_SIZE, m_edgeIdCount + 1);
1132 }
1133 
reinitArrays(bool doResetTableSizes)1134 void Graph::reinitArrays(bool doResetTableSizes)
1135 {
1136 	if(doResetTableSizes) {
1137 		resetTableSizes();
1138 	}
1139 
1140 	for(NodeArrayBase *nab : m_regNodeArrays)
1141 		nab->reinit(m_nodeArrayTableSize);
1142 
1143 	for(EdgeArrayBase *eab : m_regEdgeArrays)
1144 		eab->reinit(m_edgeArrayTableSize);
1145 
1146 	for(AdjEntryArrayBase *aab : m_regAdjArrays)
1147 		aab->reinit(m_edgeArrayTableSize << 1);
1148 }
1149 
1150 
reinitStructures()1151 void Graph::reinitStructures()
1152 {
1153 	// is there a challenge?
1154 	for(GraphObserver *obs : m_regStructures)
1155 		obs->reInit();
1156 }
1157 
1158 
resetAdjEntryIndex(int newIndex,int oldIndex)1159 void Graph::resetAdjEntryIndex(int newIndex, int oldIndex)
1160 {
1161 	for(AdjEntryArrayBase *aab : m_regAdjArrays)
1162 		aab->resetIndex(newIndex,oldIndex);
1163 }
1164 
1165 
1166 #ifdef OGDF_DEBUG
consistencyCheck() const1167 void Graph::consistencyCheck() const
1168 {
1169 	int n = 0;
1170 	for(node v : nodes) {
1171 		OGDF_ASSERT(v->graphOf() == this);
1172 
1173 		n++;
1174 		int in = 0, out = 0;
1175 
1176 		for(adjEntry adj : v->adjEntries) {
1177 			edge e = adj->m_edge;
1178 			OGDF_ASSERT(adj->m_twin->m_edge == e);
1179 
1180 			if (e->m_adjSrc == adj) {
1181 				out++;
1182 			} else {
1183 				OGDF_ASSERT(e->m_adjTgt == adj);
1184 				in++;
1185 			}
1186 
1187 			OGDF_ASSERT(adj->m_node == v);
1188 			OGDF_ASSERT(adj->graphOf() == this);
1189 		}
1190 
1191 		OGDF_ASSERT(v->m_indeg == in);
1192 		OGDF_ASSERT(v->m_outdeg == out);
1193 	}
1194 
1195 	OGDF_ASSERT(n == nodes.size());
1196 
1197 	int m = 0;
1198 	for(edge e : edges) {
1199 		m++;
1200 		OGDF_ASSERT(e->graphOf() == this);
1201 		OGDF_ASSERT(e->m_adjSrc != e->m_adjTgt);
1202 		OGDF_ASSERT(e->m_adjSrc->m_edge == e);
1203 		OGDF_ASSERT(e->m_adjTgt->m_edge == e);
1204 		OGDF_ASSERT(e->m_adjSrc->m_node == e->m_src);
1205 		OGDF_ASSERT(e->m_adjTgt->m_node == e->m_tgt);
1206 	}
1207 
1208 	OGDF_ASSERT(m == edges.size());
1209 }
1210 #endif
1211 
1212 
resetEdgeIdCount(int maxId)1213 void Graph::resetEdgeIdCount(int maxId)
1214 {
1215 	m_edgeIdCount = maxId+1;
1216 
1217 #ifdef OGDF_HEAVY_DEBUG
1218 	for(edge e : edges)
1219 	{
1220 		// if there is an edge with higer index than maxId, we cannot
1221 		// set the edge id count to maxId+1
1222 		OGDF_ASSERT(e->index() <= maxId);
1223 	}
1224 #endif
1225 }
1226 
1227 
splitNode(adjEntry adjStartLeft,adjEntry adjStartRight)1228 node Graph::splitNode(adjEntry adjStartLeft, adjEntry adjStartRight)
1229 {
1230 	OGDF_ASSERT(adjStartLeft != nullptr);
1231 	OGDF_ASSERT(adjStartRight != nullptr);
1232 	OGDF_ASSERT(adjStartLeft->graphOf() == this);
1233 	OGDF_ASSERT(adjStartRight->graphOf() == this);
1234 	OGDF_ASSERT(adjStartLeft->theNode() == adjStartRight->theNode());
1235 
1236 	node w = newNode();
1237 
1238 	adjEntry adj, adjSucc;
1239 	for(adj = adjStartRight; adj != adjStartLeft; adj = adjSucc) {
1240 		adjSucc = adj->cyclicSucc();
1241 		moveAdj(adj,w);
1242 	}
1243 
1244 	newEdge(adjStartLeft, adjStartRight, Direction::before);
1245 
1246 	return w;
1247 }
1248 
1249 
contract(edge e)1250 node Graph::contract(edge e)
1251 {
1252 	adjEntry adjSrc = e->adjSource();
1253 	adjEntry adjTgt = e->adjTarget();
1254 	node v = e->source();
1255 	node w = e->target();
1256 
1257 	adjEntry adjNext;
1258 	for (adjEntry adj = adjTgt->cyclicSucc(); adj != adjTgt; adj = adjNext) {
1259 		adjNext = adj->cyclicSucc();
1260 		if (adj->twinNode() == v) {
1261 			continue;
1262 		}
1263 
1264 		edge eAdj = adj->theEdge();
1265 		if (w == eAdj->source()) {
1266 			moveSource(eAdj, adjSrc, Direction::before);
1267 		} else {
1268 			moveTarget(eAdj, adjSrc, Direction::before);
1269 		}
1270 	}
1271 
1272 	delNode(adjTgt->theNode());
1273 
1274 	return v;
1275 }
1276 
1277 
moveAdj(adjEntry adj,node w)1278 void Graph::moveAdj(adjEntry adj, node w)
1279 {
1280 	node v = adj->m_node;
1281 
1282 	v->adjEntries.move(adj,w->adjEntries);
1283 	adj->m_node = w;
1284 
1285 	edge e = adj->m_edge;
1286 	if(v == e->m_src) {
1287 		--v->m_outdeg;
1288 		e->m_src = w;
1289 		++w->m_outdeg;
1290 	} else {
1291 		--v->m_indeg;
1292 		e->m_tgt = w;
1293 		++w->m_indeg;
1294 	}
1295 }
1296 
1297 
operator <<(std::ostream & os,ogdf::node v)1298 std::ostream &operator<<(std::ostream &os, ogdf::node v)
1299 {
1300 	if (v) os << v->index(); else os << "nil";
1301 	return os;
1302 }
1303 
operator <<(std::ostream & os,ogdf::edge e)1304 std::ostream &operator<<(std::ostream &os, ogdf::edge e)
1305 {
1306 	if (e) os << "(" << e->source() << "," << e->target() << ")";
1307 	else os << "nil";
1308 	return os;
1309 }
1310 
operator <<(std::ostream & os,ogdf::adjEntry adj)1311 std::ostream &operator<<(std::ostream &os, ogdf::adjEntry adj)
1312 {
1313 	if (adj) {
1314 		ogdf::edge e = adj->theEdge();
1315 		if (adj == e->adjSource())
1316 			os << e->source() << "->" << e->target();
1317 		else
1318 			os << e->target() << "->" << e->source();
1319 	} else os << "nil";
1320 	return os;
1321 }
1322 
1323 
CCsInfo(const Graph & G)1324 Graph::CCsInfo::CCsInfo(const Graph& G)
1325 	: m_graph(&G), m_nodes(G.numberOfNodes()), m_edges(G.numberOfEdges())
1326 {
1327 	NodeArray<int> component(G,-1);
1328 
1329 	ArrayBuffer<node> S;
1330 	SListPure<int> startNodes;
1331 	SListPure<int> startEdges;
1332 	int nComponent = 0, n = 0, m = 0;
1333 
1334 	for(node v : G.nodes) {
1335 		if (component[v] != -1) continue;
1336 
1337 		S.push(v);
1338 		component[v] = nComponent;
1339 
1340 		while(!S.empty()) {
1341 			node w = S.popRet();
1342 			m_nodes[n++] = w;
1343 
1344 			for(adjEntry adj : w->adjEntries) {
1345 				if((adj->index() & 1) == 0)
1346 					m_edges[m++] = adj->theEdge();
1347 				node x = adj->twinNode();
1348 				if (component[x] == -1) {
1349 					component[x] = nComponent;
1350 					S.push(x);
1351 				}
1352 			}
1353 		}
1354 
1355 		++nComponent;
1356 		startNodes.pushBack(n);
1357 		startEdges.pushBack(m);
1358 	}
1359 
1360 	m_startNode.init(nComponent+1);
1361 	m_startNode[0] = 0;
1362 
1363 	int i = 1;
1364 	for (int j : startNodes)
1365 		m_startNode[i++] = j;
1366 
1367 
1368 	m_startEdge.init(nComponent+1);
1369 	m_startEdge[0] = 0;
1370 
1371 	i = 1;
1372 	for(int j : startEdges)
1373 		m_startEdge[i++] = j;
1374 
1375 	m_numCC = nComponent;
1376 }
1377 
hide(edge e)1378 void Graph::HiddenEdgeSet::hide(edge e)
1379 {
1380 	OGDF_ASSERT(m_graph == e->graphOf());
1381 	OGDF_ASSERT(!e->m_hidden);
1382 
1383 	node src = e->m_src, tgt = e->m_tgt;
1384 
1385 	src->adjEntries.delPure(e->m_adjSrc);
1386 	src->m_outdeg--;
1387 	tgt->adjEntries.delPure(e->m_adjTgt);
1388 	tgt->m_indeg--;
1389 
1390 	m_graph->edges.move(e, m_edges);
1391 #ifdef OGDF_DEBUG
1392 	e->m_hidden = true;
1393 #endif
1394 }
1395 
restore(edge e)1396 void Graph::HiddenEdgeSet::restore(edge e)
1397 {
1398 	OGDF_ASSERT(m_graph == e->graphOf());
1399 	OGDF_ASSERT(e->m_hidden);
1400 	OGDF_ASSERT(!m_edges.empty());
1401 
1402 	node v = e->m_src;
1403 	v->adjEntries.pushBack(e->m_adjSrc);
1404 	++v->m_outdeg;
1405 
1406 	node w = e->m_tgt;
1407 	w->adjEntries.pushBack(e->m_adjTgt);
1408 	++w->m_indeg;
1409 
1410 	m_edges.move(e, m_graph->edges);
1411 #ifdef OGDF_DEBUG
1412 	e->m_hidden = false;
1413 #endif
1414 }
1415 
restore()1416 void Graph::HiddenEdgeSet::restore()
1417 {
1418 	OGDF_ASSERT(m_graph != nullptr);
1419 
1420 	while (!m_edges.empty()) {
1421 		restore(m_edges.head());
1422 	}
1423 }
1424 
size()1425 int Graph::HiddenEdgeSet::size()
1426 {
1427 	return m_edges.size();
1428 }
1429 
operator <<(std::ostream & os,const Graph::EdgeType & et)1430 std::ostream &operator<<(std::ostream &os, const Graph::EdgeType &et) {
1431 	switch (et) {
1432 		case Graph::EdgeType::association:    os << "association";    break;
1433 		case Graph::EdgeType::generalization: os << "generalization"; break;
1434 		case Graph::EdgeType::dependency:     os << "dependency";     break;
1435 	}
1436 	return os;
1437 }
1438 
1439 }
1440