1 /** \file
2  * \brief Implementation of Block and BlockOrder classes
3  *
4  * \author Paweł Schmidt, 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/layered/BlockOrder.h>
33 
34 namespace ogdf {
35 
BlockOrder(Hierarchy & hierarchy,bool longEdgesOnly)36 BlockOrder::BlockOrder(Hierarchy& hierarchy, bool longEdgesOnly)
37   : m_GC(hierarchy.operator const ogdf::GraphCopy &().original())
38   , m_ranks(m_GC,0)
39   , m_storedPerm()
40   , m_currentPerm()
41   , m_bestPerm()
42   , m_currentPermInv()
43   , m_storedCrossings(std::numeric_limits<int>::max())
44   , m_bestCrossings(std::numeric_limits<int>::max())
45   , m_Blocks()
46   , m_NodeBlocks(m_GC,nullptr)
47   , m_EdgeBlocks(m_GC,nullptr)
48   , m_isActiveEdge(m_GC,false)
49   , m_activeBlocksCount(0)
50   , m_hierarchy(hierarchy)
51   , m_levels(0,-1,nullptr)
52   , m_verticalStepsBound(0)
53 {
54 	doInit(longEdgesOnly);
55 }
56 
57 
doInit(bool longEdgesOnly)58 void BlockOrder::doInit(bool longEdgesOnly)
59 {
60 	const GraphCopy &GC = m_hierarchy;
61 	NodeArray<bool> nodesInCC(m_GC,false);
62 
63 	unsigned int countBlocks = 0;
64 
65 	int minLvl = 0;
66 	int maxLvl = m_hierarchy.maxRank();
67 
68 	m_nNodesOnLvls.init(minLvl, maxLvl, 0);
69 
70 	// one block for every node
71 	for(node v : GC.nodes) {
72 		//m_GC may contain nodes from another CC
73 		if (GC.original(v) != nullptr) {
74 			m_ranks[GC.original(v)] = m_hierarchy.rank(v);
75 			nodesInCC[GC.original(v)] = true;
76 			++countBlocks;
77 			m_nNodesOnLvls[m_hierarchy.rank(v)] += 1;
78 		}
79 	}
80 
81 	//one block for every long edge
82 	for(edge e : m_GC.edges) {
83 		node src = e->source();
84 		node tgt = e->target();
85 
86 		if (nodesInCC[src] && nodesInCC[tgt]) {
87 			int top = min(m_ranks[src], m_ranks[tgt]);
88 			int bot = max(m_ranks[src], m_ranks[tgt]);
89 			if (top + 1 < bot || !longEdgesOnly) {
90 				++countBlocks;
91 			}
92 		}
93 	}
94 
95 	//m_blocksCount = countBlocks;
96 
97 	m_Blocks.init(countBlocks);
98 	m_storedPerm.init(countBlocks);
99 	m_bestPerm.init(countBlocks);
100 	m_currentPerm.init(countBlocks);
101 	m_currentPermInv.init(countBlocks);
102 
103 	int i = 0;
104 	for(node v : GC.nodes) {
105 		node vOrig = GC.original(v);
106 		if (vOrig != nullptr) {
107 			m_Blocks[i] = m_NodeBlocks[vOrig] = new Block(vOrig);
108 			m_Blocks[i]->m_index = i;
109 			m_Blocks[i]->m_lower = m_Blocks[i]->m_upper = m_ranks[vOrig];
110 			++i;
111 			m_activeBlocksCount += 1;
112 		}
113 	}
114 
115 	for(edge e : m_GC.edges) {
116 		node src = e->source();
117 		node tgt = e->target();
118 
119 		if (nodesInCC[src] && nodesInCC[tgt]) {
120 			int top = min(m_ranks[src], m_ranks[tgt]);
121 			int bot = max(m_ranks[src], m_ranks[tgt]);
122 
123 			if (top + 1 < bot || !longEdgesOnly) {
124 				m_Blocks[i] = m_EdgeBlocks[e] = new Block(e);
125 				m_Blocks[i]->m_index = i;
126 				m_Blocks[i]->m_upper = top + 1;
127 				m_Blocks[i]->m_lower = bot - 1;
128 				++i;
129 			}
130 			if (top + 1 < bot) {
131 				m_isActiveEdge[e] = true;
132 				m_activeBlocksCount += 1;
133 			} else
134 				m_isActiveEdge[e] = false;
135 		}
136 	}
137 }
138 
139 
Block(edge e)140 Block::Block(edge e)
141 : m_NeighboursIncoming(1)
142 , m_InvertedIncoming(1)
143 , m_NeighboursOutgoing(1)
144 , m_InvertedOutgoing(1)
145 , m_Edge(e)
146 , m_isEdgeBlock(true)
147 , m_isNodeBlock(false)
148 { }
149 
150 
Block(node v)151 Block::Block(node v)
152 : m_NeighboursIncoming(v->indeg())
153 , m_InvertedIncoming(v->indeg())
154 , m_NeighboursOutgoing(v->outdeg())
155 , m_InvertedOutgoing(v->outdeg())
156 , m_Node(v)
157 , m_isEdgeBlock(false)
158 , m_isNodeBlock(true)
159 { }
160 
161 
sortAdjacencies()162 void BlockOrder::sortAdjacencies()
163 {
164 
165 	Block *processedBlock; // A in paper
166 
167 	EdgeArray<int> p(m_GC, 0);  // array P in paper
168 	EdgeArray<int> longEdgeP(m_GC, 0); // additional P for long edges
169 	// explanation:
170 	// Bachmaier et al. in their paper convert long edge u ---> v to three blocks and two edges: u -> [block for edge] -> v.
171 	// I decided to use edges and vertices from original graph (thus I am able to use Node- and EdgeArrays).
172 	// It implies that (block for a long) edge u ---> v is traversed four times
173 	// (i.e. twice when blocks for vertices u and v are processed, and then twice, when block for this edge is processed)
174 	// and since that, some information can be overwritten and lost.
175 	// To avoid this, for any long edge u--->v , array p stores information about source vertex u, and longEdgeP stores information about target vertex v
176 	// Later an attempt to delete this array can be made since long edge block have exactly one neighbour incoming and one outgoing.
177 
178 	//Array to store number of items inserted to arrays of neighbours in N+
179 	// These arrays store next free position in arrays N+ and  N-
180 	Array<int> NPlusItemsCount(0, m_Blocks.high(), 0);
181 	Array<int> NMinusItemsCount(0, m_Blocks.high(), 0);
182 
183 	// foreach A in B
184 	for (int i = 0; i < m_activeBlocksCount; ++i) {
185 		processedBlock = m_Blocks[m_currentPermInv[i]];
186 
187 		if (processedBlock->isVertexBlock()) {
188 			node v = processedBlock->m_Node;
189 
190 			//foreach s in { (u,v) in E' | v=upper(A)}
191 			for(adjEntry adj : v->adjEntries) {
192 				edge e = adj->theEdge();
193 				if (v == e->target()) {
194 					// if e is a short edge
195 					if (!m_isActiveEdge[e]) {
196 
197 						node u = e->source();
198 						Block *blockOfU = m_NodeBlocks[u];
199 
200 						// insert v at the next free position j of N+[u]
201 						int j = NPlusItemsCount[blockOfU->m_index];
202 						NPlusItemsCount [blockOfU->m_index] += 1;
203 						blockOfU->m_NeighboursOutgoing[j] = processedBlock->m_index;
204 
205 
206 						if (m_currentPerm[processedBlock->m_index] < m_currentPerm[blockOfU->m_index]) {
207 							//first traversal of e
208 							p[e] = j;
209 						} else {
210 							//second traversal of e
211 							blockOfU->m_InvertedOutgoing[j] = p[e];
212 							processedBlock->m_InvertedIncoming[p[e]] = j;
213 						}
214 					} else {
215 						// e is a long edge
216 						Block *blockOfU = m_EdgeBlocks[e];
217 
218 						// insert v at the next free position j of N+[u]
219 						int j = NPlusItemsCount[blockOfU->m_index];
220 						NPlusItemsCount[blockOfU->m_index] += 1;
221 						blockOfU->m_NeighboursOutgoing[j] = processedBlock->m_index;
222 
223 						// here we count "edges" outgoing from block u
224 						// thus we should use longEdgeP
225 						if (m_currentPerm[processedBlock->m_index] < m_currentPerm[blockOfU ->m_index]) {
226 							//first traversal of e
227 							longEdgeP[e] = j;
228 						} else {
229 							//second traversal of e
230 							blockOfU->m_InvertedOutgoing[j] = longEdgeP[e];
231 							processedBlock->m_InvertedIncoming[longEdgeP[e]] = j;
232 						}
233 					}
234 				}
235 			}
236 
237 			node w = processedBlock->m_Node;
238 			// foreach s in { (w,x) in E' | w = lower(A) }
239 			for(adjEntry adj : w->adjEntries) {
240 				edge e = adj->theEdge();
241 				if (w == e->source()) {
242 					// if e is a short edge
243 					if (!m_isActiveEdge[e]) {
244 
245 						node x = e->target();
246 						Block *blockOfX = m_NodeBlocks[x];
247 
248 						// insert w at the next free position j of N-[x]
249 						int j = NMinusItemsCount[blockOfX->m_index];
250 						NMinusItemsCount[blockOfX->m_index] += 1;
251 						blockOfX->m_NeighboursIncoming[j] = processedBlock->m_index;
252 
253 						if (m_currentPerm[processedBlock->m_index] < m_currentPerm[blockOfX->m_index]) {
254 							// first traversal of e
255 							p[e] = j;
256 						} else {
257 							//second traversal of e
258 							blockOfX->m_InvertedIncoming[j] = p[e];
259 							processedBlock->m_InvertedOutgoing [p[e]] = j;
260 						}
261 					} else {
262 						// e is a long edge
263 						Block *blockOfX = m_EdgeBlocks[e];
264 
265 						// insert v at the next free position j of N-(x)
266 						int j = NMinusItemsCount[blockOfX->m_index];
267 						NMinusItemsCount[blockOfX->m_index] += 1;
268 						blockOfX->m_NeighboursIncoming[j] = processedBlock->m_index;
269 
270 						// here we count "edges" incoming to edge block
271 						// thus we use p instead of LongEdgeP
272 
273 						if (m_currentPerm[processedBlock->m_index] < m_currentPerm[blockOfX->m_index]) {
274 							//first traversal of e
275 							p[e] = j;
276 						} else {
277 							//second traversal of e
278 							blockOfX->m_InvertedIncoming[j] = p[e];
279 							processedBlock->m_InvertedOutgoing[p[e]] = j;
280 						}
281 					}
282 				}
283 			}
284 		}
285 
286 		if (processedBlock->isEdgeBlock()) {
287 
288 			edge e = processedBlock->m_Edge;
289 
290 			node u = e->source();
291 			node x = e->target();
292 
293 			Block *blockOfU = m_NodeBlocks[u];
294 			Block *blockOfX = m_NodeBlocks[x];
295 
296 
297 			// first foreach loop
298 			// edge incoming to block
299 			{
300 				// insert v at the next free position j of N+[u]
301 				int j = NPlusItemsCount[blockOfU->m_index];
302 				NPlusItemsCount[blockOfU->m_index] += 1;
303 				blockOfU->m_NeighboursOutgoing[j] = processedBlock->m_index;
304 
305 
306 				if (m_currentPerm[processedBlock->m_index] < m_currentPerm[blockOfU->m_index]) {
307 					// first traversal of e
308 					p[e] = j;
309 				} else {
310 					// second traversal of e
311 					blockOfU->m_InvertedOutgoing[j] = p[e];
312 					processedBlock->m_InvertedIncoming[p[e]] = j;
313 				}
314 			}
315 
316 			// second foreach loop
317 			// edge outgoing from block
318 			{
319 				// insert w at the next free position j of N-[x]
320 
321 				int j = NMinusItemsCount[blockOfX->m_index];
322 				NMinusItemsCount[blockOfX->m_index] += 1;
323 				blockOfX->m_NeighboursIncoming[j] = processedBlock->m_index ;
324 
325 				if (m_currentPerm[processedBlock->m_index] < m_currentPerm[blockOfX->m_index]) {
326 					//first traversal of e
327 					longEdgeP[e] = j;
328 				} else {
329 					//second traversal of e
330 					blockOfX->m_InvertedIncoming[j] = longEdgeP[e];
331 					processedBlock->m_InvertedOutgoing[longEdgeP[e]] = j;
332 				}
333 			}
334 		}
335 	}
336 }
337 
deconstruct()338 void BlockOrder::deconstruct()
339 {
340 	for (auto &elem : m_Blocks) {
341 		delete elem;
342 	}
343 	for (auto &elem : m_levels) {
344 		delete elem;
345 	}
346 }
347 
348 
updateAdjacencies(Block * blockOfA,Block * blockOfB,Direction d)349 void BlockOrder::updateAdjacencies(Block *blockOfA, Block *blockOfB, Direction d)
350 {
351 	Array<int> &NdA = (d == Direction::Minus) ? blockOfA->m_NeighboursIncoming
352 	                                          : blockOfA->m_NeighboursOutgoing;
353 	Array<int> &IdA = (d == Direction::Minus) ? blockOfA->m_InvertedIncoming
354 	                                          : blockOfA->m_InvertedOutgoing;
355 	Array<int> &NdB = (d == Direction::Minus) ? blockOfB->m_NeighboursIncoming
356 	                                          : blockOfB->m_NeighboursOutgoing;
357 	Array<int> &IdB = (d == Direction::Minus) ? blockOfB->m_InvertedIncoming
358 	                                          : blockOfB->m_InvertedOutgoing;
359 
360 	int i = 0, j = 0;
361 
362 	int r = NdA.size();
363 	int s = NdB.size();
364 
365 	while (i < r && j < s) {
366 		// if pi (block(xi)) < pi(block (yj))
367 		if (m_currentPerm[NdA[i]] < m_currentPerm[NdB[j]])
368 			++i;
369 		else if (m_currentPerm[NdA[i]] > m_currentPerm[NdB[j]])
370 			++j;
371 		else {
372 			Block *z = m_Blocks[NdA[i]]; // = yj;
373 			if (d == Direction::Plus) {
374 
375 				z->m_NeighboursIncoming.swap(IdA[i], IdB[j]);
376 				z->m_InvertedIncoming.swap(IdA[i], IdB[j]);
377 			} else {
378 				z->m_NeighboursOutgoing.swap(IdA[i], IdB[j]);
379 				z->m_InvertedOutgoing.swap(IdA[i], IdB[j]);
380 			}
381 			IdA[i] +=  1;
382 			IdB[j] += -1;
383 			++i; ++j;
384 		}
385 	}
386 }
387 
388 
uswap(Block * blockOfA,Block * blockOfB,Direction d,int level)389 int BlockOrder::uswap(Block *blockOfA, Block *blockOfB, Direction d, int level)
390 {
391 	Array<int> &NdA = (d == Direction::Minus) ? blockOfA->m_NeighboursIncoming
392 	                                          : blockOfA->m_NeighboursOutgoing;
393 	Array<int> &NdB = (d == Direction::Minus) ? blockOfB->m_NeighboursIncoming
394 	                                          : blockOfB->m_NeighboursOutgoing;
395 
396 	int nextLevel;
397 	if (d == Direction::Minus)
398 		for (nextLevel = level - 1; m_nNodesOnLvls[nextLevel] == 0; --nextLevel);
399 	else
400 		for (nextLevel = level + 1; m_nNodesOnLvls[nextLevel] == 0; ++nextLevel);
401 
402 
403 	int c = 0;
404 	int i = 0;
405 	int j = 0;
406 
407 	int r = NdA.size();
408 	int s = NdB.size();
409 
410 	if ((d == Direction::Minus && nextLevel < blockOfA->m_upper && nextLevel < blockOfB->m_upper)
411 	 || (d == Direction::Plus  && nextLevel > blockOfA->m_lower && nextLevel > blockOfB->m_lower)) {
412 		while (i < r && j < s) {
413 			if (m_currentPerm[NdA[i]] < m_currentPerm[NdB[j]]) {
414 				c = c + (s - j);
415 				i += 1;
416 			} else if (m_currentPerm[NdA[i]] > m_currentPerm[NdB[j]]) {
417 				c = c - (r - i);
418 				j += 1;
419 			} else {
420 				c = c + (s - j) - (r - i);
421 				i += 1;
422 				j += 1;
423 			}
424 		}
425 	} else
426 	if ((d == Direction::Minus && nextLevel >= blockOfA->m_upper)
427 	 || (d == Direction::Plus  && nextLevel <= blockOfA->m_lower)) {
428 		// edge in block A is an internal edge
429 		int pi = m_currentPerm[blockOfA->m_index];
430 		for (j = 0; j < s && m_currentPerm[NdB[j]] < pi ;)
431 			++j;
432 		// j is the number of blocks on level level that are neighbours of b and are before a in current permutation
433 		c = s - 2 * j;
434 	} else {
435 		// edge in block B is an internal edge
436 		int pi = m_currentPerm[blockOfB->m_index];
437 		for (i = 0 ; i < r && m_currentPerm[NdA[i]] < pi;)
438 			++i;
439 		// j is the number of blocks on level level that are neighbours of a and are before b in current permutation
440 		c = 2 * i - s;
441 	}
442 	return c;
443 }
444 
445 
siftingSwap(Block * blockOfA,Block * blockOfB)446 int BlockOrder::siftingSwap(Block *blockOfA, Block *blockOfB)
447 {
448 	int Delta = 0;
449 
450 	if (blockOfA->m_upper > blockOfB->m_lower || blockOfA->m_lower < blockOfB->m_upper) {
451 		// empty intersection of A.levels and B.levels - no change in number of crossings
452 		Delta = 0;
453 	} else {
454 		// intersection of A.levels and B.levels is nonempty
455 		// top = max(upper(A),upper(B))
456 		int top = (blockOfA->m_upper > blockOfB->m_upper) ? blockOfA->m_upper
457 		                                                  : blockOfB->m_upper;
458 		// bottom = min(lower(A),lower(B))
459 		int bottom = (blockOfA->m_lower < blockOfB->m_lower) ? blockOfA->m_lower
460 		                                                     : blockOfB->m_lower;
461 
462 		Delta += uswap(blockOfA, blockOfB, Direction::Minus, top);
463 		if (top == blockOfA->m_upper && top == blockOfB->m_upper)
464 			updateAdjacencies(blockOfA, blockOfB, Direction::Minus);
465 
466 		Delta += uswap(blockOfA, blockOfB, Direction::Plus, bottom);
467 		if (bottom == blockOfA->m_lower && bottom == blockOfB->m_lower)
468 			updateAdjacencies(blockOfA, blockOfB, Direction::Plus);
469 	}
470 
471 	// swap positions of A and B in permutation
472 	int c = m_currentPerm[blockOfA->m_index];
473 	int d = m_currentPerm[blockOfB->m_index];
474 
475 	m_currentPermInv[c] = blockOfB->m_index;
476 	m_currentPermInv[d] = blockOfA->m_index;
477 
478 	m_currentPerm[blockOfA->m_index] +=  1;
479 	m_currentPerm[blockOfB->m_index] += -1;
480 
481 	return Delta;
482 }
483 
484 
siftingStep(Block * blockOfA)485 int BlockOrder::siftingStep(Block *blockOfA)
486 {
487 
488 	// new order with A put to front
489 	int positionOfA = m_storedPerm[blockOfA->m_index];
490 	for (int i = 0; i < m_storedPerm.size(); ++i) {
491 		if (m_storedPerm[i] < positionOfA && m_storedPerm[i] != -1)
492 			m_currentPerm[i] = m_storedPerm[i] + 1;
493 		else
494 			m_currentPerm[i] = m_storedPerm[i];
495 	}
496 	m_currentPerm[blockOfA->m_index] = 0;
497 
498 	for (int i = 0; i < m_currentPerm.size(); ++i) {
499 		if (m_currentPerm[i] != -1)
500 			m_currentPermInv[m_currentPerm[i]] = i;
501 	}
502 	sortAdjacencies();
503 
504 	int chi = 0;
505 	int bestChi = 0;
506 	int bestPos = 0;
507 
508 	int oldChi = 0;
509 
510 	for (int p = 1; p < m_activeBlocksCount; ++p) {
511 		chi = chi + siftingSwap(blockOfA, m_Blocks[m_currentPermInv[p]]);
512 		if (chi < bestChi) {
513 			bestChi = chi;
514 			bestPos = p;
515 		}
516 		if (p == positionOfA) {
517 			oldChi = chi;
518 		}
519 	}
520 
521 	//return B'[1]< ... < B[bestPos] < A < B[bestPos+1] <...
522 	for (int i = 0; i < bestPos; ++i) {
523 		m_storedPerm[m_currentPermInv[i]] = i;
524 	}
525 	for (int i = bestPos; i < m_activeBlocksCount; ++i) {
526 		m_storedPerm[m_currentPermInv[i]] = i + 1;
527 	}
528 	m_storedPerm[blockOfA->m_index] = bestPos;
529 
530 	return bestChi - oldChi;
531 }
532 
533 
globalSifting(int rho,int nRepeats,int * pNumCrossings)534 void BlockOrder::globalSifting(int rho, int nRepeats, int *pNumCrossings)
535 {
536 	Array<int> storedPermInv(m_activeBlocksCount);
537 	int p = 0;
538 
539 	for (auto &elem : m_storedPerm) {
540 		elem = -1;
541 	}
542 
543 	for (int i = 0; i < m_Blocks.size(); ++i)
544 		if (m_Blocks[i]->isVertexBlock()
545 		 || (m_Blocks[i]->isEdgeBlock() && m_isActiveEdge[m_Blocks[i]->m_Edge])) {
546 			storedPermInv[p] = i;
547 			m_storedPerm[i] = p;
548 			++p;
549 		}
550 	m_bestCrossings = std::numeric_limits<int>().max();
551 
552 
553 
554 	while (rho-- > 0) {
555 		storedPermInv.permute(0, m_activeBlocksCount - 1);
556 
557 		for (int i = 0; i < m_activeBlocksCount; ++i)
558 			m_storedPerm[storedPermInv[i]] = i;
559 
560 		int times = nRepeats;
561 		while (times-- > 0) {
562 			for (auto &block : m_Blocks) {
563 				if (block->isVertexBlock()
564 				 || (block->isEdgeBlock() && m_isActiveEdge[block->m_Edge])) {
565 					siftingStep(block);
566 				}
567 			}
568 
569 			buildHierarchy();
570 			if (m_storedCrossings < m_bestCrossings) {
571 				for (int b = 0; b < m_bestPerm.size(); ++b) {
572 					m_bestPerm[b] = m_storedPerm[b];
573 				}
574 				m_bestCrossings = m_storedCrossings;
575 			}
576 		}
577 	}
578 
579 	//restore the best permutation
580 	for (int i = 0; i < m_storedPerm.size(); ++i) {
581 		m_storedPerm[i] = m_bestPerm[i];
582 	}
583 	m_storedCrossings = m_bestCrossings;
584 	buildHierarchy();
585 	if(pNumCrossings)
586 		*pNumCrossings = m_storedCrossings;
587 }
588 
589 
buildDummyNodesLists()590 void BlockOrder::buildDummyNodesLists()
591 {
592 	const GraphCopy &GC = m_hierarchy;
593 	NodeArray<bool> mark(GC, false);
594 
595 	NodeArray<int> ranks(GC);
596 
597 	for (auto b : m_Blocks) {
598 		if (b->isVertexBlock()) {
599 			node v = b->m_Node;
600 			int rank = m_ranks[v];
601 			b->m_nodes.init(rank, rank, nullptr);
602 
603 		} else if (m_isActiveEdge[b->m_Edge]) 	{
604 			//m_Blocks[i] is EdgeBlock
605 			b->m_nodes.init(b->m_upper, b->m_lower, nullptr);
606 		}
607 	}
608 
609 	// init m_nodes for vertex blocks
610 	for(node v : GC.nodes) {
611 		ranks[v] = m_hierarchy.rank(v);
612 		node vOrig = GC.original(v);
613 		if (vOrig != nullptr) {
614 			m_NodeBlocks[vOrig]->m_nodes[m_ranks[vOrig]] = v;
615 			mark[v] = true;
616 		}
617 	}
618 
619 	//init m_nodes for edge blocks
620 	for(node v : GC.nodes) {
621 		if (m_hierarchy.isLongEdgeDummy(v)
622 		 && !mark[v]) {
623 			// find the edge from original graph corresponding to this node
624 			node low = v;
625 			node high = v;
626 
627 			List<node> nodesInBlock;
628 			nodesInBlock.pushBack(v);
629 			while (!mark[low]) {
630 				for (adjEntry adj : low->adjEntries) {
631 					edge e = adj->theEdge();
632 					if (low == e->source()) {
633 						low = e->target();
634 						nodesInBlock.pushBack(low);
635 						break;
636 					}
637 				}
638 			}
639 			while (!mark[high]) {
640 				for (adjEntry adj : high->adjEntries) {
641 					edge e = adj->theEdge();
642 					if (high == e->target()) {
643 						high = e->source();
644 						nodesInBlock.pushBack(high);
645 						break;
646 					}
647 				}
648 			}
649 
650 			Block *edgeBlock = m_EdgeBlocks[m_GC.searchEdge(GC.original(high),
651 			                                                GC.original(low))];
652 			for (node u : nodesInBlock) {
653 				if (!mark[u]) {
654 					edgeBlock->m_nodes[ranks[u]] = u;
655 					mark[u] = true;
656 				}
657 			}
658 		}
659 	}
660 }
661 
662 
buildLevels()663 void BlockOrder::buildLevels()
664 {
665 	Array<int> storedPermInv(m_activeBlocksCount);
666 
667 	for (int i = 0; i < m_storedPerm.size(); ++i) {
668 		if (m_storedPerm[i] != -1)
669 			storedPermInv[m_storedPerm[i]] = i;
670 	}
671 
672 
673 	m_pos = NodeArray<int>(m_hierarchy,0);
674 	for (auto &level : m_levels) {
675 		delete level;
676 	}
677 
678 	m_levels.init(0);
679 
680 	// find maximum level index
681 	int maxLevel = 0;
682 
683 	for (int i = 0; i < m_activeBlocksCount; ++i)
684 		maxLevel = max<int>(maxLevel, m_Blocks[storedPermInv[i]]->m_lower);
685 
686 	// number of nodes (on each level)
687 	Array<int> levelNodes(0, maxLevel, 0);
688 
689 	for (int i = 0; i < m_activeBlocksCount; ++i)
690 		for (int level = m_Blocks[storedPermInv[i]]->m_upper; level <= m_Blocks[storedPermInv[i]]->m_lower; ++level)
691 			levelNodes[level] += 1;
692 
693 
694 	m_levels.init(0, maxLevel);
695 	for (int i = 0; i <= maxLevel; ++i)
696 		m_levels[i] = new ArrayLevel(levelNodes[i]);
697 
698 	Array<int> itemsOnLevelCtr(0, maxLevel, 0);
699 
700 	for (int i = 0; i < m_activeBlocksCount; ++i){
701 		Block *b = m_Blocks[storedPermInv[i]];
702 		for (int level = b->m_upper; level <= b->m_lower; ++level) {
703 			ArrayLevel &lvl = *m_levels[level];
704 			lvl[itemsOnLevelCtr[level]] = b->m_nodes[level];
705 			m_pos[b->m_nodes[level]] = itemsOnLevelCtr[level];
706 			++itemsOnLevelCtr[level];
707 		}
708 	}
709 }
710 
711 // copied from HierarchyLevels
buildAdjNodes()712 void BlockOrder::buildAdjNodes()
713 {
714 	m_nSet = NodeArray<int>(m_hierarchy,0);
715 	m_lowerAdjNodes = NodeArray<Array<node> >(m_hierarchy);
716 	m_upperAdjNodes = NodeArray<Array<node> >(m_hierarchy);
717 
718 	const GraphCopy &GC = m_hierarchy;
719 	for(node v : GC.nodes) {
720 		m_lowerAdjNodes[v].init(v->indeg());
721 		m_upperAdjNodes[v].init(v->outdeg());
722 	}
723 
724 
725 	for (int i = 0; i<= high(); ++i){
726 		if (i > 0) {
727 			const ArrayLevel &lowerLevel = *m_levels[i-1];
728 
729 			for(int j = 0; j <= lowerLevel.high(); ++j)
730 				m_nSet[lowerLevel[j]] = 0;
731 		}
732 
733 		if (i < high()) {
734 			const ArrayLevel &upperLevel = *m_levels[i+1];
735 
736 			for(int j = 0; j <= upperLevel.high(); ++j)
737 				m_nSet[upperLevel[j]] = 0;
738 		}
739 
740 		const ArrayLevel &level = *m_levels[i];
741 		for(int j = 0; j <= level.high(); ++j) {
742 			node v = level[j];
743 			for(adjEntry adj : v->adjEntries) {
744 				edge e = adj->theEdge();
745 				if (e->source() == v) {
746 					(m_lowerAdjNodes[e->target()])[m_nSet[e->target()]++] = v;
747 				} else {
748 					(m_upperAdjNodes[e->source()])[m_nSet[e->source()]++] = v;
749 				}
750 			}
751 		}
752 	}
753 }
754 
755 
localCountCrossings(const Array<int> & levels)756 int BlockOrder::localCountCrossings(const Array<int> &levels)
757 {
758 
759 	if (levels.size() < 2) return 0;
760 	// set m_currentPerm
761 	for (auto &level : m_levels) {
762 		delete level;
763 	}
764 
765 	Graph G;
766 
767 	Array<int> storedPermInv(m_Blocks.size());
768 	m_currentPermInv.init(m_Blocks.size());
769 
770 	for (int i = 0; i < m_Blocks.size(); ++i) {
771 		m_currentPerm[i] = m_storedPerm[i];
772 		if (m_storedPerm[i] != -1) {
773 			storedPermInv[m_storedPerm[i]] = i;
774 			m_currentPermInv[m_storedPerm[i]] = i;
775 		}
776 	}
777 
778 
779 	sortAdjacencies();
780 
781 	Array<unsigned int> itemsOnLevelCtr(0, levels.high(), 0);
782 
783 	// create vertices used to calculate number of crossings
784 	for (int i = 0; i < m_Blocks.size(); ++i) {
785 		Block *block = m_Blocks[i];
786 		if (m_storedPerm[i] != -1) {
787 			block->m_nodes.init(levels[0], levels[levels.high()], nullptr);
788 
789 			for (int j = 0; j < levels.size(); ++j) {
790 				int currentLevel = levels[j];
791 				if (block->m_upper <= currentLevel && block->m_lower >= currentLevel) {
792 					itemsOnLevelCtr[j] += 1;
793 					block->m_nodes[currentLevel] = G.newNode();
794 				}
795 			}
796 		} else {
797 			edge currentEdge = block->m_Edge;
798 			Block *targetBlock = m_NodeBlocks[currentEdge->target()];
799 			for (int level = levels.low(); level <= levels.high(); ++level) {
800 				if (block->m_upper <= levels[level] && levels[level] <= block->m_lower && targetBlock->m_nodes[levels[level]] == nullptr) {
801 					itemsOnLevelCtr[level] += 1;
802 					targetBlock->m_nodes[levels[level]] = G.newNode();
803 				}
804 			}
805 		}
806 	}
807 
808 	m_levels.init(levels.size());
809 	for (int j = 0; j < levels.size(); ++j)
810 		m_levels[j] = new ArrayLevel(itemsOnLevelCtr[j]);
811 
812 	m_pos.init(G);
813 	m_upperAdjNodes.init(G);
814 
815 	itemsOnLevelCtr.init(0, levels.high(), 0);
816 
817 	// build m_levels and m_pos
818 	for (int i = 0; i < m_activeBlocksCount; ++i) {
819 		Block *block = m_Blocks[storedPermInv[i]];
820 		for (int j = 0; j < levels.size(); ++j) {
821 			if (block->m_nodes[levels[j]] != nullptr) {
822 				(*m_levels[j])[itemsOnLevelCtr[j]] = block->m_nodes[levels[j]];
823 				m_pos[block->m_nodes[levels[j]]] = itemsOnLevelCtr[j];
824 				itemsOnLevelCtr[j] += 1;
825 			}
826 		}
827 	}
828 
829 	// build m_upperAdjNodes
830 	for (int i = 0; i < m_activeBlocksCount; ++i) {
831 		Block *block = m_Blocks[storedPermInv[i]];
832 		for (int j = 0; j < levels.high(); ++j) {
833 			int currentLevel = levels[j];
834 
835 			int nextLevel = levels[j+1];
836 			if (block->m_upper <= currentLevel && block->m_lower >= currentLevel) 	{
837 				if (nextLevel > block->m_lower) 	{
838 					Array<node> &upperAdj = m_upperAdjNodes[block->m_nodes[currentLevel]];
839 					upperAdj.init(block->m_NeighboursOutgoing.size());
840 					for (int k = 0; k < block->m_NeighboursOutgoing.size(); ++k) {
841 						upperAdj[k] = m_Blocks[block->m_NeighboursOutgoing[k]]->m_nodes[nextLevel];
842 					}
843 				} else {
844 					m_upperAdjNodes[block->m_nodes[currentLevel]]
845 						.init(0, 0, block->m_nodes[nextLevel]);
846 				}
847 			}
848 		}
849 	}
850 	return calculateCrossings();
851 }
852 
853 
verticalSwap(Block * b,int level)854 int BlockOrder::verticalSwap(Block *b, int level)
855 {
856 	int Delta = 0;
857 
858 	int minLvl = level;
859 	int maxLvl = level;
860 
861 	for (int i = m_nNodesOnLvls.low(); i <= m_nNodesOnLvls.high(); ++i) {
862 		if (m_nNodesOnLvls[i] > 0) {
863 			minLvl = i;
864 			break;
865 		}
866 	}
867 	for (int i = m_nNodesOnLvls.high(); i >= m_nNodesOnLvls.low(); --i) {
868 		if (m_nNodesOnLvls[i] > 0) {
869 			maxLvl = i;
870 			break;
871 		}
872 	}
873 
874 	Array<int> levels;
875 	if (level % 2 == 0) {
876 		int ctr = 0;
877 		if (minLvl <= level - 2 && level - 2 <= maxLvl) ++ctr;
878 		if (minLvl <= level - 1 && level - 1 <= maxLvl) ++ctr;
879 		if (minLvl <= level     && level     <= maxLvl) ++ctr;
880 		if (minLvl <= level + 1 && level + 1 <= maxLvl) ++ctr;
881 		if (minLvl <= level + 2 && level + 2 <= maxLvl) ++ctr;
882 		levels.init(ctr);
883 		ctr = 0;
884 		if (minLvl <= level - 2 && level - 2 <= maxLvl) levels[ctr++] = level - 2;
885 		if (minLvl <= level - 1 && level - 1 <= maxLvl) levels[ctr++] = level - 1;
886 		if (minLvl <= level     && level     <= maxLvl) levels[ctr++] = level;
887 		if (minLvl <= level + 1 && level + 1 <= maxLvl) levels[ctr++] = level + 1;
888 		if (minLvl <= level + 2 && level + 2 <= maxLvl) levels[ctr++] = level + 2;
889 	} else {
890 		int ctr = 0;
891 		if (minLvl <= level - 3 && level - 3 <= maxLvl) ++ctr;
892 		if (minLvl <= level - 1 && level - 1 <= maxLvl) ++ctr;
893 		if (minLvl <= level + 1 && level + 1 <= maxLvl) ++ctr;
894 
895 		levels.init(ctr);
896 		ctr = 0;
897 		if (minLvl <= level - 3 && level - 3 <= maxLvl) levels[ctr++] = level - 3;
898 		if (minLvl <= level - 1 && level - 1 <= maxLvl) levels[ctr++] = level - 1;
899 		if (minLvl <= level + 1 && level + 1 <= maxLvl) levels[ctr++] = level + 1;
900 	}
901 
902 	Delta -= localCountCrossings(levels);
903 
904 	// phi(B) = level
905 	m_nNodesOnLvls[b->m_upper] += -1;
906 	b->m_upper = b->m_lower = level;
907 	m_nNodesOnLvls[level] += 1;
908 
909 	Array<int> nextExistingLvl(m_nNodesOnLvls.low(), m_nNodesOnLvls.high(), -1);
910 	int last = std::numeric_limits<int>::max();
911 	for (int i = nextExistingLvl.high(); i >= nextExistingLvl.low(); --i) {
912 		nextExistingLvl[i] = last;
913 		if (m_nNodesOnLvls[i] > 0)
914 			last = i;
915 	}
916 
917 	node v = b->m_Node;
918 
919 	for(adjEntry adj : v->adjEntries) {
920 		edge e = adj->theEdge();
921 		Block *BlockOfE = m_EdgeBlocks[e];
922 		if (v == e->source()) {
923 			BlockOfE->m_upper = level + 1;
924 		} else {
925 			// v == e->target()
926 			BlockOfE->m_lower = level - 1;
927 		}
928 	}
929 
930 	for(edge e : m_GC.edges) {
931 		if (m_EdgeBlocks[e] != nullptr) {
932 			Block *blockOfE = m_EdgeBlocks[e];
933 
934 			int top = blockOfE->m_upper;
935 			int bot = blockOfE->m_lower;
936 
937 			int lvl = nextExistingLvl[top - 1];
938 
939 			if (top <= lvl && lvl <= bot) {
940 				// block is active
941 				if (!m_isActiveEdge[e]) {
942 					int sourcePos = m_storedPerm[m_NodeBlocks[e->source()]->m_index];
943 					int targetPos = m_storedPerm[m_NodeBlocks[e->target()]->m_index];
944 
945 					m_storedPerm[blockOfE->m_index] = (sourcePos + targetPos) / 2;
946 					m_activeBlocksCount += 1;
947 					m_isActiveEdge[e] = true;
948 				}
949 			} else {
950 				//block is inactive
951 				if (m_isActiveEdge[e]) {
952 					m_storedPerm[blockOfE->m_index] = -1;
953 					m_activeBlocksCount -= 1;
954 					m_isActiveEdge[e] = false;
955 				}
956 			}
957 		}
958 	}
959 
960 	// bucketsort
961 	Array<List<int> > buckets(-1, m_storedPerm.size());
962 	for (int i = 0; i < m_storedPerm.size(); ++i) {
963 		buckets[m_storedPerm[i]].pushBack(i);
964 		m_storedPerm[i] = -1;
965 	}
966 	int ctr = 0;
967 	for (int i = 0; i <= buckets.high(); ++i) {
968 		while (!buckets[i].empty()) {
969 			int ind = buckets[i].front();
970 			buckets[i].popFront();
971 			m_storedPerm[ind] = ctr;
972 			ctr += 1;
973 		}
974 	}
975 
976 	// calculate crossings once again
977 	for (int i = m_nNodesOnLvls.low(); i <= m_nNodesOnLvls.high(); ++i) {
978 		if (m_nNodesOnLvls[i] > 0) {
979 			minLvl = i;
980 			break;
981 		}
982 	}
983 	for (int i = m_nNodesOnLvls.high(); i >= m_nNodesOnLvls.low(); --i) {
984 		if (m_nNodesOnLvls[i] > 0) {
985 			maxLvl = i;
986 			break;
987 		}
988 	}
989 
990 	if (level % 2 == 0) {
991 		ctr = 0;
992 		if (minLvl <= level - 2 && level - 2 <= maxLvl) ctr++;
993 		if (minLvl <= level     && level     <= maxLvl) ctr++;
994 		if (minLvl <= level + 2 && level + 2 <= maxLvl) ctr++;
995 		levels.init(ctr);
996 
997 		ctr = 0;
998 		if (minLvl <= level - 2 && level - 2 <= maxLvl) levels[ctr++] = level - 2;
999 		if (minLvl <= level     && level     <= maxLvl) levels[ctr++] = level;
1000 		if (minLvl <= level + 2 && level + 2 <= maxLvl) levels[ctr++] = level + 2;
1001 	} else {
1002 		ctr = 0;
1003 		if (minLvl <= level - 3 && level - 3 <= maxLvl) ctr++;
1004 		if (minLvl <= level - 1 && level - 1 <= maxLvl) ctr++;
1005 		if (minLvl <= level     && level     <= maxLvl) ctr++;
1006 		if (minLvl <= level + 1 && level + 1 <= maxLvl) ctr++;
1007 		levels.init(ctr);
1008 
1009 		ctr = 0;
1010 		if (minLvl <= level - 3 && level - 3 <= maxLvl) levels[ctr++] = level - 3;
1011 		if (minLvl <= level - 1 && level - 1 <= maxLvl) levels[ctr++] = level - 1;
1012 		if (minLvl <= level     && level     <= maxLvl) levels[ctr++] = level;
1013 		if (minLvl <= level + 1 && level + 1 <= maxLvl) levels[ctr++] = level + 1;
1014 	}
1015 
1016 	Delta += localCountCrossings(levels);
1017 
1018 	// do horizontal steps
1019 	v = b->m_Node;
1020 	for(adjEntry adj : v->adjEntries) {
1021 		edge e = adj->theEdge();
1022 		if (m_isActiveEdge[e]) {
1023 			int delta = siftingStep(m_EdgeBlocks[e]);
1024 			Delta += delta;
1025 		}
1026 	}
1027 
1028 	int delta = siftingStep(b);
1029 	Delta += delta;
1030 
1031 	return Delta;
1032 }
1033 
1034 
verticalStep(Block * b)1035 void BlockOrder::verticalStep(Block *b)
1036 {
1037 	int maxLevel = 0;
1038 	//normalize levels to 2,4,6,8,...
1039 	for (auto currentBlock : m_Blocks) {
1040 		if (currentBlock->isVertexBlock()) {
1041 			currentBlock->m_upper = 2 + 2 * (currentBlock->m_upper);
1042 			currentBlock->m_lower = 2 + 2 * (currentBlock->m_lower);
1043 		} else {
1044 			// currentBlock->isEdgeBlock()
1045 			edge e = currentBlock->m_Edge;
1046 			currentBlock->m_upper = m_NodeBlocks[e->source()]->m_lower + 1;
1047 			currentBlock->m_lower = m_NodeBlocks[e->target()]->m_upper - 1;
1048 		}
1049 
1050 		if (currentBlock->m_lower > maxLevel)
1051 			maxLevel = currentBlock->m_lower;
1052 	}
1053 
1054 	m_nNodesOnLvls.init(1, maxLevel + 1, 0);
1055 
1056 	for (auto &block : m_Blocks) {
1057 		if (block->isVertexBlock()) {
1058 			m_nNodesOnLvls[block->m_upper] += 1;
1059 		}
1060 	}
1061 
1062 	int lMin = 1;
1063 	int lMax = maxLevel + 1;
1064 	node v = b->m_Node;
1065 	for(adjEntry adj : v->adjEntries) {
1066 		edge e = adj->theEdge();
1067 		if (v == e->source()) {
1068 			lMax = min<int>(lMax, m_NodeBlocks[e->target()]->m_upper - 1);
1069 		} else {
1070 		  // v == e->target()
1071 			lMin = max<int>(lMin, m_NodeBlocks[e->source()]->m_lower + 1);
1072 		}
1073 	}
1074 	if (lMin < b->m_upper - m_verticalStepsBound)
1075 		lMin = b->m_upper - m_verticalStepsBound;
1076 	if (lMax > b->m_lower + m_verticalStepsBound)
1077 		lMax = b->m_lower + m_verticalStepsBound;
1078 
1079 	Array<int> startingPerm(0, m_storedPerm.high(), -1);
1080 
1081 	Array<int> startingM_upper(0, m_Blocks.high(), 0);
1082 	Array<int> startingM_lower(0, m_Blocks.high(), 0);
1083 
1084 	int startingActiveBlocksCount;
1085 	EdgeArray<bool> startingM_isActiveEdge;
1086 
1087 	Array<int> bestPerm(m_storedPerm.size());
1088 
1089 	Array<int> bestM_upper(0, m_Blocks.high(), 0);
1090 	Array<int> bestM_lower(0, m_Blocks.high(), 0);
1091 
1092 	int bestActiveBlocksCount = 0;
1093 	EdgeArray<bool> bestM_isActiveEdge;
1094 
1095 	int bestChi = std::numeric_limits<int>::max();
1096 	int currentChi = 0;
1097 
1098 
1099 	// store starting embedding
1100 	for (int i = 0; i < m_Blocks.size(); ++i) {
1101 		startingPerm[i]    = m_storedPerm[i];
1102 		startingM_lower[i] = m_Blocks[i]->m_lower;
1103 		startingM_upper[i] = m_Blocks[i]->m_upper;
1104 	}
1105 	startingActiveBlocksCount = m_activeBlocksCount;
1106 	startingM_isActiveEdge = m_isActiveEdge;
1107 
1108 	// for upward
1109 	for (int level = b->m_upper + 1; level >= lMin; --level) {
1110 		int Delta = verticalSwap(b, level);
1111 		currentChi += Delta;
1112 		if (currentChi < bestChi) {
1113 			// store currentEmbedding as best found
1114 			for (int i = 0; i < m_Blocks.size(); ++i) {
1115 				bestPerm[i]    = m_storedPerm[i];
1116 				bestM_lower[i] = m_Blocks[i]->m_lower;
1117 				bestM_upper[i] = m_Blocks[i]->m_upper;
1118 			}
1119 
1120 			bestActiveBlocksCount = m_activeBlocksCount;
1121 			bestM_isActiveEdge = m_isActiveEdge;
1122 			bestChi = currentChi;
1123 		}
1124 	}
1125 
1126 	// restore starting embedding
1127 	for (int i = 0; i < m_Blocks.size(); ++i) {
1128 		m_storedPerm[i] = startingPerm[i];
1129 		m_Blocks[i]->m_lower = startingM_lower[i];
1130 		m_Blocks[i]->m_upper = startingM_upper[i];
1131 	}
1132 
1133 	currentChi = 0;
1134 
1135 	m_activeBlocksCount = startingActiveBlocksCount;
1136 	m_isActiveEdge = startingM_isActiveEdge;
1137 
1138 	m_nNodesOnLvls.init(1, maxLevel + 1, 0);
1139 
1140 	for (auto &block : m_Blocks) {
1141 		if (block->isVertexBlock()) {
1142 			m_nNodesOnLvls[block->m_upper] += 1;
1143 		}
1144 	}
1145 
1146 	// for downward
1147 	for (int level = b->m_lower + 1; level <= lMax; ++level) {
1148 		int Delta = verticalSwap(b, level);
1149 		currentChi += Delta;
1150 		if (currentChi < bestChi) {
1151 			// store currentEmbedding as best found
1152 			for (int i = 0; i < m_Blocks.size(); ++i) {
1153 				bestPerm[i]    = m_storedPerm[i];
1154 				bestM_lower[i] = m_Blocks[i]->m_lower;
1155 				bestM_upper[i] = m_Blocks[i]->m_upper;
1156 			}
1157 
1158 			bestActiveBlocksCount = m_activeBlocksCount;
1159 			bestM_isActiveEdge = m_isActiveEdge;
1160 			bestChi = currentChi;
1161 		}
1162 	}
1163 
1164 	// restore best
1165 	for (int i = 0; i < m_Blocks.size(); ++i) {
1166 		m_storedPerm[i] = bestPerm[i];
1167 		m_Blocks[i]->m_lower = bestM_lower[i];
1168 		m_Blocks[i]->m_upper = bestM_upper[i];
1169 	}
1170 	currentChi = bestChi;
1171 
1172 	m_activeBlocksCount = bestActiveBlocksCount;
1173 	m_isActiveEdge = bestM_isActiveEdge;
1174 
1175 	// delete empty levels
1176 	m_nNodesOnLvls.init(1, maxLevel + 1, 0);
1177 
1178 	for (auto &block : m_Blocks) {
1179 		if (block->isVertexBlock()) {
1180 			m_nNodesOnLvls[block->m_upper] += 1;
1181 		}
1182 	}
1183 
1184 	int p = 0;
1185 	Array<int> normalizedLvl(1, maxLevel + 1);
1186 	for (int i = 1; i <= maxLevel + 1; ++i) {
1187 		if (m_nNodesOnLvls[i] > 0) {
1188 			normalizedLvl[i] = p;
1189 			++p;
1190 		}
1191 	}
1192 
1193 	for (auto currentBlock : m_Blocks) {
1194 		if (currentBlock->isVertexBlock()) {
1195 			currentBlock->m_upper = normalizedLvl[currentBlock->m_upper];
1196 			currentBlock->m_lower = normalizedLvl[currentBlock->m_lower];
1197 		} else { // currentBlock->isEdgeBlock()
1198 			edge e = currentBlock->m_Edge;
1199 			currentBlock->m_upper = m_NodeBlocks[e->source()]->m_lower  + 1;
1200 			currentBlock->m_lower = m_NodeBlocks[e->target()]->m_upper  - 1;
1201 		}
1202 	}
1203 }
1204 
1205 
gridSifting(int nRepeats)1206 void BlockOrder::gridSifting(int nRepeats)
1207 {
1208 #if 0
1209 	while (rho-- > 0)
1210 #endif
1211 	{
1212 		Array<int> storedPermInv(0, m_Blocks.high(), -1);
1213 		m_storedPerm.init(0, m_Blocks.high(), -1);
1214 		int p = 0;
1215 
1216 		for (int i = 0; i < m_Blocks.size(); ++i) {
1217 			if (m_Blocks[i]->isVertexBlock()
1218 			 || (m_Blocks[i]->isEdgeBlock() && m_isActiveEdge[m_Blocks[i]->m_Edge])) {
1219 				storedPermInv[p] = i;
1220 				m_storedPerm[i] = p;
1221 				++p;
1222 			}
1223 		}
1224 
1225 		// initialize with random permutation
1226 		storedPermInv.permute(0, m_activeBlocksCount - 1);
1227 
1228 		for (int i = 0; i < m_activeBlocksCount; ++i)
1229 			m_storedPerm[storedPermInv[i]] = i;
1230 
1231 
1232 		int times = nRepeats;
1233 		while (times-- > 0) {
1234 			for(node v : m_GC.nodes) {
1235 				Block *currentBlock = m_NodeBlocks[v];
1236 				if (currentBlock != nullptr) {
1237 					verticalStep(currentBlock);
1238 				}
1239 			}
1240 		}
1241 	}
1242 
1243 	// reassign m_hierarchy!
1244 	m_ranks.init(m_GC, 0);
1245 	EdgeArray<edge> auxCopy(m_GC);
1246 	List<node> nodes;
1247 	for(node v : m_GC.nodes) {
1248 		if (m_NodeBlocks[v] != nullptr) {
1249 			m_ranks[v] = m_NodeBlocks[v]->m_upper;
1250 			nodes.pushBack(v);
1251 		}
1252 	}
1253 	m_hierarchy.createEmpty(m_GC);
1254 	m_hierarchy.initByNodes(nodes, auxCopy, m_ranks);
1255 
1256 	// build levels
1257 	buildHierarchy();
1258 	return;
1259 }
1260 
1261 }
1262