Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/graphs/planarity/graphK23Search.c
4091 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
#include "graph.h"
46
47
/* Imported functions */
48
49
extern void _FillVisitedFlags(graphP, int);
50
51
extern int _GetNextVertexOnExternalFace(graphP theGraph, int curVertex, int *pPrevLink);
52
extern int _OrientVerticesInBicomp(graphP theGraph, int BicompRoot, int PreserveSigns);
53
extern int _JoinBicomps(graphP theGraph);
54
55
extern int _MarkHighestXYPath(graphP theGraph);
56
57
extern int _FindUnembeddedEdgeToAncestor(graphP theGraph, int cutVertex, int *pAncestor, int *pDescendant);
58
extern int _FindUnembeddedEdgeToCurVertex(graphP theGraph, int cutVertex, int *pDescendant);
59
extern int _FindUnembeddedEdgeToSubtree(graphP theGraph, int ancestor, int SubtreeRoot, int *pDescendant);
60
61
extern int _MarkPathAlongBicompExtFace(graphP theGraph, int startVert, int endVert);
62
63
extern int _AddAndMarkEdge(graphP theGraph, int ancestor, int descendant);
64
65
extern int _DeleteUnmarkedVerticesAndEdges(graphP theGraph);
66
67
extern int _ChooseTypeOfNonOuterplanarityMinor(graphP theGraph, int I, int R);
68
extern int _IsolateOuterplanarityObstructionA(graphP theGraph);
69
extern int _IsolateOuterplanarityObstructionB(graphP theGraph);
70
71
/* Private function declarations for K_{2,3} searching */
72
73
int _SearchForK23(graphP theGraph, int I);
74
75
int _SearchForK23InBicomp(graphP theGraph, int I, int R);
76
int _IsolateOuterplanarityObstructionE1orE2(graphP theGraph);
77
int _IsolateOuterplanarityObstructionE3orE4(graphP theGraph);
78
79
/****************************************************************************
80
_SearchForK23()
81
We begin by identifying all root copies of I on which the
82
Walkdown failed. We can do this via straightforward traversal of
83
descendant to ancestor DFS tree paths. This is an O(n) total cost in the
84
worst case. If we find a K_{2,3}, then we can afford the time. However,
85
if we find only a K_4, then the outerplanarity algorithm must continue so
86
we could not afford the worst case performance. Fortunately, this
87
operation is worst-case constant time if there are no K_{2,3} homeomorphs
88
to be found in step I because a non-outerplanar biconnected graph either
89
contains a K_{2,3} or is \emph{isomorphic} to K_4.
90
****************************************************************************/
91
92
int _SearchForK23(graphP theGraph, int I)
93
{
94
int J, W, C, RetVal=OK;
95
96
/* Traverse the edges of I to find the unembedded forward edges to
97
descendants. For each such edge (I, W), traverse the DFS tree
98
path up to mark the child of I that is the root of the subtree
99
containing W. Optimize with visitation flag. */
100
101
/* Traverse each unembedded back edge to the descendant endpoint... */
102
103
J = theGraph->V[I].fwdArcList;
104
105
// Ensure we have at least one bicomp on which Walkdown failed, which
106
// should always be the case in an error free implementation
107
if (!gp_IsArc(theGraph, J))
108
return NOTOK;
109
110
while (J != NIL)
111
{
112
W = theGraph->G[J].v;
113
114
/* Go from the descendant endpoint to find the ancestor that
115
is a child of I, which in turn indicates the root of a
116
bicomp on which the Walkdown failed to embed all back edges */
117
118
C = W;
119
while (theGraph->V[C].DFSParent != I)
120
C = theGraph->V[C].DFSParent;
121
122
RetVal = _SearchForK23InBicomp(theGraph, I, C+theGraph->N);
123
124
/* If something went wrong, NOTOK was returned;
125
If a K_{2,3} was found, NONEMBEDDABLE was returned;
126
If OK was returned, then an isolated K_4 was found, so
127
we continue searching any other bicomps on which the
128
Walkdown failed. */
129
130
if (RetVal != OK)
131
break;
132
133
/* Get the next unembedded back edge from I */
134
135
J = gp_GetNextArc(theGraph, J);
136
if (J == theGraph->V[I].fwdArcList)
137
J = NIL;
138
}
139
140
/* If we got through the loop with an OK value for each bicomp on
141
which the Walkdown failed, then we return OK to indicate that only
142
isolated K_4's were found. This allows the embedder to continue.
143
If a K_{2,3} is ever found (or if an error occurred), then RetVal
144
will not be OK, and the loop terminates immediately so we can
145
return the appropriate value. */
146
147
return RetVal;
148
}
149
150
/****************************************************************************
151
_SearchForK23InBicomp()
152
****************************************************************************/
153
154
int _SearchForK23InBicomp(graphP theGraph, int I, int R)
155
{
156
isolatorContextP IC = &theGraph->IC;
157
int X, Y, XPrevLink, YPrevLink;
158
159
/* Begin by determining whether minor A, B or E is detected */
160
161
if (_ChooseTypeOfNonOuterplanarityMinor(theGraph, I, R) != OK)
162
return NOTOK;
163
164
/* Minors A and B result in the desired K_{2,3} homeomorph,
165
so we isolate it and return NONEMBEDDABLE. */
166
167
if (theGraph->IC.minorType & (MINORTYPE_A|MINORTYPE_B))
168
{
169
_FillVisitedFlags(theGraph, 0);
170
171
if (theGraph->IC.minorType & MINORTYPE_A)
172
{
173
if (_FindUnembeddedEdgeToCurVertex(theGraph, IC->w, &IC->dw) != TRUE)
174
return NOTOK;
175
176
if (_IsolateOuterplanarityObstructionA(theGraph) != OK)
177
return NOTOK;
178
}
179
else if (theGraph->IC.minorType & MINORTYPE_B)
180
{
181
int SubtreeRoot = LCGetPrev(theGraph->BicompLists,
182
theGraph->V[IC->w].pertinentBicompList, NIL);
183
184
if (_FindUnembeddedEdgeToSubtree(theGraph, IC->v, SubtreeRoot, &IC->dw) != TRUE)
185
return NOTOK;
186
187
if (_IsolateOuterplanarityObstructionB(theGraph) != OK)
188
return NOTOK;
189
}
190
191
if (_DeleteUnmarkedVerticesAndEdges(theGraph) != OK)
192
return NOTOK;
193
194
return NONEMBEDDABLE;
195
}
196
197
/* For minor E (a K_4) , we run the additional tests to see if a K_{2,3} is
198
entangled with the K_4. If not, then we return OK to indicate that
199
the outerplanarity embedder should proceed as if the K_4 had not
200
been found. */
201
202
/* If any vertices other than R, X, Y and W exist along the
203
external face, then we can obtain a K_{2,3} by minor E1 or E2 */
204
205
X = IC->x;
206
Y = IC->y;
207
XPrevLink = 1;
208
YPrevLink = 0;
209
if (IC->w != _GetNextVertexOnExternalFace(theGraph, X, &XPrevLink) ||
210
IC->w != _GetNextVertexOnExternalFace(theGraph, Y, &YPrevLink))
211
{
212
_FillVisitedFlags(theGraph, 0);
213
214
if (_IsolateOuterplanarityObstructionE1orE2(theGraph) != OK)
215
return NOTOK;
216
217
if (_DeleteUnmarkedVerticesAndEdges(theGraph) != OK)
218
return NOTOK;
219
220
return NONEMBEDDABLE;
221
}
222
223
/* If X, Y or W make either a direct back edge connection or a
224
connection through a separated child bicomp to an ancestor of
225
the current vertex I, then we can obtain a K_{2,3} by minor
226
E3 or E4. Note that this question is query on X, Y and W is
227
equivalent to the planarity version of external activity. */
228
229
if (FUTUREPERTINENT(theGraph, X, I) ||
230
FUTUREPERTINENT(theGraph, Y, I) ||
231
FUTUREPERTINENT(theGraph, IC->w, I))
232
{
233
_FillVisitedFlags(theGraph, 0);
234
235
if (_IsolateOuterplanarityObstructionE3orE4(theGraph) != OK)
236
return NOTOK;
237
238
if (_DeleteUnmarkedVerticesAndEdges(theGraph) != OK)
239
return NOTOK;
240
241
return NONEMBEDDABLE;
242
}
243
244
/* The extra cases for finding a K_{2,3} failed, so the bicomp rooted
245
by R is a separable subgraph of the input that is isomorphic
246
to K_4. So, we restore the original vertex orientation of
247
the bicomp (because it's polite, not because we really have to).
248
Then, we return OK to tell the outerplanarity embedder that it
249
can ignore this K_4 and keep processing. */
250
251
if (_OrientVerticesInBicomp(theGraph, R, 1) != OK)
252
return NOTOK;
253
254
return OK;
255
}
256
257
/****************************************************************************
258
_IsolateOuterplanarityObstructionE1orE2()
259
****************************************************************************/
260
261
int _IsolateOuterplanarityObstructionE1orE2(graphP theGraph)
262
{
263
isolatorContextP IC = &theGraph->IC;
264
int XPrevLink = 1;
265
266
if (_MarkHighestXYPath(theGraph) != TRUE)
267
return NOTOK;
268
269
/* Isolate E1 */
270
271
if (theGraph->IC.px != theGraph->IC.x)
272
{
273
if (_MarkPathAlongBicompExtFace(theGraph, IC->r, IC->w) != OK ||
274
_MarkPathAlongBicompExtFace(theGraph, IC->py, IC->r) != OK)
275
return NOTOK;
276
}
277
else if (theGraph->IC.py != theGraph->IC.y)
278
{
279
if (_MarkPathAlongBicompExtFace(theGraph, IC->r, IC->x) != OK ||
280
_MarkPathAlongBicompExtFace(theGraph, IC->w, IC->r) != OK)
281
return NOTOK;
282
}
283
284
/* Isolate E2 */
285
286
else if (IC->w != _GetNextVertexOnExternalFace(theGraph, IC->x, &XPrevLink))
287
{
288
if (_MarkPathAlongBicompExtFace(theGraph, IC->r, IC->y) != OK)
289
return NOTOK;
290
}
291
292
else
293
{
294
if (_MarkPathAlongBicompExtFace(theGraph, IC->x, IC->r) != OK)
295
return NOTOK;
296
}
297
298
/* Final bits are in common */
299
300
if (_FindUnembeddedEdgeToCurVertex(theGraph, IC->w, &IC->dw) != TRUE ||
301
theGraph->functions.fpMarkDFSPath(theGraph, IC->w, IC->dw) != OK ||
302
_JoinBicomps(theGraph) != OK ||
303
_AddAndMarkEdge(theGraph, IC->v, IC->dw) != OK)
304
return NOTOK;
305
306
return OK;
307
}
308
309
/****************************************************************************
310
_IsolateOuterplanarityObstructionE3orE4()
311
****************************************************************************/
312
313
int _IsolateOuterplanarityObstructionE3orE4(graphP theGraph)
314
{
315
isolatorContextP IC = &theGraph->IC;
316
int u, d, XorY;
317
318
/* Minor E3 */
319
320
if (FUTUREPERTINENT(theGraph, theGraph->IC.x, theGraph->IC.v) ||
321
FUTUREPERTINENT(theGraph, theGraph->IC.y, theGraph->IC.v))
322
{
323
if (_MarkHighestXYPath(theGraph) != TRUE)
324
return NOTOK;
325
326
if (FUTUREPERTINENT(theGraph, theGraph->IC.x, theGraph->IC.v))
327
XorY = theGraph->IC.x;
328
else XorY = theGraph->IC.y;
329
330
/* The cases of X externally active and Y externally active
331
are the same except for the bicomp external face marking
332
(because parameter order is important) */
333
334
if (XorY == theGraph->IC.x)
335
{
336
if (_MarkPathAlongBicompExtFace(theGraph, IC->x, IC->w) != OK ||
337
_MarkPathAlongBicompExtFace(theGraph, IC->y, IC->r) != OK)
338
return NOTOK;
339
}
340
else
341
{
342
if (_MarkPathAlongBicompExtFace(theGraph, IC->r, IC->x) != OK ||
343
_MarkPathAlongBicompExtFace(theGraph, IC->w, IC->y) != OK)
344
return NOTOK;
345
}
346
347
if (_FindUnembeddedEdgeToCurVertex(theGraph, IC->w, &IC->dw) != TRUE)
348
return NOTOK;
349
350
if (_FindUnembeddedEdgeToAncestor(theGraph, XorY, &u, &d) != TRUE)
351
return NOTOK;
352
353
if (theGraph->functions.fpMarkDFSPath(theGraph, u, IC->v) != OK ||
354
theGraph->functions.fpMarkDFSPath(theGraph, XorY, d) != OK ||
355
theGraph->functions.fpMarkDFSPath(theGraph, IC->w, IC->dw) != OK ||
356
_JoinBicomps(theGraph) != OK ||
357
_AddAndMarkEdge(theGraph, u, d) != OK ||
358
_AddAndMarkEdge(theGraph, IC->v, IC->dw) != OK)
359
return NOTOK;
360
361
return OK;
362
}
363
364
/* Otherwise, isolate Minor E4 (reduce to minor A) */
365
366
if (_FindUnembeddedEdgeToAncestor(theGraph, IC->w, &u, &d) != TRUE)
367
return NOTOK;
368
369
IC->v = u;
370
IC->dw = d;
371
return _IsolateOuterplanarityObstructionA(theGraph);
372
}
373
374