6 * $Date: 2012-07-07 23:10:08 +0200 (Sa, 07. Jul 2012) $
7 ***************************************************************/
10 * \brief Computes an embedding of a graph with minimum depth and
11 * maximum external face.
13 * See the paper "Graph Embedding with Minimum
14 * Depth and Maximum External Face" by C. Gutwenger and P. Mutzel
16 * The algorithm for minimum depth and maximum external face is
17 * combined with the algorithm for maximum external layers which
18 * defines how to embed blocks into inner faces. See diploma thesis
19 * "Algorithmen zur Bestimmung von guten Graph-Einbettungen für
20 * orthogonale Zeichnungen" (in german) by Thorsten Kerkhof (2007)
23 * \author Thorsten Kerkhof
26 * This file is part of the Open Graph Drawing Framework (OGDF).
30 * See README.txt in the root directory of the OGDF installation for details.
33 * This program is free software; you can redistribute it and/or
34 * modify it under the terms of the GNU General Public License
35 * Version 2 or 3 as published by the Free Software Foundation;
36 * see the file LICENSE.txt included in the packaging of this file
40 * This program is distributed in the hope that it will be useful,
41 * but WITHOUT ANY WARRANTY; without even the implied warranty of
42 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
43 * GNU General Public License for more details.
46 * You should have received a copy of the GNU General Public
47 * License along with this program; if not, write to the Free
48 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
49 * Boston, MA 02110-1301, USA.
51 * \see http://www.gnu.org/copyleft/gpl.html
52 ***************************************************************/
54 #include <ogdf/planarity/EmbedderMinDepthMaxFaceLayers.h>
55 #include <ogdf/internal/planarity/ConnectedSubgraph.h>
56 #include <ogdf/internal/planarity/EmbedderMaxFaceBiconnectedGraphsLayers.h>
60 void EmbedderMinDepthMaxFaceLayers::call(Graph
& G
, adjEntry
& adjExternal
)
64 int maxint
= 0xFFFFFF;
67 pAdjExternal
= &adjExternal
;
70 if (G
.numberOfNodes() <= 1)
72 if (G
.numberOfEdges() == 1)
74 edge e
= G
.firstEdge();
75 adjExternal
= e
->adjSource();
79 //HINT: Edges are directed from child to parent in BC-trees
80 pBCTree
= new BCTree(G
);
82 //base case of biconnected graph:
83 if (pBCTree
->bcTree().numberOfNodes() == 1)
85 NodeArray
<int> m_nodeLength(G
, 0);
86 EdgeArray
<int> m_edgeLength(G
, 1);
87 adjEntry m_adjExternal
;
88 EmbedderMaxFaceBiconnectedGraphsLayers
<int>::embed(
89 G
, m_adjExternal
, m_nodeLength
, m_edgeLength
);
90 adjExternal
= m_adjExternal
->twin();
97 //============================================================================
98 // First step: calculate min depth and node lengths
99 //============================================================================
100 //Find root Block (only node with out-degree of 0):
102 forall_nodes(n
, pBCTree
->bcTree())
104 if (n
->outdeg() == 0)
111 /****************************************************************************/
113 /****************************************************************************/
114 //Node lengths of block graph:
115 md_nodeLength
.init(pBCTree
->auxiliaryGraph(), 0);
117 //Edge lengths of BC-tree, values m_{c, B} for all (c, B) \in bcTree:
118 md_m_cB
.init(pBCTree
->bcTree(), 0);
120 //Bottom-up traversal: (set m_cB for all {c, B} \in bcTree)
121 forall_adj_edges(e
, rootBlockNode
)
123 node cT
= e
->source();
124 //node cH = pBCTree->cutVertex(cT, rootBlockNode);
126 //set length of c in block graph of root block node:
128 forall_adj_edges(e2
, cT
)
130 if (e2
->target() != cT
)
133 node blockNode
= e2
->source();
134 node cutVertex
= pBCTree
->cutVertex(cT
, blockNode
);
137 md_m_cB
[e2
] = md_bottomUpTraversal(blockNode
, cutVertex
);
141 //Top-down traversal: (set m_cB for all {B, c} \in bcTree and get min depth
143 md_nodeLength
.fill(0);
144 md_minDepth
.init(pBCTree
->bcTree(), maxint
);
145 md_M_B
.init(pBCTree
->bcTree());
146 md_M2
.init(pBCTree
->bcTree());
147 md_topDownTraversal(rootBlockNode
);
149 /****************************************************************************/
151 /****************************************************************************/
152 mf_cstrLength
.init(pBCTree
->auxiliaryGraph(), 0);
153 mf_nodeLength
.init(pBCTree
->auxiliaryGraph(), 0);
154 mf_maxFaceSize
.init(pBCTree
->bcTree(), 0);
156 //Bottom-Up-Traversal:
158 forall_adj_edges(e
, rootBlockNode
)
160 node cT
= e
->source();
161 node cH
= pBCTree
->cutVertex(cT
, rootBlockNode
);
163 //set length of v in block graph of root block node:
164 int length_v_in_rootBlock
= 0;
166 forall_adj_edges(e2
, cT
)
168 //check if edge is an incoming edge:
169 if (e2
->target() != cT
)
172 node blockNode
= e2
->source();
173 node cutVertex
= pBCTree
->cutVertex(cT
, blockNode
);
174 length_v_in_rootBlock
+= mf_constraintMaxFace(blockNode
, cutVertex
);
176 mf_nodeLength
[cH
] = length_v_in_rootBlock
;
180 node mf_bT_opt
= G
.chooseNode(); //= G.chooseNode() only to get rid of warning
182 mf_maximumFaceRec(rootBlockNode
, mf_bT_opt
, mf_ell_opt
);
184 /****************************************************************************/
185 /* MIN DEPTH + MAX FACE */
186 /****************************************************************************/
188 mdmf_edgeLength
.init(pBCTree
->auxiliaryGraph(), MDMFLengthAttribute(0, 1));
189 mdmf_nodeLength
.init(pBCTree
->auxiliaryGraph(), MDMFLengthAttribute(0, 0));
194 forall_nodes(bT
, pBCTree
->bcTree())
196 if (pBCTree
->typeOfBNode(bT
) != BCTree::BComp
)
198 if ( md_minDepth
[bT
] < d_opt
|| (md_minDepth
[bT
] == d_opt
&& mf_maxFaceSize
[bT
] > ell_opt
))
200 d_opt
= md_minDepth
[bT
];
201 ell_opt
= mf_maxFaceSize
[bT
];
206 //============================================================================
207 // Second step: Embed G by expanding a maximum face in bT_opt
208 //============================================================================
210 treeNodeTreated
.init(pBCTree
->bcTree(), false);
211 //reset md_nodeLength and set them during embedBlock call, because they are
212 //calculated for starting embedding with rootBlockNode, which is not
214 md_nodeLength
.fill(0);
218 G
.sort(n
, newOrder
[n
]);
224 int EmbedderMinDepthMaxFaceLayers::md_bottomUpTraversal(const node
& bT
, const node
& cH
)
226 int m_B
= 0; //max_{c \in B} m_B(c)
227 List
<node
> M_B
; //{c \in B | m_B(c) = m_B}
231 forall_adj_edges(e
, bT
)
233 if (e
->target() != bT
)
235 node cT
= e
->source();
236 //node c_in_bT = pBCTree->cutVertex(cT, bT);
238 //set length of c in block graph of root block node:
240 forall_adj_edges(e_cT_bT2
, cT
)
245 node bT2
= e_cT_bT2
->source();
246 node c_in_bT2
= pBCTree
->cutVertex(cT
, bT2
);
247 md_m_cB
[e_cT_bT2
] = md_bottomUpTraversal(bT2
, c_in_bT2
);
249 //update m_B and M_B:
250 if (m_B
< md_m_cB
[e_cT_bT2
])
252 node cV_in_bT
= pBCTree
->cutVertex(cT
, bT
);
253 m_B
= md_m_cB
[e_cT_bT2
];
255 M_B
.pushBack(cV_in_bT
);
257 else if ( m_B
== md_m_cB
[e_cT_bT2
] && M_B
.search(pBCTree
->cutVertex(cT
, bT
)) == -1)
259 node cV_in_bT
= pBCTree
->cutVertex(cT
, bT
);
260 M_B
.pushBack(cV_in_bT
);
265 //set vertex length for all vertices in bH to 1 if vertex is in M_B:
266 for (ListIterator
<node
> iterator
= M_B
.begin(); iterator
.valid(); iterator
++)
267 md_nodeLength
[*iterator
] = 1;
269 //generate block graph of bT:
271 node cInBlockGraph_bT
;
272 NodeArray
<int> nodeLengthSG(blockGraph_bT
);
273 ConnectedSubgraph
<int>::call(pBCTree
->auxiliaryGraph(), blockGraph_bT
, cH
,
274 cInBlockGraph_bT
, md_nodeLength
, nodeLengthSG
);
280 //set edge length for all edges in block graph to 0:
281 EdgeArray
<int> edgeLength(blockGraph_bT
, 0);
283 //compute maximum external face of block graph and get its size:
284 int cstrLength_B_c
= EmbedderMaxFaceBiconnectedGraphsLayers
<int>::computeSize(
290 if (cstrLength_B_c
== M_B
.size())
297 void EmbedderMinDepthMaxFaceLayers::md_topDownTraversal(const node
& bT
)
299 //m_B(c) = max {0} \cup {m_{c, B'} | c \in B', B' \neq B}
300 int m_B
= 0; //max_{c \in B} m_B(c)
302 //Compute m_B and M_B:
306 forall_adj_edges(e_bT_cT
, bT
)
308 if (e_bT_cT
->source() == bT
)
309 cT_parent
= e_bT_cT
->target();
310 node cT
= (e_bT_cT
->source() == bT
) ? e_bT_cT
->target() : e_bT_cT
->source();
312 forall_adj_edges(e_cT_bT2
, cT
)
314 if (e_cT_bT2
== e_bT_cT
)
317 //update m_B and M_B:
318 if (m_B
< md_m_cB
[e_cT_bT2
])
320 m_B
= md_m_cB
[e_cT_bT2
];
322 md_M_B
[bT
].pushBack(pBCTree
->cutVertex(cT
, bT
));
324 else if ( m_B
== md_m_cB
[e_cT_bT2
] && md_M_B
[bT
].search(pBCTree
->cutVertex(cT
, bT
)) == -1)
326 md_M_B
[bT
].pushBack(pBCTree
->cutVertex(cT
, bT
));
328 }//forall_adj_edges(e_cT_bT2, cT)
329 }//forall_adj_edges(e_bT_cT, bT)
331 //set vertex length for all vertices in bH to 1 if vertex is in M_B:
332 NodeArray
<int> m_nodeLength(pBCTree
->auxiliaryGraph(), 0);
333 for (ListIterator
<node
> iterator
= md_M_B
[bT
].begin(); iterator
.valid(); iterator
++)
335 md_nodeLength
[*iterator
] = 1;
336 m_nodeLength
[*iterator
] = 1;
339 //generate block graph of bT:
341 NodeArray
<int> nodeLengthSG(blockGraph_bT
);
342 NodeArray
<node
> nG_to_nSG
;
343 ConnectedSubgraph
<int>::call(pBCTree
->auxiliaryGraph(), blockGraph_bT
,
344 (*(pBCTree
->hEdges(bT
).begin()))->source(),
345 m_nodeLength
, nodeLengthSG
, nG_to_nSG
);
347 //set edge length for all edges in block graph to 0:
348 EdgeArray
<int> edgeLengthBlock(blockGraph_bT
, 0);
350 //compute size of a maximum external face of block graph:
351 StaticSPQRTree
* spqrTree
= 0;
352 if ( !blockGraph_bT
.empty()
353 && blockGraph_bT
.numberOfNodes() != 1
354 && blockGraph_bT
.numberOfEdges() > 2)
356 spqrTree
= new StaticSPQRTree(blockGraph_bT
);
358 NodeArray
< EdgeArray
<int> > edgeLengthSkel
;
359 int cstrLength_B_c
= EmbedderMaxFaceBiconnectedGraphsLayers
<int>::computeSize(
360 blockGraph_bT
, nodeLengthSG
, edgeLengthBlock
, *spqrTree
, edgeLengthSkel
);
362 //Prepare recursion by setting m_{c, B} for all edges {B, c} \in bcTree:
363 if (md_M_B
[bT
].size() > 0)
365 node cT1
= pBCTree
->bcproper(pBCTree
->original(*(md_M_B
[bT
].begin())));
366 bool calculateNewNodeLengths
;
367 if (md_M_B
[bT
].size() == 1 && cT1
== cT_parent
)
368 calculateNewNodeLengths
= true;
370 calculateNewNodeLengths
= false;
371 forall_adj_edges(e_bT_cT
, bT
)
373 if (e_bT_cT
->target() != bT
)
375 node cT
= e_bT_cT
->source();
376 node cH
= pBCTree
->cutVertex(cT
, bT
);
378 if (md_M_B
[bT
].size() == 1 && cT1
== cT
)
380 //Compute new vertex lengths according to
381 //m2 = max_{v \in V_B, v != c} m_B(v) and
382 //M2 = {c \in V_B \ {v} | m_B(c) = m2}.
387 forall_adj_edges(e_bT_cT2
, bT
)
389 node cT2
= (e_bT_cT2
->source() == bT
) ? e_bT_cT2
->target() : e_bT_cT2
->source();
393 forall_adj_edges(e_cT2_bT2
, cT2
)
395 if (e_cT2_bT2
== e_bT_cT2
)
398 //update m_B and M_B:
399 if (m2
< md_m_cB
[e_cT2_bT2
])
401 m2
= md_m_cB
[e_cT2_bT2
];
403 md_M2
[bT
].pushBack(pBCTree
->cutVertex(cT2
, bT
));
405 else if ( m2
== md_m_cB
[e_cT2_bT2
] && md_M2
[bT
].search(pBCTree
->cutVertex(cT2
, bT
)) == -1)
407 md_M2
[bT
].pushBack(pBCTree
->cutVertex(cT2
, bT
));
409 }//forall_adj_edges(e_cT2_bT2, cT2)
410 }//forall_adj_edges(e_bT_cT2, bT)
412 //set vertex length for all vertices in bH to 1 if vertex is in M2 and
414 md_nodeLength
[*(md_M_B
[bT
].begin())] = 0;
415 for (ListIterator
<node
> iterator
= md_M2
[bT
].begin(); iterator
.valid(); iterator
++)
416 md_nodeLength
[*iterator
] = 1;
419 node cInBlockGraph_bT
;
420 NodeArray
<int> nodeLengthSG(blockGraph_bT
);
421 ConnectedSubgraph
<int>::call(pBCTree
->auxiliaryGraph(), blockGraph_bT
, cH
,
422 cInBlockGraph_bT
, md_nodeLength
, nodeLengthSG
);
424 //set edge length for all edges in block graph to 0:
425 EdgeArray
<int> edgeLength(blockGraph_bT
, 0);
427 //compute a maximum external face size of a face containing c in block graph:
428 int maxFaceSize
= EmbedderMaxFaceBiconnectedGraphsLayers
<int>::computeSize(
429 blockGraph_bT
, cInBlockGraph_bT
, nodeLengthSG
, edgeLength
);
430 if (md_M2
[bT
].size() == 0)
431 md_m_cB
[e_bT_cT
] = 1;
434 if (maxFaceSize
== md_M2
[bT
].size())
435 md_m_cB
[e_bT_cT
] = m2
;
437 md_m_cB
[e_bT_cT
] = m2
+ 2;
440 if (calculateNewNodeLengths
)
441 calculateNewNodeLengths
= false;
444 //reset node lengths:
445 for (ListIterator
<node
> iterator
= md_M2
[bT
].begin(); iterator
.valid(); iterator
++)
446 md_nodeLength
[*iterator
] = 0;
447 md_nodeLength
[*(md_M_B
[bT
].begin())] = 1;
450 else //M_B.size() != 1
452 //compute a maximum external face size of a face containing c in block graph:
453 node cInBlockGraph_bT
= nG_to_nSG
[cH
];
454 int maxFaceSize
= EmbedderMaxFaceBiconnectedGraphsLayers
<int>::computeSize(
455 blockGraph_bT
, cInBlockGraph_bT
, nodeLengthSG
, edgeLengthBlock
, *spqrTree
, edgeLengthSkel
);
456 if (md_M_B
[bT
].size() == 0)
457 md_m_cB
[e_bT_cT
] = 1;
460 if (maxFaceSize
== md_M_B
[bT
].size())
461 md_m_cB
[e_bT_cT
] = m_B
;
463 md_m_cB
[e_bT_cT
] = m_B
+ 2;
466 }//forall_adj_edges(e_bT_cT, bT)
468 if (calculateNewNodeLengths
)
470 //Compute new vertex lengths according to
471 //m2 = max_{v \in V_B, v != c} m_B(v) and
472 //M2 = {c \in V_B \ {v} | m_B(c) = m2}.
477 forall_adj_edges(e_bT_cT2
, bT
)
479 node cT2
= (e_bT_cT2
->source() == bT
) ? e_bT_cT2
->target() : e_bT_cT2
->source();
483 forall_adj_edges(e_cT2_bT2
, cT2
)
485 if (e_cT2_bT2
== e_bT_cT2
)
488 //update m_B and M_B:
489 if (m2
< md_m_cB
[e_cT2_bT2
])
491 m2
= md_m_cB
[e_cT2_bT2
];
493 md_M2
[bT
].pushBack(pBCTree
->cutVertex(cT2
, bT
));
495 else if ( m2
== md_m_cB
[e_cT2_bT2
] && md_M2
[bT
].search(pBCTree
->cutVertex(cT2
, bT
)) == -1)
497 md_M2
[bT
].pushBack(pBCTree
->cutVertex(cT2
, bT
));
499 }//forall_adj_edges(e_cT2_bT2, cT2)
500 }//forall_adj_edges(e_bT_cT2, bT)
502 //set vertex length for all vertices in bH to 1 if vertex is in M2 and
504 md_nodeLength
[*(md_M_B
[bT
].begin())] = 0;
505 for (ListIterator
<node
> iterator
= md_M2
[bT
].begin(); iterator
.valid(); iterator
++)
506 md_nodeLength
[*iterator
] = 1;
507 } //if (calculateNewNodeLengths
508 else if (md_M_B
[bT
].size() == 1)
510 //Compute M2 = {c \in V_B \ {v} | m_B(c) = m2} with
511 //m2 = max_{v \in V_B, v != c} m_B(v).
514 forall_adj_edges(e_bT_cT2
, bT
)
516 node cT2
= (e_bT_cT2
->source() == bT
) ? e_bT_cT2
->target() : e_bT_cT2
->source();
520 forall_adj_edges(e_cT2_bT2
, cT2
)
522 if (e_cT2_bT2
== e_bT_cT2
)
525 //update m_B and M_B:
526 if (m2
< md_m_cB
[e_cT2_bT2
])
528 m2
= md_m_cB
[e_cT2_bT2
];
530 md_M2
[bT
].pushBack(pBCTree
->cutVertex(cT2
, bT
));
532 else if ( m2
== md_m_cB
[e_cT2_bT2
] && md_M2
[bT
].search(pBCTree
->cutVertex(cT2
, bT
)) == -1)
534 md_M2
[bT
].pushBack(pBCTree
->cutVertex(cT2
, bT
));
536 }//forall_adj_edges(e_cT2_bT2, cT2)
537 }//forall_adj_edges(e_bT_cT2, bT)
542 forall_adj_edges(e_bT_cT
, bT
)
544 if (e_bT_cT
->target() != bT
)
547 node cT
= e_bT_cT
->source();
549 forall_adj_edges(e_cT_bT2
, cT
)
551 if (e_cT_bT2
== e_bT_cT
)
554 md_topDownTraversal(e_cT_bT2
->source());
558 //Compute M_B and M2 for embedBlock-function:
564 forall_adj_edges(e_bT_cT
, bT
)
566 node cT
= (e_bT_cT
->source() == bT
) ? e_bT_cT
->target() : e_bT_cT
->source();
568 forall_adj_edges(e_cT_bT2
, cT
)
570 if (e_bT_cT
== e_cT_bT2
)
573 //update m_B and M_B:
574 if (m_B
< md_m_cB
[e_cT_bT2
])
576 m_B
= md_m_cB
[e_cT_bT2
];
578 md_M_B
[bT
].pushBack(pBCTree
->cutVertex(cT
, bT
));
580 else if ( m_B
== md_m_cB
[e_cT_bT2
] && md_M_B
[bT
].search(pBCTree
->cutVertex(cT
, bT
)) == -1)
582 md_M_B
[bT
].pushBack(pBCTree
->cutVertex(cT
, bT
));
584 }//forall_adj_edges(e_cT_bT2, cT)
585 }//forall_adj_edges(e_bT_cT, bT)
587 if (md_M_B
[bT
].size() == 1)
589 node cT1
= pBCTree
->bcproper(pBCTree
->original(*(md_M_B
[bT
].begin())));
590 forall_adj_edges(e_bT_cT
, bT
)
592 node cT2
= (e_bT_cT
->source() == bT
) ? e_bT_cT
->target() : e_bT_cT
->source();
595 node cT
= (e_bT_cT
->source() == bT
) ? e_bT_cT
->target() : e_bT_cT
->source();
597 forall_adj_edges(e_cT_bT2
, cT
)
600 if (m2
< md_m_cB
[e_cT_bT2
])
602 m2
= md_m_cB
[e_cT_bT2
];
604 md_M2
[bT
].pushBack(pBCTree
->cutVertex(cT
, bT
));
606 else if ( m2
== md_m_cB
[e_cT_bT2
]
607 && md_M2
[bT
].search(pBCTree
->cutVertex(cT
, bT
)) == -1)
609 md_M2
[bT
].pushBack(pBCTree
->cutVertex(cT
, bT
));
611 }//forall_adj_edges(e_cT_bT2, cT)
612 }//forall_adj_edges(e_bT_cT, bT)
616 if (cstrLength_B_c
== md_M_B
[bT
].size())
617 md_minDepth
[bT
] = m_B
;
619 md_minDepth
[bT
] = m_B
+ 2;
625 int EmbedderMinDepthMaxFaceLayers::mf_constraintMaxFace(const node
& bT
, const node
& cH
)
627 //forall (v \in B, v \neq c) do:
628 // length_B(v) := \sum_{(v, B') \in B} ConstraintMaxFace(B', v);
630 forall_adj_edges(e
, bT
)
632 if (e
->target() != bT
)
634 node vT
= e
->source();
635 node vH
= pBCTree
->cutVertex(vT
, bT
);
637 //set length of vertex v in block graph of bT:
638 int length_v_in_block
= 0;
640 forall_adj_edges(e2
, vT
)
642 //check if edge is an incoming edge:
643 if (e2
->target() != vT
)
646 node bT2
= e2
->source();
647 node cutVertex
= pBCTree
->cutVertex(vT
, bT2
);
648 length_v_in_block
+= mf_constraintMaxFace(bT2
, cutVertex
);
650 mf_nodeLength
[vH
] = length_v_in_block
;
653 mf_nodeLength
[cH
] = 0;
656 NodeArray
<int> nodeLengthSG(blockGraph
);
657 ConnectedSubgraph
<int>::call(pBCTree
->auxiliaryGraph(), blockGraph
, cH
, cInBlockGraph
,
658 mf_nodeLength
, nodeLengthSG
);
659 EdgeArray
<int> edgeLengthSG(blockGraph
, 1);
660 int cstrLengthBc
= EmbedderMaxFaceBiconnectedGraphsLayers
<int>::computeSize(
661 blockGraph
, cInBlockGraph
, nodeLengthSG
, edgeLengthSG
);
662 mf_cstrLength
[cH
] = cstrLengthBc
;
667 void EmbedderMinDepthMaxFaceLayers::mf_maximumFaceRec(const node
& bT
, node
& bT_opt
, int& ell_opt
)
669 //(B*, \ell*) := (B, size of a maximum face in B):
672 NodeArray
<int> nodeLengthSG(blockGraph_bT
);
673 NodeArray
<node
> nG_to_nSG
;
674 ConnectedSubgraph
<int>::call(
675 pBCTree
->auxiliaryGraph(), blockGraph_bT
,
676 (*(pBCTree
->hEdges(bT
).begin()))->source(),
677 mf_nodeLength
, nodeLengthSG
, nG_to_nSG
);
678 EdgeArray
<int> edgeLengthSG(blockGraph_bT
, 1);
679 StaticSPQRTree
* spqrTree
= 0;
680 if ( !blockGraph_bT
.empty()
681 && blockGraph_bT
.numberOfNodes() != 1
682 && blockGraph_bT
.numberOfEdges() > 2)
684 spqrTree
= new StaticSPQRTree(blockGraph_bT
);
686 NodeArray
< EdgeArray
<int> > edgeLengthSkel
;
687 int m_ell_opt
= EmbedderMaxFaceBiconnectedGraphsLayers
<int>::computeSize(
688 blockGraph_bT
, nodeLengthSG
, edgeLengthSG
, *spqrTree
, edgeLengthSkel
);
689 mf_maxFaceSize
[bT
] = m_ell_opt
;
692 forall_adj_edges(e
, bT
)
694 if (e
->target() != bT
)
696 node cT
= e
->source();
697 node cH
= pBCTree
->cutVertex(cT
, bT
);
699 //cstrLengthBc := size of a maximum face in B containing c:
700 node cInBlockGraph_bT
= nG_to_nSG
[cH
];
701 mf_cstrLength
[cH
] = EmbedderMaxFaceBiconnectedGraphsLayers
<int>::computeSize(
702 blockGraph_bT
, cInBlockGraph_bT
, nodeLengthSG
, edgeLengthSG
, *spqrTree
, edgeLengthSkel
);
704 //L := \sum_{(B', c) \in bcTree} cstrLength(B', c)
708 forall_adj_edges(e2
, cT
)
710 //check if edge is an incoming edge:
711 if (e2
->source() != cT
)
714 //get partner vertex of c in the block graph of B'=e->target() and add
715 //cstrLength(B', c) to L:
716 L
+= mf_cstrLength
[pBCTree
->cutVertex(cT
, e2
->target())];
720 forall_adj_edges(e2
, cT
)
722 //check if edge is an outgoing edge or the edge from bT to cT:
723 if (e2
->target() != cT
|| e2
->source() == bT
)
726 //get partner vertex of c in the block graph of B'=e->source():
727 node partnerV
= pBCTree
->cutVertex(cT
, e2
->source());
728 mf_nodeLength
[partnerV
] = L
- mf_cstrLength
[partnerV
];
730 //pBCTree->originalGraph().chooseNode() just to get rid of warning:
731 node thisbT_opt
= pBCTree
->originalGraph().chooseNode();
733 mf_maximumFaceRec(e2
->source(), thisbT_opt
, thisell_opt
);
734 if (thisell_opt
> m_ell_opt
)
736 m_bT_opt
= thisbT_opt
;
737 m_ell_opt
= thisell_opt
;
742 //return (B*, \ell*):
750 void EmbedderMinDepthMaxFaceLayers::embedBlock(const node
& bT
)
752 ListIterator
<adjEntry
> after
;
754 embedBlock(bT
, cT
, after
);
758 void EmbedderMinDepthMaxFaceLayers::embedBlock(
761 ListIterator
<adjEntry
>& after
)
763 treeNodeTreated
[bT
] = true;
767 cH
= pBCTree
->cutVertex(cT
, bT
);
769 //***************************************************************************
770 // 1. Compute MinDepth node lengths depending on M_B, M2 and cT
771 //***************************************************************************
772 if (!(cT
== 0) && md_M_B
[bT
].size() == 1 && *(md_M_B
[bT
].begin()) == cH
)
774 //set node length to 1 if node is in M2 and 0 otherwise
775 for (ListIterator
<node
> iterator
= md_M2
[bT
].begin(); iterator
.valid(); iterator
++)
776 md_nodeLength
[*iterator
] = 1;
780 //set node length to 1 if node is in M_B and 0 otherwise
781 for (ListIterator
<node
> iterator
= md_M_B
[bT
].begin(); iterator
.valid(); iterator
++)
782 md_nodeLength
[*iterator
] = 1;
785 //***************************************************************************
786 // 2. Set MinDepthMaxFace node lengths
787 //***************************************************************************
788 //create subgraph (block bT):
789 node nodeInBlock
= cH
;
790 if (nodeInBlock
== 0)
791 nodeInBlock
= (*(pBCTree
->hEdges(bT
).begin()))->source();
793 NodeArray
<MDMFLengthAttribute
> nodeLengthSG
;
794 EdgeArray
<MDMFLengthAttribute
> edgeLengthSG
;
795 NodeArray
<node
> nSG_to_nG
;
796 EdgeArray
<edge
> eSG_to_eG
;
798 ConnectedSubgraph
<MDMFLengthAttribute
>::call(
799 pBCTree
->auxiliaryGraph(), SG
,
800 nodeInBlock
, nodeInBlockSG
,
801 nSG_to_nG
, eSG_to_eG
,
802 mdmf_nodeLength
, nodeLengthSG
,
803 mdmf_edgeLength
, edgeLengthSG
);
805 //copy (0, 1)-min depth node lengths into nodeLengthSG d component and max
806 //face sice node lengths into l component:
807 forall_nodes(nSG
, SG
)
809 nodeLengthSG
[nSG
].d
= md_nodeLength
[nSG_to_nG
[nSG
]];
810 nodeLengthSG
[nSG
].l
= mf_nodeLength
[nSG_to_nG
[nSG
]];
814 //***************************************************************************
815 // 3. Compute embedding of block
816 //***************************************************************************
817 adjEntry m_adjExternal
= 0;
819 EmbedderMaxFaceBiconnectedGraphsLayers
<MDMFLengthAttribute
>::embed(
820 SG
, m_adjExternal
, nodeLengthSG
, edgeLengthSG
);
822 EmbedderMaxFaceBiconnectedGraphsLayers
<MDMFLengthAttribute
>::embed(
823 SG
, m_adjExternal
, nodeLengthSG
, edgeLengthSG
, nodeInBlockSG
);
825 //***************************************************************************
826 // 4. Copy block embedding into graph embedding and call recursively
827 // embedBlock for all cut vertices in bT
828 //***************************************************************************
829 CombinatorialEmbedding
CE(SG
);
830 face f
= CE
.leftFace(m_adjExternal
);
832 if (*pAdjExternal
== 0)
834 node on
= pBCTree
->original(nSG_to_nG
[m_adjExternal
->theNode()]);
835 adjEntry ae1
= on
->firstAdj();
836 for (adjEntry ae
= ae1
; ae
; ae
= ae
->succ())
838 if (ae
->theEdge() == pBCTree
->original(eSG_to_eG
[m_adjExternal
->theEdge()]))
840 *pAdjExternal
= ae
->twin();
846 bool DGcomputed
= false;
849 List
<node
>* p_fPG_to_nDG
;
850 NodeArray
<int>* p_nDG_to_fPG
;
851 NodeArray
< List
<adjEntry
> >* p_adjacencyList
;
852 List
< List
<adjEntry
> >* p_faces
;
853 NodeArray
<int>* p_distances
;
855 forall_nodes(nSG
, SG
)
857 node nH
= nSG_to_nG
[nSG
];
858 node nG
= pBCTree
->original(nH
);
859 adjEntry ae
= nSG
->firstAdj();
860 ListIterator
<adjEntry
>* pAfter
;
861 if (pBCTree
->bcproper(nG
) == cT
)
864 pAfter
= new ListIterator
<adjEntry
>();
866 if (pBCTree
->typeOfGNode(nG
) == BCTree::CutVertex
)
868 node cT2
= pBCTree
->bcproper(nG
);
869 bool no_recursion
= false;
872 node parent_bT_of_cT2
;
874 forall_adj_edges(e_cT2_to_bT2
, cT2
)
876 if (e_cT2_to_bT2
->source() == cT2
)
878 parent_bT_of_cT2
= e_cT2_to_bT2
->target();
882 if (treeNodeTreated
[parent_bT_of_cT2
])
888 //find adjacency entry of nSG which lies on external face f:
889 adjEntry aeFace
= f
->firstAdj();
892 if (aeFace
->theNode() == nSG
)
897 ae
= nSG
->firstAdj();
900 aeFace
= aeFace
->faceCycleSucc();
901 } while(aeFace
!= f
->firstAdj());
905 //(if exists) find adjacency entry of nSG which lies on external face f:
906 bool aeExtExists
= false;
907 adjEntry aeFace
= f
->firstAdj();
910 if (aeFace
->theNode() == nSG
)
915 ae
= nSG
->firstAdj();
919 aeFace
= aeFace
->faceCycleSucc();
920 } while(aeFace
!= f
->firstAdj());
927 p_fPG_to_nDG
= OGDF_NEW List
<node
>();
928 p_nDG_to_fPG
= OGDF_NEW NodeArray
<int>();
929 p_adjacencyList
= OGDF_NEW NodeArray
< List
<adjEntry
> >();
930 p_faces
= OGDF_NEW List
< List
<adjEntry
> >;
931 p_distances
= OGDF_NEW NodeArray
<int>;
934 //compute dual graph of skeleton graph:
935 p_adjacencyList
->init(SG
);
937 forall_nodes(nBG
, SG
)
940 forall_adj(ae_nBG
, nBG
)
941 (*p_adjacencyList
)[nBG
].pushBack(ae_nBG
);
944 NodeArray
< List
<adjEntry
> > adjEntryTreated(SG
);
945 forall_nodes(nBG
, SG
)
950 if (adjEntryTreated
[nBG
].search(adj
) != -1)
953 List
<adjEntry
> newFace
;
957 newFace
.pushBack(adj2
);
958 adjEntryTreated
[adj2
->theNode()].pushBack(adj2
);
959 node tn
= adj2
->twinNode();
960 int idx
= (*p_adjacencyList
)[tn
].search(adj2
->twin());
962 idx
= (*p_adjacencyList
)[tn
].size() - 1;
965 adj2
= *((*p_adjacencyList
)[tn
].get(idx
));
966 } while (adj2
!= adj
);
967 p_faces
->pushBack(newFace
);
969 } //forall_nodes(nBG, blockG[bT])
971 p_nDG_to_fPG
->init(*p_DG
);
973 for (ListIterator
< List
<adjEntry
> > it
= p_faces
->begin(); it
.valid(); it
++)
975 node nn
= p_DG
->newNode();
976 (*p_nDG_to_fPG
)[nn
] = p_fPG_to_nDG
->search(*(p_fPG_to_nDG
->pushBack(nn
)));
979 NodeArray
< List
<node
> > adjFaces(*p_DG
);
981 for (ListIterator
< List
<adjEntry
> > it
= p_faces
->begin(); it
.valid(); it
++)
984 for (ListIterator
<adjEntry
> it2
= (*it
).begin(); it2
.valid(); it2
++)
988 for (ListIterator
< List
<adjEntry
> > it3
= p_faces
->begin(); it3
.valid(); it3
++)
990 bool do_break
= false;
991 for (ListIterator
<adjEntry
> it4
= (*it3
).begin(); it4
.valid(); it4
++)
993 if ((*it4
) == (*it2
)->twin())
1006 && adjFaces
[*(p_fPG_to_nDG
->get(f1_id
))].search(*(p_fPG_to_nDG
->get(f2_id
))) == -1
1007 && adjFaces
[*(p_fPG_to_nDG
->get(f2_id
))].search(*(p_fPG_to_nDG
->get(f1_id
))) == -1)
1009 adjFaces
[*(p_fPG_to_nDG
->get(f1_id
))].pushBack(*(p_fPG_to_nDG
->get(f2_id
)));
1010 p_DG
->newEdge(*(p_fPG_to_nDG
->get(f1_id
)), *(p_fPG_to_nDG
->get(f2_id
)));
1013 if (*it2
== f
->firstAdj())
1015 } //for (ListIterator<adjEntry> it2 = (*it).begin(); it2.valid(); it2++)
1017 } //for (ListIterator< List<adjEntry> > it = faces.begin(); it.valid(); it++)
1019 //compute shortest path from every face to the external face:
1020 List
<edge
> DG_edges
;
1021 p_DG
->allEdges(DG_edges
);
1022 for (ListIterator
<edge
> it_e
= DG_edges
.begin(); it_e
.valid(); it_e
++)
1024 node s
= (*it_e
)->source();
1025 node t
= (*it_e
)->target();
1026 p_DG
->newEdge(t
, s
);
1028 ShortestPathWithBFM shortestPath
;
1029 node efDG
= *(p_fPG_to_nDG
->get(extFaceID
));
1030 EdgeArray
<int> el(*p_DG
, 1);
1031 p_distances
->init(*p_DG
);
1032 NodeArray
<edge
> pi(*p_DG
);
1033 shortestPath
.call(*p_DG
, efDG
, el
, *p_distances
, pi
);
1034 } //if (!DGcomputed)
1036 //choose face with minimal shortest path:
1037 List
<adjEntry
> optFace
;
1038 int optFaceDist
= -1;
1039 for (int fID
= 0; fID
< p_faces
->size(); fID
++)
1041 List
<adjEntry
> theFace
= *(p_faces
->get(fID
));
1043 bool contains_nSG
= false;
1044 for (ListIterator
<adjEntry
> it_ae
= theFace
.begin(); it_ae
.valid(); it_ae
++)
1046 if ((*it_ae
)->theNode() == nSG
)
1048 contains_nSG
= true;
1056 int thisDist
= (*p_distances
)[*p_fPG_to_nDG
->get(fID
)];
1057 if (optFaceDist
== -1 || optFaceDist
> thisDist
)
1060 optFaceDist
= thisDist
;
1062 ae
= ae_nSG
->succ();
1064 ae
= nSG
->firstAdj();
1067 } //for (int fID = 0; fID < faces.size(); fID++)
1068 } //if (!aeExtExists)
1071 forall_adj_edges(e_cT2_to_bT2
, cT2
)
1074 if (e_cT2_to_bT2
->source() == cT2
)
1075 bT2
= e_cT2_to_bT2
->target();
1077 bT2
= e_cT2_to_bT2
->source();
1078 if (!treeNodeTreated
[bT2
])
1079 embedBlock(bT2
, cT2
, *pAfter
);
1084 //embed all edges of block bT:
1085 bool after_ae
= true;
1086 for (adjEntry aeNode
= ae
;
1087 after_ae
|| aeNode
!= ae
;
1088 after_ae
= (!after_ae
|| !aeNode
->succ()) ? false : true,
1089 aeNode
= aeNode
->succ() ? aeNode
->succ() : nSG
->firstAdj())
1091 edge eG
= pBCTree
->original(eSG_to_eG
[aeNode
->theEdge()]);
1092 if (nG
== eG
->source())
1094 if (!pAfter
->valid())
1095 *pAfter
= newOrder
[nG
].pushBack(eG
->adjSource());
1097 *pAfter
= newOrder
[nG
].insertAfter(eG
->adjSource(), *pAfter
);
1099 else //!(nG == eG->source())
1101 if (!pAfter
->valid())
1102 *pAfter
= newOrder
[nG
].pushBack(eG
->adjTarget());
1104 *pAfter
= newOrder
[nG
].insertAfter(eG
->adjTarget(), *pAfter
);
1106 } //for (adjEntry aeNode = ae; aeNode; aeNode = aeNode->succ())
1108 if (!(*pAfter
== after
))
1110 } //forall_nodes(nSG, SG)
1115 delete p_fPG_to_nDG
;
1116 delete p_nDG_to_fPG
;
1117 delete p_adjacencyList
;
1123 } // end namespace ogdf