Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/graphs/planarity/graphIsolator.c
4079 views
1
/*
2
Planarity-Related Graph Algorithms Project
3
Copyright (c) 1997-2010, John M. Boyer
4
All rights reserved. Includes a reference implementation of the following:
5
6
* John M. Boyer. "Simplified O(n) Algorithms for Planar Graph Embedding,
7
Kuratowski Subgraph Isolation, and Related Problems". Ph.D. Dissertation,
8
University of Victoria, 2001.
9
10
* John M. Boyer and Wendy J. Myrvold. "On the Cutting Edge: Simplified O(n)
11
Planarity by Edge Addition". Journal of Graph Algorithms and Applications,
12
Vol. 8, No. 3, pp. 241-273, 2004.
13
14
* John M. Boyer. "A New Method for Efficiently Generating Planar Graph
15
Visibility Representations". In P. Eades and P. Healy, editors,
16
Proceedings of the 13th International Conference on Graph Drawing 2005,
17
Lecture Notes Comput. Sci., Volume 3843, pp. 508-511, Springer-Verlag, 2006.
18
19
Redistribution and use in source and binary forms, with or without modification,
20
are permitted provided that the following conditions are met:
21
22
* Redistributions of source code must retain the above copyright notice, this
23
list of conditions and the following disclaimer.
24
25
* Redistributions in binary form must reproduce the above copyright notice, this
26
list of conditions and the following disclaimer in the documentation and/or
27
other materials provided with the distribution.
28
29
* Neither the name of the Planarity-Related Graph Algorithms Project nor the names
30
of its contributors may be used to endorse or promote products derived from this
31
software without specific prior written permission.
32
33
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
34
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
35
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
36
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
37
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
38
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
39
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
40
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
41
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
42
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43
*/
44
45
#define GRAPHISOLATOR_C
46
47
#include "graph.h"
48
49
/* Imported functions */
50
51
extern void _FillVisitedFlags(graphP, int);
52
53
extern int _GetNextVertexOnExternalFace(graphP theGraph, int curVertex, int *pPrevLink);
54
extern int _JoinBicomps(graphP theGraph);
55
56
extern int _ChooseTypeOfNonplanarityMinor(graphP theGraph, int I, int R);
57
58
/* Private function declarations (exported within system) */
59
60
int _IsolateKuratowskiSubgraph(graphP theGraph, int I, int R);
61
62
int _FindUnembeddedEdgeToAncestor(graphP theGraph, int cutVertex,
63
int *pAncestor, int *pDescendant);
64
int _FindUnembeddedEdgeToCurVertex(graphP theGraph, int cutVertex,
65
int *pDescendant);
66
int _FindUnembeddedEdgeToSubtree(graphP theGraph, int ancestor,
67
int SubtreeRoot, int *pDescendant);
68
69
int _MarkPathAlongBicompExtFace(graphP theGraph, int startVert, int endVert);
70
71
int _AddAndMarkEdge(graphP theGraph, int ancestor, int descendant);
72
void _AddBackEdge(graphP theGraph, int ancestor, int descendant);
73
int _DeleteUnmarkedVerticesAndEdges(graphP theGraph);
74
75
int _InitializeIsolatorContext(graphP theGraph);
76
77
int _IsolateMinorA(graphP theGraph);
78
int _IsolateMinorB(graphP theGraph);
79
int _IsolateMinorC(graphP theGraph);
80
int _IsolateMinorD(graphP theGraph);
81
int _IsolateMinorE(graphP theGraph);
82
83
int _IsolateMinorE1(graphP theGraph);
84
int _IsolateMinorE2(graphP theGraph);
85
int _IsolateMinorE3(graphP theGraph);
86
int _IsolateMinorE4(graphP theGraph);
87
88
int _GetLeastAncestorConnection(graphP theGraph, int cutVertex);
89
int _MarkDFSPathsToDescendants(graphP theGraph);
90
int _AddAndMarkUnembeddedEdges(graphP theGraph);
91
92
/****************************************************************************
93
gp_IsolateKuratowskiSubgraph()
94
****************************************************************************/
95
96
int _IsolateKuratowskiSubgraph(graphP theGraph, int I, int R)
97
{
98
int RetVal;
99
100
/* A subgraph homeomorphic to K_{3,3} or K_5 will be isolated by using the visited
101
flags, 1=keep edge/vertex and 0=omit. Here we initialize to omit all, then we
102
subsequently set visited to 1 on all edges and vertices in the homeomorph. */
103
104
_FillVisitedFlags(theGraph, 0);
105
106
/* Next, we determine which of the non-planarity Minors was encountered
107
and the principal bicomp on which the isolator will focus attention. */
108
109
if (_ChooseTypeOfNonplanarityMinor(theGraph, I, R) != OK)
110
return NOTOK;
111
112
if (_InitializeIsolatorContext(theGraph) != OK)
113
return NOTOK;
114
115
/* Call the appropriate isolator */
116
117
if (theGraph->IC.minorType & MINORTYPE_A)
118
RetVal = _IsolateMinorA(theGraph);
119
else if (theGraph->IC.minorType & MINORTYPE_B)
120
RetVal = _IsolateMinorB(theGraph);
121
else if (theGraph->IC.minorType & MINORTYPE_C)
122
RetVal = _IsolateMinorC(theGraph);
123
else if (theGraph->IC.minorType & MINORTYPE_D)
124
RetVal = _IsolateMinorD(theGraph);
125
else if (theGraph->IC.minorType & MINORTYPE_E)
126
RetVal = _IsolateMinorE(theGraph);
127
else
128
RetVal = NOTOK;
129
130
/* Delete the unmarked edges and vertices, and return */
131
132
if (RetVal == OK)
133
RetVal = _DeleteUnmarkedVerticesAndEdges(theGraph);
134
135
return RetVal;
136
}
137
138
/****************************************************************************
139
_InitializeIsolatorContext()
140
****************************************************************************/
141
142
int _InitializeIsolatorContext(graphP theGraph)
143
{
144
isolatorContextP IC = &theGraph->IC;
145
146
/* Obtains the edges connecting X and Y to ancestors of the current vertex */
147
148
if (_FindUnembeddedEdgeToAncestor(theGraph, IC->x, &IC->ux, &IC->dx) != TRUE ||
149
_FindUnembeddedEdgeToAncestor(theGraph, IC->y, &IC->uy, &IC->dy) != TRUE)
150
return NOTOK;
151
152
/* For Minor B, we seek the last pertinent child biconnected component, which
153
is externally active, and obtain the DFS child in its root edge.
154
This child is the subtree root containing vertices with connections to
155
both the current vertex and an ancestor of the current vertex. */
156
157
if (theGraph->IC.minorType & MINORTYPE_B)
158
{
159
int SubtreeRoot = LCGetPrev(theGraph->BicompLists,
160
theGraph->V[IC->w].pertinentBicompList, NIL);
161
162
IC->uz = theGraph->V[SubtreeRoot].Lowpoint;
163
164
if (_FindUnembeddedEdgeToSubtree(theGraph, IC->v, SubtreeRoot, &IC->dw) != TRUE ||
165
_FindUnembeddedEdgeToSubtree(theGraph, IC->uz, SubtreeRoot, &IC->dz) != TRUE)
166
return NOTOK;
167
}
168
169
/* For all other minors, we obtain */
170
171
else
172
{
173
if (_FindUnembeddedEdgeToCurVertex(theGraph, IC->w, &IC->dw) != TRUE)
174
return NOTOK;
175
176
if (theGraph->IC.minorType & MINORTYPE_E)
177
if (_FindUnembeddedEdgeToAncestor(theGraph, IC->z, &IC->uz, &IC->dz) != TRUE)
178
return NOTOK;
179
}
180
181
return OK;
182
}
183
184
/****************************************************************************
185
_IsolateMinorA(): Isolate a K3,3 homeomorph
186
****************************************************************************/
187
188
int _IsolateMinorA(graphP theGraph)
189
{
190
isolatorContextP IC = &theGraph->IC;
191
192
if (_MarkPathAlongBicompExtFace(theGraph, IC->r, IC->r) != OK ||
193
theGraph->functions.fpMarkDFSPath(theGraph, MIN(IC->ux, IC->uy), IC->r) != OK ||
194
_MarkDFSPathsToDescendants(theGraph) != OK ||
195
_JoinBicomps(theGraph) != OK ||
196
_AddAndMarkUnembeddedEdges(theGraph) != OK)
197
return NOTOK;
198
199
return OK;
200
}
201
202
/****************************************************************************
203
_IsolateMinorB(): Isolate a K3,3 homeomorph
204
****************************************************************************/
205
206
int _IsolateMinorB(graphP theGraph)
207
{
208
isolatorContextP IC = &theGraph->IC;
209
210
if (_MarkPathAlongBicompExtFace(theGraph, IC->r, IC->r) != OK ||
211
theGraph->functions.fpMarkDFSPath(theGraph, MIN3(IC->ux,IC->uy,IC->uz),
212
MAX3(IC->ux,IC->uy,IC->uz)) != OK ||
213
_MarkDFSPathsToDescendants(theGraph) != OK ||
214
_JoinBicomps(theGraph) != OK ||
215
_AddAndMarkUnembeddedEdges(theGraph) != OK)
216
return NOTOK;
217
218
return OK;
219
}
220
221
/****************************************************************************
222
_IsolateMinorC(): Isolate a K3,3 homeomorph
223
****************************************************************************/
224
225
int _IsolateMinorC(graphP theGraph)
226
{
227
isolatorContextP IC = &theGraph->IC;
228
229
if (theGraph->G[IC->px].type == VERTEX_HIGH_RXW)
230
{
231
int highY = theGraph->G[IC->py].type == VERTEX_HIGH_RYW
232
? IC->py : IC->y;
233
if (_MarkPathAlongBicompExtFace(theGraph, IC->r, highY) != OK)
234
return NOTOK;
235
}
236
else
237
{
238
if (_MarkPathAlongBicompExtFace(theGraph, IC->x, IC->r) != OK)
239
return NOTOK;
240
}
241
242
if (_MarkDFSPathsToDescendants(theGraph) != OK ||
243
theGraph->functions.fpMarkDFSPath(theGraph, MIN(IC->ux, IC->uy), IC->r) != OK ||
244
_JoinBicomps(theGraph) != OK ||
245
_AddAndMarkUnembeddedEdges(theGraph) != OK)
246
return NOTOK;
247
248
return OK;
249
}
250
251
/****************************************************************************
252
_IsolateMinorD(): Isolate a K3,3 homeomorph
253
****************************************************************************/
254
255
int _IsolateMinorD(graphP theGraph)
256
{
257
isolatorContextP IC = &theGraph->IC;
258
259
if (_MarkPathAlongBicompExtFace(theGraph, IC->x, IC->y) != OK ||
260
theGraph->functions.fpMarkDFSPath(theGraph, MIN(IC->ux, IC->uy), IC->r) != OK ||
261
_MarkDFSPathsToDescendants(theGraph) != OK ||
262
_JoinBicomps(theGraph) != OK ||
263
_AddAndMarkUnembeddedEdges(theGraph) != OK)
264
return NOTOK;
265
266
return OK;
267
}
268
269
/****************************************************************************
270
_IsolateMinorE()
271
****************************************************************************/
272
273
int _IsolateMinorE(graphP theGraph)
274
{
275
isolatorContextP IC = &theGraph->IC;
276
277
/* Minor E1: Isolate a K3,3 homeomorph */
278
279
if (IC->z != IC->w)
280
return _IsolateMinorE1(theGraph);
281
282
/* Minor E2: Isolate a K3,3 homeomorph */
283
284
if (IC->uz > MAX(IC->ux, IC->uy))
285
return _IsolateMinorE2(theGraph);
286
287
/* Minor E3: Isolate a K3,3 homeomorph */
288
289
if (IC->uz < MAX(IC->ux, IC->uy) && IC->ux != IC->uy)
290
return _IsolateMinorE3(theGraph);
291
292
/* Minor E4: Isolate a K3,3 homeomorph */
293
294
else if (IC->x != IC->px || IC->y != IC->py)
295
return _IsolateMinorE4(theGraph);
296
297
/* Minor E: Isolate a K5 homeomorph */
298
299
if (_MarkPathAlongBicompExtFace(theGraph, IC->r, IC->r) != OK ||
300
theGraph->functions.fpMarkDFSPath(theGraph, MIN3(IC->ux, IC->uy, IC->uz), IC->r) != OK ||
301
_MarkDFSPathsToDescendants(theGraph) != OK ||
302
_JoinBicomps(theGraph) != OK ||
303
_AddAndMarkUnembeddedEdges(theGraph) != OK)
304
return NOTOK;
305
306
return OK;
307
}
308
309
/****************************************************************************
310
_IsolateMinorE1()
311
312
Reduce to Minor C if the vertex Z responsible for external activity
313
below the X-Y path does not equal the pertinent vertex W.
314
****************************************************************************/
315
316
int _IsolateMinorE1(graphP theGraph)
317
{
318
isolatorContextP IC = &theGraph->IC;
319
320
if (theGraph->G[IC->z].type == VERTEX_LOW_RXW)
321
{
322
theGraph->G[IC->px].type = VERTEX_HIGH_RXW;
323
IC->x=IC->z; IC->ux=IC->uz; IC->dx=IC->dz;
324
}
325
else if (theGraph->G[IC->z].type == VERTEX_LOW_RYW)
326
{
327
theGraph->G[IC->py].type = VERTEX_HIGH_RYW;
328
IC->y=IC->z; IC->uy=IC->uz; IC->dy=IC->dz;
329
}
330
else return NOTOK;
331
332
IC->z = IC->uz = IC->dz = NIL;
333
theGraph->IC.minorType ^= MINORTYPE_E;
334
theGraph->IC.minorType |= (MINORTYPE_C|MINORTYPE_E1);
335
return _IsolateMinorC(theGraph);
336
}
337
338
/****************************************************************************
339
_IsolateMinorE2()
340
341
If uZ (which is the ancestor of I that is adjacent to Z) is a
342
descendant of both uY and uX, then we reduce to Minor A
343
****************************************************************************/
344
345
int _IsolateMinorE2(graphP theGraph)
346
{
347
isolatorContextP IC = &theGraph->IC;
348
349
_FillVisitedFlags(theGraph, 0);
350
351
IC->v = IC->uz;
352
IC->dw = IC->dz;
353
IC->z = IC->uz = IC->dz = NIL;
354
355
theGraph->IC.minorType ^= MINORTYPE_E;
356
theGraph->IC.minorType |= (MINORTYPE_A|MINORTYPE_E2);
357
return _IsolateMinorA(theGraph);
358
}
359
360
/****************************************************************************
361
_IsolateMinorE3()
362
****************************************************************************/
363
364
int _IsolateMinorE3(graphP theGraph)
365
{
366
isolatorContextP IC = &theGraph->IC;
367
368
if (IC->ux < IC->uy)
369
{
370
if (_MarkPathAlongBicompExtFace(theGraph, IC->r, IC->px) != OK ||
371
_MarkPathAlongBicompExtFace(theGraph, IC->w, IC->y) != OK)
372
return NOTOK;
373
}
374
else
375
{
376
if (_MarkPathAlongBicompExtFace(theGraph, IC->x, IC->w) != OK ||
377
_MarkPathAlongBicompExtFace(theGraph, IC->py, IC->r) != OK)
378
return NOTOK;
379
}
380
381
if (theGraph->functions.fpMarkDFSPath(theGraph, MIN3(IC->ux, IC->uy, IC->uz), IC->r) != OK ||
382
_MarkDFSPathsToDescendants(theGraph) != OK ||
383
_JoinBicomps(theGraph) != OK ||
384
_AddAndMarkUnembeddedEdges(theGraph) != OK)
385
return NOTOK;
386
387
theGraph->IC.minorType |= MINORTYPE_E3;
388
return OK;
389
}
390
391
/****************************************************************************
392
_IsolateMinorE4()
393
****************************************************************************/
394
395
int _IsolateMinorE4(graphP theGraph)
396
{
397
isolatorContextP IC = &theGraph->IC;
398
399
if (IC->px != IC->x)
400
{
401
if (_MarkPathAlongBicompExtFace(theGraph, IC->r, IC->w) != OK ||
402
_MarkPathAlongBicompExtFace(theGraph, IC->py, IC->r) != OK)
403
return NOTOK;
404
}
405
else
406
{
407
if (_MarkPathAlongBicompExtFace(theGraph, IC->r, IC->px) != OK ||
408
_MarkPathAlongBicompExtFace(theGraph, IC->w, IC->r) != OK)
409
return NOTOK;
410
}
411
412
if (theGraph->functions.fpMarkDFSPath(theGraph, MIN3(IC->ux, IC->uy, IC->uz),
413
MAX3(IC->ux, IC->uy, IC->uz)) != OK ||
414
_MarkDFSPathsToDescendants(theGraph) != OK ||
415
_JoinBicomps(theGraph) != OK ||
416
_AddAndMarkUnembeddedEdges(theGraph) != OK)
417
return NOTOK;
418
419
theGraph->IC.minorType |= MINORTYPE_E4;
420
return OK;
421
}
422
423
/****************************************************************************
424
_GetLeastAncestorConnection()
425
426
This function searches for an ancestor of the current vertex I adjacent by a
427
cycle edge to the given cutVertex or one of its DFS descendants appearing in
428
a separated bicomp. The given cutVertex is assumed to be externally active
429
such that either the leastAncestor or the lowpoint of a separated DFS child
430
is less than I. We obtain the minimum possible connection from the cutVertex
431
to an ancestor of I.
432
NOTE: the separatedDFSChildList is sorted by lowpoint, so the first entry
433
has the lowest lowpoint, i.e. is the "most" externally active.
434
This is why we only need to look at the first entry.
435
****************************************************************************/
436
437
int _GetLeastAncestorConnection(graphP theGraph, int cutVertex)
438
{
439
int subtreeRoot = theGraph->V[cutVertex].separatedDFSChildList;
440
int ancestor = theGraph->V[cutVertex].leastAncestor;
441
442
if (subtreeRoot != NIL &&
443
ancestor > theGraph->V[subtreeRoot].Lowpoint)
444
ancestor = theGraph->V[subtreeRoot].Lowpoint;
445
446
return ancestor;
447
}
448
449
/****************************************************************************
450
_FindUnembeddedEdgeToAncestor()
451
452
This function searches for an ancestor of the current vertex I adjacent by a
453
cycle edge to the given cutVertex or one of its DFS descendants appearing in
454
a separated bicomp.
455
456
The given cutVertex is assumed to be externally active such that either the
457
leastAncestor or the lowpoint of a separated DFS child is less than I.
458
We obtain the minimum possible connection from the cutVertex to an ancestor
459
of I, then compute the descendant accordingly.
460
461
NOTE: the separatedDFSChildList is sorted by lowpoint, so the first entry
462
has the lowest lowpoint, i.e. is the "most" externally active.
463
This is why we only need to look at the first entry. Even if the
464
cutVertex is externally active but pertinent, any internally active
465
pertinent child bicomps would be later in the separatedDFSChildList
466
because their internal activity suggests a higher lowpoint value.
467
468
Returns TRUE if found, FALSE otherwise.
469
****************************************************************************/
470
471
int _FindUnembeddedEdgeToAncestor(graphP theGraph, int cutVertex,
472
int *pAncestor, int *pDescendant)
473
{
474
*pAncestor = _GetLeastAncestorConnection(theGraph, cutVertex);
475
476
if (*pAncestor == theGraph->V[cutVertex].leastAncestor)
477
{
478
*pDescendant = cutVertex;
479
return TRUE;
480
}
481
else
482
{
483
int subtreeRoot = theGraph->V[cutVertex].separatedDFSChildList;
484
485
return _FindUnembeddedEdgeToSubtree(theGraph, *pAncestor,
486
subtreeRoot, pDescendant);
487
}
488
}
489
490
/****************************************************************************
491
_FindUnembeddedEdgeToCurVertex()
492
493
Given the current vertex I, we search for an edge connecting I to either
494
a given pertinent vertex W or one of its DFS descendants in the subtree
495
indicated by the the last pertinent child biconnected component.
496
Returns TRUE if founds, FALSE otherwise.
497
****************************************************************************/
498
499
int _FindUnembeddedEdgeToCurVertex(graphP theGraph, int cutVertex, int *pDescendant)
500
{
501
int RetVal = TRUE, I = theGraph->IC.v;
502
503
if (theGraph->V[cutVertex].adjacentTo != NIL)
504
*pDescendant = cutVertex;
505
else
506
{
507
int subtreeRoot = theGraph->V[cutVertex].pertinentBicompList;
508
509
RetVal = _FindUnembeddedEdgeToSubtree(theGraph, I,
510
subtreeRoot, pDescendant);
511
}
512
513
return RetVal;
514
}
515
516
/****************************************************************************
517
_FindUnembeddedEdgeToSubtree()
518
519
Given the root vertex of a DFS subtree and an ancestor of that subtree,
520
find a vertex in the subtree that is adjacent to the ancestor by a
521
cycle edge.
522
Returns TRUE if found, FALSE if not found.
523
****************************************************************************/
524
525
int _FindUnembeddedEdgeToSubtree(graphP theGraph, int ancestor,
526
int SubtreeRoot, int *pDescendant)
527
{
528
int J, Z, ZNew;
529
530
*pDescendant = NIL;
531
532
/* If SubtreeRoot is a root copy, then we change to the DFS child in the
533
DFS tree root edge of the bicomp rooted by SubtreeRoot. */
534
535
if (SubtreeRoot >= theGraph->N)
536
SubtreeRoot -= theGraph->N;
537
538
/* Find the least descendant of the cut vertex incident to the ancestor. */
539
540
J = theGraph->V[ancestor].fwdArcList;
541
while (gp_IsArc(theGraph, J))
542
{
543
if (theGraph->G[J].v >= SubtreeRoot)
544
{
545
if (*pDescendant == NIL || *pDescendant > theGraph->G[J].v)
546
*pDescendant = theGraph->G[J].v;
547
}
548
549
J = gp_GetNextArc(theGraph, J);
550
if (J == theGraph->V[ancestor].fwdArcList)
551
J = NIL;
552
}
553
554
if (*pDescendant == NIL)
555
return FALSE;
556
557
/* Make sure the identified descendant actually descends from the cut vertex */
558
559
Z = *pDescendant;
560
while (Z != SubtreeRoot)
561
{
562
ZNew = theGraph->V[Z].DFSParent;
563
if (ZNew == NIL || ZNew == Z)
564
return FALSE;
565
Z = ZNew;
566
}
567
568
/* Return successfully */
569
570
return TRUE;
571
}
572
573
574
/****************************************************************************
575
_MarkPathAlongBicompExtFace()
576
577
Sets the visited flags of vertices and edges on the external face of a
578
bicomp from startVert to endVert, inclusive, by following the 'first' arc
579
link out of each visited vertex.
580
****************************************************************************/
581
582
int _MarkPathAlongBicompExtFace(graphP theGraph, int startVert, int endVert)
583
{
584
int Z, ZPrevLink, ZPrevArc;
585
586
/* Mark the start vertex (and if it is a root copy, mark the parent copy too. */
587
588
theGraph->G[startVert].visited = 1;
589
590
/* For each vertex visited after the start vertex, mark the vertex and the
591
edge used to get there. Stop after marking the ending vertex. */
592
593
Z = startVert;
594
ZPrevLink = 1;
595
do {
596
Z = _GetNextVertexOnExternalFace(theGraph, Z, &ZPrevLink);
597
598
ZPrevArc = gp_GetArc(theGraph, Z, ZPrevLink);
599
600
theGraph->G[ZPrevArc].visited = 1;
601
theGraph->G[gp_GetTwinArc(theGraph, ZPrevArc)].visited = 1;
602
theGraph->G[Z].visited = 1;
603
604
} while (Z != endVert);
605
606
return OK;
607
}
608
609
/****************************************************************************
610
_MarkDFSPath()
611
612
Sets visited flags of vertices and edges from descendant to ancestor,
613
including root copy vertices, and including the step of hopping from
614
a root copy to its parent copy.
615
616
The DFSParent of a vertex indicates the next vertex to visit, so we
617
search the adjacency list looking for the edge leading either to the
618
DFSParent or to a root copy of the DFSParent. We start by marking the
619
descendant, then traverse up the DFS tree, stopping after we mark
620
the ancestor.
621
****************************************************************************/
622
623
int _MarkDFSPath(graphP theGraph, int ancestor, int descendant)
624
{
625
int J, parent, Z, N;
626
627
N = theGraph->N;
628
629
/* If we are marking from a root vertex upward, then go up to the parent
630
copy before starting the loop */
631
632
if (descendant >= N)
633
descendant = theGraph->V[descendant-N].DFSParent;
634
635
/* Mark the lowest vertex (i.e. the descendant with the highest number) */
636
theGraph->G[descendant].visited = 1;
637
638
/* Mark all ancestors of the lowest vertex, and the edges used to reach
639
them, up to the given ancestor vertex. */
640
641
while (descendant != ancestor)
642
{
643
/* Get the parent vertex */
644
645
parent = theGraph->V[descendant].DFSParent;
646
647
/* If the descendant was a DFS tree root, then obviously
648
we aren't going to find the ancestor, so something is wrong.*/
649
650
if (parent == NIL || parent == descendant)
651
return NOTOK;
652
653
/* Find the edge from descendant that leads either to
654
parent or to a root copy of the parent.
655
When the edge is found, mark it and break the loop */
656
657
J = gp_GetFirstArc(theGraph, descendant);
658
while (gp_IsArc(theGraph, J))
659
{
660
Z = theGraph->G[J].v;
661
if ((Z < N && Z == parent) ||
662
(Z >= N && theGraph->V[Z-N].DFSParent == parent))
663
{
664
theGraph->G[J].visited = 1;
665
theGraph->G[gp_GetTwinArc(theGraph, J)].visited = 1;
666
break;
667
}
668
J = gp_GetNextArc(theGraph, J);
669
}
670
671
/* Mark the parent copy of the DFS parent */
672
theGraph->G[parent].visited = 1;
673
674
/* Hop to the parent */
675
descendant = parent;
676
}
677
678
return OK;
679
}
680
681
/****************************************************************************
682
_MarkDFSPathsToDescendants()
683
****************************************************************************/
684
685
int _MarkDFSPathsToDescendants(graphP theGraph)
686
{
687
isolatorContextP IC = &theGraph->IC;
688
689
if (theGraph->functions.fpMarkDFSPath(theGraph, IC->x, IC->dx) != OK ||
690
theGraph->functions.fpMarkDFSPath(theGraph, IC->y, IC->dy) != OK)
691
return NOTOK;
692
693
if (IC->dw != NIL)
694
if (theGraph->functions.fpMarkDFSPath(theGraph, IC->w, IC->dw) != OK)
695
return NOTOK;
696
697
if (IC->dz != NIL)
698
if (theGraph->functions.fpMarkDFSPath(theGraph, IC->w, IC->dz) != OK)
699
return NOTOK;
700
701
return OK;
702
}
703
704
/****************************************************************************
705
_AddAndMarkUnembeddedEdges()
706
****************************************************************************/
707
708
int _AddAndMarkUnembeddedEdges(graphP theGraph)
709
{
710
isolatorContextP IC = &theGraph->IC;
711
712
if (_AddAndMarkEdge(theGraph, IC->ux, IC->dx) != OK ||
713
_AddAndMarkEdge(theGraph, IC->uy, IC->dy) != OK)
714
return NOTOK;
715
716
if (IC->dw != NIL)
717
if (_AddAndMarkEdge(theGraph, IC->v, IC->dw) != OK)
718
return NOTOK;
719
720
if (IC->dz != NIL)
721
if (_AddAndMarkEdge(theGraph, IC->uz, IC->dz) != OK)
722
return NOTOK;
723
724
return OK;
725
}
726
727
/****************************************************************************
728
_AddAndMarkEdge()
729
730
Adds edge records for the edge (ancestor, descendant) and marks the edge
731
records and vertex structures that represent the edge.
732
****************************************************************************/
733
734
int _AddAndMarkEdge(graphP theGraph, int ancestor, int descendant)
735
{
736
_AddBackEdge(theGraph, ancestor, descendant);
737
738
/* Mark the edge so it is not deleted */
739
740
theGraph->G[ancestor].visited = 1;
741
theGraph->G[gp_GetFirstArc(theGraph, ancestor)].visited = 1;
742
theGraph->G[gp_GetFirstArc(theGraph, descendant)].visited = 1;
743
theGraph->G[descendant].visited = 1;
744
745
return OK;
746
}
747
748
/****************************************************************************
749
_AddBackEdge()
750
751
This function transfers the edge records for the edge between the ancestor
752
and descendant from the forward edge list of the ancestor to the adjacency
753
lists of the ancestor and descendant.
754
****************************************************************************/
755
756
void _AddBackEdge(graphP theGraph, int ancestor, int descendant)
757
{
758
int fwdArc, backArc;
759
760
/* We get the two edge records of the back edge to embed. */
761
762
fwdArc = theGraph->V[ancestor].fwdArcList;
763
while (gp_IsArc(theGraph, fwdArc))
764
{
765
if (theGraph->G[fwdArc].v == descendant)
766
break;
767
768
fwdArc = gp_GetNextArc(theGraph, fwdArc);
769
if (fwdArc == theGraph->V[ancestor].fwdArcList)
770
fwdArc = NIL;
771
}
772
773
if (fwdArc == NIL)
774
return;
775
776
backArc = gp_GetTwinArc(theGraph, fwdArc);
777
778
/* The forward arc is removed from the fwdArcList of the ancestor. */
779
if (theGraph->V[ancestor].fwdArcList == fwdArc)
780
{
781
if (gp_GetNextArc(theGraph, fwdArc) == fwdArc)
782
theGraph->V[ancestor].fwdArcList = NIL;
783
else theGraph->V[ancestor].fwdArcList = gp_GetNextArc(theGraph, fwdArc);
784
}
785
786
gp_SetNextArc(theGraph, gp_GetPrevArc(theGraph, fwdArc), gp_GetNextArc(theGraph, fwdArc));
787
gp_SetPrevArc(theGraph, gp_GetNextArc(theGraph, fwdArc), gp_GetPrevArc(theGraph, fwdArc));
788
789
/* The forward arc is added to the adjacency list of the ancestor. */
790
gp_SetPrevArc(theGraph, fwdArc, gp_AdjacencyListEndMark(ancestor));
791
gp_SetNextArc(theGraph, fwdArc, gp_GetFirstArc(theGraph, ancestor));
792
gp_SetPrevArc(theGraph, gp_GetFirstArc(theGraph, ancestor), fwdArc);
793
gp_SetFirstArc(theGraph, ancestor, fwdArc);
794
795
/* The back arc is added to the adjacency list of the descendant. */
796
gp_SetPrevArc(theGraph, backArc, gp_AdjacencyListEndMark(descendant));
797
gp_SetNextArc(theGraph, backArc, gp_GetFirstArc(theGraph, descendant));
798
gp_SetPrevArc(theGraph, gp_GetFirstArc(theGraph, descendant), backArc);
799
gp_SetFirstArc(theGraph, descendant, backArc);
800
801
theGraph->G[backArc].v = ancestor;
802
}
803
804
/****************************************************************************
805
_DeleteUnmarkedVerticesAndEdges()
806
807
For each vertex, traverse its adjacency list and delete all unvisited edges.
808
****************************************************************************/
809
810
int _DeleteUnmarkedVerticesAndEdges(graphP theGraph)
811
{
812
int I, J, fwdArc, descendant;
813
814
/* All of the forward and back arcs of all of the edge records
815
were removed from the adjacency lists in the planarity algorithm
816
preprocessing. We now put them back into the adjacency lists
817
(and we do not mark them), so they can be properly deleted below. */
818
819
for (I = 0; I < theGraph->N; I++)
820
{
821
while (theGraph->V[I].fwdArcList != NIL)
822
{
823
fwdArc = theGraph->V[I].fwdArcList;
824
descendant = theGraph->G[fwdArc].v;
825
_AddBackEdge(theGraph, I, descendant);
826
}
827
}
828
829
/* Now we delete all unmarked edges. We don't delete vertices
830
from the embedding, but the ones we should delete will become
831
degree zero. */
832
833
for (I = 0; I < theGraph->N; I++)
834
{
835
J = gp_GetFirstArc(theGraph, I);
836
while (gp_IsArc(theGraph, J))
837
{
838
if (theGraph->G[J].visited)
839
J = gp_GetNextArc(theGraph, J);
840
else J = gp_DeleteEdge(theGraph, J, 0);
841
}
842
}
843
844
return OK;
845
}
846
847