Title: On the Cutting Edge: Simplified On planarity by Edge Addition
1On the Cutting EdgeSimplified O(n) planarity by
Edge Addition
- John M. Boyer
- Wendy J. Myrvold
Slides prepared by Ying Wang
2Our Goal
- Definitions
- Planar graph A graph that admits a planar
drawing. - Planar embedding An equivalence class of planar
drawing, defined by the clockwise order of the
neighbors of each vertex. - Our main purpose
- Given a graph with N vertices, decide if the
graph is planar, and find a planar embedding if
it is planar. - We give an O(N) time complexity algorithm which
is both easy to understand and implement.
3A Big Picture
- We start by constructing a DFS tree, and then we
process vertex one by one according to the
reverse DFI order. - Processing a vertex v means to embed two type of
edges adjacent to v, namely the tree edges from v
to its DFS child, and the back edges from v to
its descendants. Notice that we dont embed edges
from v to its ancestors when processing v. - The key point is HOW TO PRESERVE PLANARITY when
adding edges?
4Intuition 1 Why Reverse DFI Order?
- The reason to use this order is that, when we
have a partial embedding, all the unprocessed
vertices will lie in the same face of this
embedding, because every two unprocessed vertices
are connected by a path which do not contain any
processed vertices. - By applying proper flipping techniques, we can
always let this face be the common external face
of the current embedding, thus we only need to
consider the external face of the current partial
embedding. This is a very nice property, and it
is analogous to the s-t numbering used by the
PQ-tree method.
5Big Picture Continued
- Now, since edges will be only added to the
external face of the current embedding,
preserving planarity is equivalent to letting
the externally active vertices stay on the outer
face. - By externally active vertices we mean those
vertices that will be involved in future
embedding. - So remember The key point of the algorithm is to
make externally active vertices stay on the
external face. Everything else is just to make
the runtime linear!
6Intuition 2 Biconnected Components
- Now we only care about the external face of the
current embedding, so we always search along the
external face. - Each biconnected component has a complete circle
as the outer face, and different biconnected
components correspond to different circles. - These circles are connected by cut vertices, and
it is hard to define the next vertex when we
are at a cut vertex. - Therefore, it is natural to consider biconnected
components.
7An illustration on biconnectivity
For a biconnected graph, it is easy to define the
next vertex on the external face when we have a
order either clockwise or counterclockwise
Not biconnected graph each biconnected component
has a bounding cycle, and these cycles are joined
by cut vertices.
8Biconnectivity Continued
- If a biconnected component has only two vertices,
it is helpful to view it as a cycle of two
parallel edges. Thus every biconnected component
has a bounding cycle.
9Illustration of the algorithm
- Now we have enough preliminaries to give a more
detailed picture of the algorithm. - When we process a vertex v, we first embed all
the tree edges. Then we perform two searches
along the external face, one in clockwise order
and one in counterclockwise order. If we find a
vertex that has a back edge to v, we embed this
edge and keep going if we encounter a stopping
vertex then we stop. - What is a stopping vertex? This will be explained
later.
10Embedding an edge
v
v
c
c
y
y
- We traverse along the external face in and find
y, so we embed the edge from y to v.
Two things happened after embedding the edge 1.
c is no longer a cut vertex. 2. We have a new
external face.
11Continued
v
v
c
c
y
y
- In the last picture, we may also traverse in
clockwise order, then the edge embedded will be
in the different direction.
12Observation
- Notice that in the last two pictures when we
embed an edge, the path on the external face we
traversed will NOT stay on the external face
after embedding the edge, which means it will not
be traversed in the future. This is essential for
achieving linear runtime. - This also indicates that the path we traversed
can not contain any externally active vertex
(with an exception that will be discussed later),
so we stop the traverse if we encounter an
externally active vertex.
13Embedding an Edge
- We talked about embedding an edge several
times. How do we actually embed an edge in the
code? - It is very easy. For each vertex we equip a list
recording its neighbors in clockwise order. At
first the list contains only the tree edge. If we
traverse in clockwise order and find an edge, the
vertex is added to the front of list if we
traverse in counterclockwise order then add it to
the back of the list. - The above process will be run on each child
biconnected component separately, and lists from
different child biconnected component can be
concatenated. (Illustration on next slide)
14Embedding Edges - Concatenation
v
- For each child biconnected component of v we can
get a list of edges adjacent to v. There are no
edges between different child biconnected
components, so the lists can be combined in any
order. However, we would like a particular order
(which is described later) to help future
embedding.
15Externally Activity
- When processing a vertex v, a processed vertex w
is called externally active if either it has a
back edge pointing to an ancestor of v, or there
is an externally active vertex in one of its
child biconnected components. - Notice that the second condition only applies
when the vertex has at least one child
biconnected components, i.e., it must be a cut
vertex. - We will use several pictures to illustrate these
two types of externally active vertices.
16Type 1
u
v
w
r
- We are processing v. u is an ancestor of v. w has
a back edge pointing to u so w is externally
active. Suppose we pass w and find r and embed
the edge from r to v, then there is no way for us
to embed the back edge of w. - Later on we will always use square nodes to
indicate externally active nodes, and dotted
lines for back edges.
17Type 2
u
v
p
s
r
w
- r has a path to an externally active vertex w, so
r is also externally active. If we pass r and
embed the edge from s to v, then we cant embed
the back edge of w in the future. - Notice p also has a path to w, but p is not a cut
vertex, so p is not externally active.
18How to determine external activity?
- For type-1, we can just check if it has a back
edge to the ancestor of v. - For type-2, we shall use the concept lowpoint
value. These will be discussed later.
19Algorithm Continued
- With the definition of external activity, we can
restate our algorithm again. - Perform a DFS on the graph.
- Process each vertex in the reverse DFI order.
- When processing v, for each DFS child of v, first
embed the tree edge, then descend to the DFS
child and perform two traverse along the external
face of the child biconnected component.
20Algorithm Continued
- During the traverse, if we find a back edge to v,
embed it. - If we encounter a cut vertex and some of its
child biconneted components has a back edge to v,
descend to the corresponding biconnected
component. - If we encounter a externally active vertex, stop
the traverse (with one exception to be discussed
later).
21An Example
v
v
w
w
r
The back edge from r to v is not embedded! The
graph is not planar.
Notice that we make copies of the cut vertex w in
each biconnected components.
We encounter a non-cut externally active vertex,
hence stop the traverse.
The other direction of traverse is performed
similarly.
22One Important Thing to Notice
- In the last picture we used the trick of
splitting the cut vertex into several copies in
each biconnected component containing it. The
generated copies are called virtual vertices or
virtual roots. We dont just create them to help
understanding. We do need them in the
implementation. - So, each cut vertex has several copies as virtual
roots (at the top of each child biconnected
components), and a non-root counterpart. - Hence later when we say descend, we always mean
going from the real vertex to a virtual copy, and
ascend means the other direction.
23Illustration
v
v
v
v
w
w
w
w
- With the help of virtual vertices and parallel
edges, each biconnected component has a bounding
cycle and the clockwise direction is well
defined. Notice the cut vertex w has two virtual
copies w and w, and a non-root counterpart w.
24Walkdown
- We call the above process Walkdown, which is a
process that traverses from top to bottom and
embeds back edges to v. Now we define this
process more precisely. - Definition
- Pertinent vertex A vertex is called pertinent if
either it has a back edge to v that is not yet
embedded, or there is a pertinent vertex in its
child biconnected components. - We can see that pertinent is analogous to
externally active, only that it has a back edge
to v instead of to an ancestor of v. A vertex can
be both pertinent and externally active.
25Walkdown continued
- Suppose we are currently traversing a vertex w,
there can be several different situations - If w is pertinent, we first embed the back edge
- If w is not externally active, go to the next
vertex on the external face - If w is externally active but not pertinent, stop
traversing - Otherwise w is a pertinent cut vertex, descend to
the child pertinent biconnected component.
26Some explanation
u
u
v
v
w
w
In this setting. w is both pertinent and
externally active. When visiting w, we first
embed the back edge. Now it is externally active
but not pertinent, thus a stopping vertex.
Now w has a pertinent vertex in its child
biconnected component, so it is still pertinent
after embedding the back edge, and we must
descend to its child biconnected component.
27Walkdown Continued
- A natural thing to ask is, if there are several
child pertinent biconnected components, which one
shall we descend to? We always descend to a
biconnected component that do not contain a
externally active vertex (we call it internally
active biconnected component) first. The reason
will be given in the next slide.
28Internally Active and Externally Active
v
w
- w has two pertinent child biconnected components.
If we descend to the one has an externally active
vertex, the traverse will terminate before going
back to w. Hence we should descend to the
internally active components first, and then
descend to the externally active components.
29Walkdown Continued
- In conclusion, the rule of descending to child
pertinent biconnected components can be
summarized as - First descend to internally active biconnected
components and embed edges (without possibility
of termination). - Then descend to an externally active biconnected
component (We are sure it will encounter a
stopping vertex there). - Notice we only perform two traverses, so we fail
to embed edges if there are more than two
externally active child biconnected components.
30Intuition What is internal activity
- If a biconnected component is internally active,
then it only have back edges to the vertex v
being processed. After processing v, we dont
need to care about it any more, so we can put
this component in the internal face of the
embedding. That is why we can always embed them
first. - Comparatively, an externally active component
must stay on the external face after process of v.
31Obtaining a New Direction after Descending
- Once we descend to a child biconnected component,
a natural thing to ask is, which direction do we
go? - The answer is We do NOT always keep the original
direction! Instead, we check what is the next
active vertex in each direction, and find the one
that interests us.
32Obtaining a Direction Continued
- We check the next active vertex in both sides,
and always go to an internally active vertex if
one exists otherwise, choose the direction that
leads to a pertinent vertex. If both directions
lead to non-pertinent externally active vertices,
obviously, we fail to embed some back edges and
we claim the graph must be non-planar. - In one sentence, we choose the direction that
TERMINATES AS LATE AS POSSIBLE.
33An Example
v
s
s
r
w
- w is both pertinent and externally active, and r
is internally active, so we pick r after
descending to s. - Notice that if we pick the other direction, after
embedding the back edge of w it becomes a
stopping vertex, hence we can not reach r, but we
can reach w if we go to r first. That is
terminate as late as possible.
34Walkdown Pseudo Code
- Now we are in the position to give the pseudo
code of walkdown - void walkdown(Biconnected component root r,
direction d) - c GetNextVertex(r,d)
- while (c ! r)
- if (c has a back edge to v) embed this edge
- if (c has pertinent child biconnected components)
- Perform walkdown for each internally active child
components - For each externally active child components,
compute new directions and walk down - If c has externally active child component
terminate - if (c is externally active) terminate
- c GetNextVertex(c,d)
35Example One
v
v
- Situation 1 No stopping vertex, the traverse is
ended when it return to the root.
36Example Two
v
r
w
s
- Here is another example. We descend to the
internally active vertex r first, and terminate
when we descend to w. But we are in trouble now,
the externally active w is not on the external
face, but this graph is indeed planar!
37Example Three
v
w
- In this setting, in order to embed both back
edges, we need to traverse in both directions.
38Example Four
v
w
w
r
- We traverse in counterclockwise order so the back
edge is embedded in this direction, but now we
block the externally active vertex r.
39Problems regarding walkdown
- In example two, we see that problems may arise
when embedding edges. This problem is solved by
arranging the child biconnected components in a
particular order. - In example four, we see another problem due to
the change of direction, i.e., we changed
direction at point w. Now the proper face
generated by embedding the back edge is no longer
the external path we traversed. This problem can
be fixed by flipping.
40Problem 1 Order of Children
v
r
w
s
- Recall that we always descend to the internally
active biconnected components first, so there can
be any externally active child biconnected
component on the left of a internally active
child biconnected component. - In the above picture, w is on the left of r, so
we cant let it happen.
41Order of Children - Continued
- Recall that the lowpoint value of a vertex is the
least DFI we can reach from that vertex by
walking along a sequence of tree edges and zero
or one back edge. - Observation The root of an internally active
biconnected component has lowpoint value equals
to the DFI of v an externally active biconnected
component will always have lowpoint less than v. - Therefore, we can order the DFS children of each
vertex in descending lowpoint order, then all the
internally active biconnected components will
stay on the left.
42Correct Order
v
v
s
w
r
w
s
r
43Problem 2 Merging and Flipping
v
v
w
w
w
s
r
s
r
- When we embed a back edge, biconnected components
along the path need to be merged, and some of
them need to be flipped before getting merged.
Notice that we maintain the adjacency list by
counterclockwise order, so flipping a vertex is
done by reversing this list and flipping a
component is done by flipping each vertex in the
component.
44Flipping
- When?
- If the direction of entering a cut vertex and the
direction of leaving its virtual copy is
opposite, then the child biconnected component
need to be flipped before merging. - How?
- A naïve way to do it is to simply invert the
adjacency list of each vertex in it.
45Merging
- Maintain a stack called merge stack. For each
descent record four things The cut vertex, the
direction we entered it, the virtual root, and
the direction we left the virtual root. - Each time we embed a back edge, everything in the
merge stack is merged and the merge stack is
cleared.
46Half-time Break
- Lets take a break and recall everything we have
gone through. We already have enough elements to
implement the algorithm now. - We shall begin with computing a DFS and lowpoint
values. For each vertex, sort its DFS children in
decreasing lowpoint order. - Then we process vertices one by one using reverse
DFI order, and perform walkdown in each child
biconnected component to embed back edges.
47Half-time Break
- Computing DFS and lowpoint is very simple. We
have also introduced how the walkdown routine
works, and when it terminates, and how to flip
and merge biconnected components. We can expect
the implementation to be SIMPLE. - All that is left is to make it run in linear
time, and to prove its correctness.
48Key elements to make it linear
- Walkdown We cant traverse the whole graph. We
hope the path we traversed could be assigned a
cost which we are able to manage. - Flipping There can be O(n) flippings in total
and each may take up to O(n) time. We want to
flip in O(1). - DFS and lowpoint calculation These are
well-known linear time routines.
49Linear-time Performance
- We start by a simple step How to determine
external activity in O(1)? Recalling the
definition of external activity, we know that a
vertex is externally active if and only if its
least ancestor lt v or some vertex in its child
biconnected components has lowpoint lt v. - So we are concerned with the problem that, for a
vertex w, what are the child biconnected
components of w?
50Example
w
w
w
a
b
c
- Consider the three DFS children of w. b is in the
same biconnected component as w, so only a and c
are considered in child biconnected components of
w.
51Deciding External Activity
- For each vertex w equip a list called
SeparatedDFSChildList. Initially it shall contain
all the DFS children of the vertex w. When a
child is merged with w, remove it from the list.
Hence the list always contain the DFS children of
w that are NOT in the same biconnected component
as w. - Notice the DFS children are sorted in decreasing
lowpoint order, so a vertex is externally active
if and only if its least ancestor lt v, or the
last vertex in its SeparatedDFSChildList has
lowpoint lt v.
52Flipping in O(1)
- The key observation here is we can still traverse
the external face if the adjacency of some
vertices are not inverted properly. - The reason is that each vertex has two neighbors
on the external face. We must go into the vertex
from one of those two, hence we always leave from
the other.
53Flipping in O(1)
s
r
t
- Suppose we are traversing the external face and
we are at s. We dont need to know which one of r
and t is on clockwise order. We just need to know
whether we come from s or t.
54Flipping in O(1)
- The previous observation means that we dont
really need to flip the adjacency list to run the
algorithm, we just need to know which vertices
are flipped. - Therefore, we flip a biconnected component by
just marking it.
55Flipping in O(1)
- Claim
- For each biconnected component, the virtual root
have exactly 1 DFS child in this biconnected
component. - Proof
- The root of a biconnected component has the least
DFI in it. If it has more than two DFS children
in the biconnected component, there can not be
any edge between the two DFS subtree, so the root
is a cut vertex and the component can not be
biconnected. It is also trivial to see it have at
least 1 DFS child, thus completing the proof.
56Flipping in O(1)
- To distinguish the virtual root with copies of it
in other biconnected components, we can assign
the virtual root with its only DFS child, so if
the root is w and its DFS child is c, we write
the virtual root as wc, and the edge between them
is called the root edge. See the next slide for
illustration.
57A Graph and the corresponding biconnected
components
0
0
01
1
12
1
2
26
2
6
6
3
5
5
3
34
7
4
7
4
58Flipping in O(1)
- Now we can flip in O(1). If we are merging w and
wc and the subtree rooted at wc need to be
flipped, then we flip only the root wc and merge
it with w, and we mark the root edge. - An important observation is that the subtree
rooted at wc is the same as the subtree rooted at
c (except for the vertex wc itself)!
59Flipping in O(1)
- We can summarize the flipping as
- Flip the virtual root so that it is properly
merged. - Mark the root edge associated with it.
- To restore which vertices are flipped after we
construct the whole embedding, just trace the
path from a vertex to the DFS root of the graph.
It is flipped if and only if this path has an odd
number of marked edges. - This can be done in O(n) by doing a DFS search
again.
60Walkup
- We are close to the O(n) performance now, but we
still need to fix some parts of the walkdown. - The first problem How do we check if a vertex is
pertinent? Recall that pertinent is defined
similarly as externally active, but we cant use
lowpoint value to decide pertinency now (why?). - Instead, we use a routine called walkup.
61Pertinent
- The idea of identifying pertinent vertices is
extremely simple If a vertex w has a back edge
to v, then it is pertinent, and every cut vertex
on the path from w to v is pertinent, so we trace
up along the external face and mark whenever we
ascend from a virtual root to its non-root
counterpart.
62vc
c
c
e
e
d
d
w
- Suppose w has a back edge to v. Then w is
pertinent, and if we trace up from w, we ascend
from d and c, so d and c are also pertinent.
Notice e is not pertinent.
63Walkup
- Specifically, for each non-virtual vertex we
equip a list called PertinentRoots to record the
roots of its pertinent child biconnected
components. Initialliy it is empty. During
walkup, if we ascend from wc to w, then wc is
added to the PertinentRoots list of w.
64Walkup
- We can trace up without worrying about runtime
because we know a path will never be used again
after embedding the back edge. The problem is,
from each vertex there are two paths leading to
the virtual root, and we dont know which one is
shorter. If we keep taking the longer one, the
runtime can become quadratic. - Fix Traverse in both directions SIMULTANEOUSLY,
and terminate the other direction if one
direction finds the virtual root. Thus the
runtime is exactly two times the shorter path.
65vc
vc
c
c
c
c
e
e
e
d
d
d
d
w
w
- This is an illustration of traversing both
directions simultaneously.
66Walkup Continued
- There is one last problem regarding walkup. We
might have several back edges pointing to v so we
need to do several walkups, but we dont want to
traverse the same path again and again. - Fix
- Equip a Visited flag for each vertex and simply
terminate the search in both directions when we
find a visited vertex.
67Walkdown Continued
- We are almost there. We can decide external
activity in O(1), and walkup, flipping, merging
all can be done in total time O(n). There is only
one last problem regarding walkdown. We claimed
that the path we traversed will not stay at the
external face after embedding the back edges. Is
that really the case?
68Problems of Walkdown
vc
c
c
c
s
s
p
p
Further more, the path between p and s is not
assigned a proper cost.
When we descend to w, both directions are
searched but only one is used.
- In this setting, p is pertinent and s is a
stopping vertex.
69Fix of Walkdown Short-circuit Edges
- The above two problems can be summarized as
- When descending to a child biconnected component,
both directions are searched, but only one is
used by us. - The cost of the path between the last back edge
endpoint we visited and the stopping vertex is
not handled. - We simply add an edge from vc to where we stop.
This type of edges is called short-circuit edges.
70Short-circuit Edges
vc
vc
c
c
c
c
s
s
p
p
71Short-circuit Edges
- Short-circuit edges do not change planarity.
- For each child biconnected component of v, at
most two short-circuit edges are added (one in
each direction), so the total number of
short-circuit edges added is O(n). - After we get the final embedding, we can remove
the short-circuit edges in O(n).
72One Last Exception
- What if a biconnected component has only
pertinent vertices but not stopping vertices?
Then we wont stop in this component and the cost
of some parts of the path is not assigned to a
new generated proper face. However, notice that
the component is pertinent but not externally
active, so after embedding the back edges it will
never be active again, and it will not be visited.
73Linear Time Performance
- Now everything is O(n), and the total runtime is
O(n)! We finally get there. - The remaining part will focus on the proof of
correctness. It is obvious that the algorithm
keeps planarity, so if we embed all edges, the
graph must be planar but can we claim that, if
the algorithm fails to embed some back edges, the
graph is definitely non-planar?
74Proof of Correctness
- The proof is done by contradiction, so we assume
after the walkdown process there are still some
back edges not embedded. - At a first glance, the walkdown process is messy
and there can be a lot of different situations.
We want to reduce the graph to something we can
handle.
75Reduction of non-active vertices
- The first observation is trivial, if a vertex is
not active (neither pertinent nor externally
active), we can remove it and connect its two
neighbors on the external face.
76Reduction of internally activebiconnected
components
- Suppose a vertex w has an internally active child
biconnected component. When we walkdown to w, we
first process the internally active child
biconnected component without possibility of
termination. This is just equivalent to the case
w has a back edge to v, hence we can get rid of
all internally active biconnected components.
77Case 1
- We know that the traverse will terminate if it
descends to a externally active pertinent
biconnected component, so the first case is we
have at least three such components. In this
case, it is impossible to visit all of them. - The next example shows that we have a K3,3 in
such case.
78Explanation of The Examples
- We will show an example for each kind of
non-planar condition. v denotes the current
vertex being processed, u denotes an ancestor of
v, a dotted line denotes a back edge to u or v,
and a real line denotes a path between nodes.
Paths denoted by different real lines do not
intersect.
79Case 1
u
v
r
c
a
b
80Case 2
- Now we can assume case 1 do not happen, so there
are at most two externally active pertinent
biconnected component. - Suppose there is a vertex w that has both a back
edge to u, and it also has an externally active
pertinent child biconnected component. - If we traverse to such a vertex, from the rule of
walkdown we should descend to the child
biconnected component.
81Case 2
u
v
w
- w has a back edge to u, but why we can still pass
w and descend to its child? The reason is w is a
cut vertex, so its back edge can be embedded in
both directions.
82Case 2
- In last picture, notice that once we descend to
the child of w and embed a back edge, we cant
descend to this child anymore. Otherwise we will
block w in both directions and it will be in the
internal face. - Now we show that if we cant embed all back edges
of the child biconnected component of w by
traversing it once, the graph is non-planar.
83Case 2.1
u
v
w
c
a
b
- a and c are separated by b so we cant embed both
edges in one pass. u,a,c,v,w,b is a K3,3
84Case 2.2
u
v
w
b
a
- Both a and b are pertinent and externally active,
so we cant visit both of them in one pass. This
is a K5.
85Case 2.3
- w may have two externally active pertinent child
biconnected component. If any of them needs more
than one pass, we have shown that the graph is
non-planar if both need one traverse and there
are no other externally active pertinent
biconnected component in the graph, then we can
embed all back edges if both need one traverse
and there are other components need traverse,
this goes to situation 1 where we have at least
three different externally active pertinent
biconnected components.
86Case 3
- According to case 2, we know that the failure of
embedding back edges caused by such a vertex w
will result in non-planarity, thus now we assume
such vertex w does not cause trouble, so we can
remove its child biconnected components and make
it a stopping vertex. - Case 3 is, one component needs two pass and
another component needs one pass. This is similar
to the case we have three components each need
one pass, and we can find K3,3 in this case.
87Case 4
- The last essentially different case is, a
pertinent vertex is blocked by two stopping
vertices in both direction, so we cant reach it
no matter how many traverses we make. This case
is illustrated in the next slide.
88Case 4
u
v
r
b
a
c
- c is blocked in both directions.
- u,r,c,v,a,b is a K3,3
89Proof of Correctness
- These four cases are indeed all what we need, so
we arrive at the final theorem. - Theorem
- Given a child biconnected component of v with
root vc, if the walkdown fails to embed a back
edge to v, then the graph is not planar.
90Conclusion
- The algorithm indeed computes a planar embedding
in linear time!
91Remarks
- This is really a very interesting algorithm. The
walk down part is actually answering the
following question If we are only allowed to
change direction at cut vertices and we always
terminate at stopping vertices, can we visit all
pertinent vertices by two walks? The walkdown
process suggests a greedy approach to this, and
we further show that this problem is equivalent
to planarity.
92Remarks Continued
- This algorithm is significantly simpler to
implement compared with other O(n) approaches. - If we only want O(n2) time complexity, we dont
need walkup, flipping in O(1), etc. Imagine how
simple the algorithm can be!