planar.tex
上传用户:gzelex
上传日期:2007-01-07
资源大小:707k
文件大小:71k
开发平台:

MultiPlatform

  1. input cwebmac
  2. documentstyle[comments,a4,psfig]{cweb}
  3. typeout{TransFig: figure text in LaTeX.}
  4. typeout{TransFig: figures in PostScript.}
  5. begingroupmakeatletter
  6. % extract first six characters in fmtname
  7. defx#1#2#3#4#5#6#7relax{defx{#1#2#3#4#5#6}}
  8. expandafterxfmtname xxxxxxrelax defy{splain}
  9. endgroup
  10. endinput
  11. voffset=-0.5cm
  12. textwidth 14cm
  13. oddsidemargin          0.4cm
  14. evensidemargin         1.4cm
  15. marginparwidth 1.9cm
  16. marginparsep 0.4cm
  17. marginparpush 0.4cm
  18. topmargin 0cm
  19. headsep 1.5cm
  20. textheight 21.5cm
  21. footskip 2.2cm
  22. begin{document}
  23. thispagestyle{empty}
  24. renewcommand{thefootnote}{fnsymbol{footnote}}
  25. title{An Implementation of the Hopcroft and Tarjan Planarity Test and
  26. Embedding Algorithm}
  27. thanks{This work was supported in part by the German Ministry for Research
  28. and Technology (Bundesministerium fuer Forschung und Technologie) under
  29. grant ITS 9103 and by the ESPRIT Basic Research Actions Program under
  30. contract No. 7141 (project ALCOM II).}
  31. author{Kurt Mehlhorn\
  32.         {footnotesize  Max-Planck-Institut fuer Informatik,}\[-0.7ex]
  33.     {footnotesize 66123 Saarbruecken, Germany}\[0.7ex]
  34. and Petra Mutzel\
  35.         {footnotesize  Institut fuer Informatik,}\[-0.7ex]
  36. {footnotesize Universitaet zu Koeln, 50969 Koeln}\[0.7ex]
  37. and Stefan Naeher\
  38.         {footnotesize  Max-Planck-Institut fuer Informatik,}\[-0.7ex]
  39.     {footnotesize 66123 Saarbruecken, Germany}\[0.7ex]}
  40.         date{}
  41.         maketitle
  42. setcounter{page}{0}
  43. thispagestyle{empty}
  44. %%%%%%% Abstract %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  45. vspace*{2.2cm}
  46. begin{abstract}
  47. We describe an implementation of the Hopcroft and Tarjan planarity test and
  48. embedding algorithm. The program tests the planarity of the input
  49. graph and either constructs a combinatorial embedding (if the graph
  50. is planar) or exhibits a Kuratowski subgraph (if the graph is non-planar).
  51. end{abstract}
  52. tableofcontents
  53. N{1}{1}Introduction.
  54. We descibe two procedures to test the planarity of a graph PB{|G}:
  55. begin{center}
  56. PB{&{bool} \{planar}(&{graph} ${}{AND}|G,{}$&{bool} \{embed}${}K%
  57. \{false})$}
  58. end{center}
  59. and
  60. begin{center}
  61. PB{&{bool} \{planar}(&{graph} ${}{AND}|G,&{list}langle&{edge}%
  62. rangle{}$ ${}{AND}|P,{}$&{bool} \{embed}${}K\{false})$}.
  63. end{center}
  64. Both take a directed graph PB{|G} and test it for planarity.
  65. If the graph is planar and bidirected, i.e., for every edge of PB{|G} its
  66. reversal is also in PB{|G}, and the argument PB{\{embed}} is true, then
  67. they
  68. also compute a combinatorial embedding of PB{|G} (by suitably reordering
  69. its adjacency lists). If the graph PB{|G} is
  70. non-planar then the first version of PB{\{planar}} only records that fact.
  71. The second version in addition returns a subgraph of PB{|G} homeomorphic
  72. to $K_{3,3}$ or $K_5$ (as a list PB{|P} of edges). For a planar graph
  73. PB{|G} the running time of
  74. both versions is linear (cf. section ref{Efficiency} for more
  75. detailed information). For non-planar graphs PB{|G} the
  76. first version runs in linear time but the second version runs in
  77. quadratic time.
  78. We are aware of the linear time algorithm of Williamson
  79. cite{Williamson:Kuratowski} to find Kuratowski subgraphs but have
  80. not implemented it.
  81. The implementation of PB{\{planar}} is based on the LEDA platform of
  82. combinatorial
  83. and geometric computing cite{LEDA-Manual,Mehlhorn-Naeher:LEDA}. It is part of
  84. the LEDA-distribution (available through anonymous ftp at cs.uni-sb.de). In
  85. this document we describe the implementation of both versions of PB{%
  86. \{planar}} and
  87. a demo, and report on our experimental experience.
  88. Procedure PB{\{planar}} is based on the
  89. Hopcroft and Tarjan linear time planarity testing algorithm as
  90. described in cite[section IV.10]{Me:book}. For the sequel we assume
  91. knowledge of section IV.10 of cite{Me:book}. A revised version of that section
  92. is included in this document (see section ref{reprint}) for the convenience
  93. of the reader. Our procedure PB{\{planar}} differs from cite[section
  94. IV.10]{Me:book}
  95. in two respects: Firstly, it works for arbitrary directed graphs and
  96. not only for biconnected
  97. undirected graphs. To this end we augment the input graph by additional edges
  98. to make it biconnected and bidirected. The augmentation does not destroy
  99. planarity. Secondly, the embedding
  100. phase follows the
  101. presentation in cite{Mehlhorn-Mutzel:embedding}. We want to remark that the
  102. description of the embedding phase given
  103. in cite[section IV.10]{Me:book} is false.
  104. The essential part of cite{Mehlhorn-Mutzel:embedding} is reprinted in
  105. section ref{embedding}.
  106. This document defines the files PB{$\{planar}.|h$}, PB{$\{planar}.|c$},
  107. and PB{$\{demo}.|c$}.
  108. PB{$\{planar}.|c$} contains the code for procedure PB{\{planar}}, PB{$%
  109. \{demo}.|c$}
  110. contains the code for a demo, and PB{$\{planar}.|h$} consists of the
  111. declarations of procedure PB{\{planar}}.
  112. The third file is defined in section ref{demo}, the structure of the first two
  113. files
  114. is as follows:
  115. YB4X1:.{planar.h }X${}E{}$6
  116. &{bool} \{planar}(&{graph} ${}{AND}|G,39{}$&{bool} \{embed}${}K%
  117. \{false});{}$6
  118. &{bool} \{planar}(&{graph} ${}{AND}|G,39&{list}langle&{edge}rangle{}$
  119. ${}{AND}|P,39{}$&{bool} \{embed}${}K\{false});{}$6
  120. &{void} \{Make_biconnected_graph}(&{graph} ${}{AND}|G){}$;par
  121. fi
  122. M{2}
  123. YB4X2:.{planar.c }X${}E{}$6
  124. X3:includesX;6
  125. X11:typedefs, global variables and class declarationsX;6
  126. X9:auxiliary functionsX;6
  127. X5:first version of PB{\{planar}}X;6
  128. X4:second version of PB{\{planar}}X;par
  129. fi
  130. M{3}We include parts of LEDA (who would want to
  131. work without it) cite{LEDA-Manual,Mehlhorn-Naeher:LEDA}.
  132. We need stacks, graphs, and graph algorithms.
  133. YB4X3:includesX${}E{}$6
  134. 8#&{include} .{<LEDA/stack.h>}6
  135. 8#&{include} .{<LEDA/graph.h>}6
  136. 8#&{include} .{<LEDA/graph_alg.h>}6
  137. 8#&{include} .{"planar.h"}par
  138. A36.
  139. Us2ET35.fi
  140. M{4}The second version of PB{\{planar}} is easy to describe. We first test
  141. the
  142. planarity of PB{|G} using the first version.
  143. If PB{|G} is planar then we are done. If PB{|G} is
  144. non-planar then we cycle through the edges of PB{|G}. For every edge PB{|e}
  145. of
  146. PB{|G} we test the planarity of PB{$|G-|e$}. If PB{$|G-|e$} is planar
  147. we add PB{|e} back in.
  148. In this way we determine a minimal (with respect to set inclusion)
  149. non-planar subgraph of PB{|G}, i.e., either a $K_5$ or a $K_{3,3}$.
  150. YB4X4:second version of PB{\{planar}}X${}E{}$6
  151. &{bool} \{planar}(&{graph} ${}{AND}|G,39&{list}langle&{edge}rangle{}$
  152. ${}{AND}|P,39{}$&{bool} \{embed}${}K\{false}){}$11226
  153. ${}{{}$16
  154. &{if} ${}(\{planar}(|G,39\{embed})){}$15
  155. &{return} \{true};C{ We work on a copy PB{|H} of PB{|G} since the
  156. procedure alters PB{|G}; we link every vertex and edge of PB{|H} with its
  157. original. For the vertices we also have the reverse links. }27
  158. ${}&{GRAPH}langle&{node},39&{edge}rangle{}$ |H;6
  159. ${}&{node_array}langle&{node}rangle{}$ \{link}(|G);6
  160. &{node} |v;7
  161. &{forall_nodes} ${}(|v,39|G){}$15
  162. ${}\{link}[|v]K|H.\{new_node}(|v){}$;C{ This requires some explanation.
  163. PB{$|H.\{new_node}(|v)$} adds a new node to PB{|H}, returns the new
  164. node, and makes PB{|v} the information associated with the new node. So the
  165. statement creates a copy of PB{|v} and bidirectionally links it with PB{|v}
  166. }27
  167. &{edge} |e;7
  168. &{forall_edges} ${}(|e,39|G){}$15
  169. ${}|H.\{new_edge}(\{link}[\{source}(|e)],39\{link}[\{target}(|e)],39%
  170. |e){}$;C{ PB{\{link}[\{source}(|e)]} and PB{\{link}[\{target}(|e)]}
  171. are the copies of PB{\{source}(|e)} and PB{\{target}(|e)} in PB{|H}.
  172. The operation PB{$|H.\{new_edge}$} creates a new edge with these endpoints,
  173. returns it, and makes PB{|e} the information of that edge. So the effect of
  174. the loop is to make the edge set of PB{|H} a copy of the edge set of PB{|G}
  175. and to let every edge of PB{|H} know its original. We can now determine a
  176. minimal non-planar subgraph of PB{|H} }27
  177. ${}&{list}langle&{edge}rangle{}$ |L${}K|H.\{all_edges}(,);{}$6
  178. &{edge} \{eh};7
  179. &{forall} ${}(\{eh},39|L){}$5
  180. ${}{{}$16
  181. ${}|eK|H[\{eh}]{}$;SHC{ the edge in PB{|G} corresponding to PB{\{eh}}
  182. }7
  183. &{node} |x${}K\{source}(\{eh});{}$6
  184. &{node} |y${}K\{target}(\{eh});{}$7
  185. ${}|H.\{del_edge}(\{eh});{}$6
  186. &{if} (\{planar}(|H))15
  187. ${}|H.\{new_edge}(|x,39|y,39|e){}$;SHC{put a new version of PB{%
  188. \{eh}} back in and establish the correspondence }26
  189. 4${}}{}$C{ PB{|H} is now a homeomorph of either $K_5$ or $K_{3,3}$. We
  190. still need to translate back to PB{|G}. }26
  191. ${}|P.\{clear}(,);{}$6
  192. &{forall_edges} ${}(\{eh},39|H){}$15
  193. ${}|P.\{append}(|H[\{eh}]);{}$26
  194. &{return} \{false};6
  195. 4${}}{}$2par
  196. U2.fi
  197. M{5}The first version of PB{\{planar}} is also quite simple to describe.
  198. Graphs with at most three
  199. vertices are always planar. So assume that PB{|G} has more than three
  200. vertices. We first add edges to PB{|G} to make it bidirected
  201. and then add some more edges to make
  202. it biconnected (of course, without destroying planarity). Then we test
  203. the planarity of the extended graph and construct an embedding.
  204. Since PB{\{planar}} alters the input graph, it works on a copy of it.
  205. YB4X5:first version of PB{\{planar}}X${}E{}$6
  206. &{bool} \{planar}(&{graph} ${}{AND}\{Gin},39{}$&{bool} \{embed}${}K%
  207. \{false}{}$)C{ PB{\{Gin}} is a directed graph. PB{\{planar}} decides
  208. whether PB{\{Gin}} is planar. If it is and PB{$\{embed}E\{true}$} then it
  209. also computes a  combinatorial embedding of PB{\{Gin}} by suitably reordering
  210. its adjacency lists. PB{\{Gin}} must be bidirected in that case. }116
  211. ${$ &{int} |n${}K\{Gin}.\{number_of_nodes}(,);{}$7
  212. &{if} ${}(|nZT{3}){}$15
  213. &{return} \{true};26
  214. &{if} ${}(\{Gin}.\{number_of_edges}(,)>T{6}*|n-T{12}){}$15
  215. &{return} \{false};C{ An undirected planar graph has at most $3n-6$ edges; a
  216. directed graph may have twice as many }26
  217. ${}\{cout}LL.{"number of nodes and}).{ edges  "}LL|nLL.{"  "}%
  218. LL\{Gin}.\{number_of_edges}(,);{}$6
  219. \{newline};7
  220. &{float} |T${}K\{used_time}(,);{}$7
  221. X6:make PB{|G} a copy of PB{\{Gin}} and add edges to make PB{|G}
  222. bidirectedX;6
  223. X8:make PB{|G} biconnectedX;6
  224. ${}\{cout}LL.{"time to copy and to}).{ make bidirected and}).{
  225. connected  "}LL\{used_time}(|T);{}$6
  226. \{newline};6
  227. X13:test planarityX;6
  228. ${}\{cout}LL.{"time to test planar}).{ity   "}LL\{used_time}(%
  229. |T);{}$6
  230. \{newline}; &{if} (\{embed}) ${$ &{if} (\{Gin_is_bidirected}) %
  231. X26:construct embeddingX 6
  232. &{else}15
  233. ${}\{error_handler}(T{2},39.{"sorry: can only emb}).{ed bidirected
  234. graphs}).{"});{}$26
  235. ${}\{cout}LL.{"time to construct e}).{mbedding   "}LL\{used%
  236. _time}(|T);{}$6
  237. \{newline}; $}$ &{return} \{true}; $}{}$par
  238. U2.fi
  239. M{6}We make PB{|G} a copy of PB{\{Gin}} and bidirectionally link all
  240. vertices and
  241. edges. Then we add edges to PB{|G} to make it bidirected. In
  242. PB{\{Gin_is_bidirected}} we record whether we needed to add edges.
  243. YB4X6:make PB{|G} a copy of PB{\{Gin}} and add edges to make PB{|G}
  244. bidirectedX${}E{}$6
  245. $&{GRAPH}langle&{node},39&{edge}rangle{}$ |G;6
  246. ${}&{edge_array}langle&{edge}rangle{}$ \{companion_in_G}(\{Gin});6
  247. ${}&{node_array}langle&{node}rangle{}$ \{link}(\{Gin});6
  248. &{bool} \{Gin_is_bidirected}${}K\{true};{}$7
  249. ${}{{}$16
  250. &{node} |v;7
  251. &{forall_nodes} ${}(|v,39\{Gin}){}$15
  252. ${}\{link}[|v]K|G.\{new_node}(|v){}$;SHC{bidirectional links }27
  253. &{edge} |e;7
  254. &{forall_edges} ${}(|e,39\{Gin}){}$15
  255. ${}\{companion_in_G}[|e]K|G.\{new_edge}(\{link}[\{source}(|e)],39%
  256. \{link}[\{target}(|e)],39|e);{}$26
  257. 4${}}{}$26
  258. X7:bidirect GX;par
  259. U5.fi
  260. M{7}We bidirect G. We first assign numbers to nodes and edges. We make sure
  261. that
  262. the two versions of the same undirected edge get the same number but versions
  263. of distinct undirected edges get different numbers. Then we sort the edges
  264. according to numbers. Finally we step through the sorted list of edges
  265. and add
  266. missing edges.
  267. YB4X7:bidirect GX${}E{}$6
  268. ${}{{}$16
  269. ${}&{node_array}langle&{int}rangle{}$ \{nr}(|G);6
  270. ${}&{edge_array}langle&{int}rangle{}$ \{cost}(|G);6
  271. &{int} \{cur_nr}${}KT{0};{}$6
  272. &{int} |n${}K|G.\{number_of_nodes}(,);{}$6
  273. &{node} |v;6
  274. &{edge} |e;7
  275. &{forall_nodes} ${}(|v,39|G){}$15
  276. ${}\{nr}[|v]K\{cur_nr}PP;{}$26
  277. &{forall_edges} ${}(|e,39|G){}$15
  278. ${}\{cost}[|e]K((\{nr}[\{source}(|e)]<\{nr}[\{target}(|e)])?|n*%
  279. \{nr}[\{source}(|e)]+\{nr}[\{target}(|e)]:|n*\{nr}[\{target}(|e)]+%
  280. \{nr}[\{source}(|e)]);{}$26
  281. ${}|G.\{sort_edges}(\{cost});{}$7
  282. ${}&{list}langle&{edge}rangle{}$ |L${}K|G.\{all_edges}(,);{}$7
  283. &{while} ${}(R|L.\{empty}(,)){}$5
  284. ${}{{}$16
  285. ${}|eK|L.\{pop}(,){}$;C{ check whether the first edge on PB{|L} is
  286. equal to the reversal of PB{|e}. If so, delete it from PB{|L}, if not, add
  287. the reversal to PB{|G} }6
  288. &{if} ${}(R|L.\{empty}(,)W(\{source}(|e)E\{target}(|L.\{head}(,)))%
  289. W(\{source}(|L.\{head}(,))E\{target}(|e))){}$15
  290. ${}|L.\{pop}(,);{}$26
  291. &{else}5
  292. ${}{{}$16
  293. ${}|G.\{new_edge}(\{target}(|e),39\{source}(|e));{}$6
  294. ${}\{Gin_is_bidirected}K\{false};{}$6
  295. 4${}}{}$26
  296. 4${}}{}$26
  297. 4${}}{}$2par
  298. U6.fi
  299. N{1}{8}Making the Graph Biconnected.
  300. We make PB{|G} biconnected. We first make it connected by linking all
  301. roots. Assume that is done. Let $a$ be any articulation
  302. point and let $u$ and $v$ be neighbors of $a$ belonging to different
  303. biconnected components. Then there are embeddings of the two components
  304. with the edges ${u,a}$ and ${v,a}$ on the boundary of the unbounded
  305. face. Hence we may add the edge ${u,v}$ without destroying planarity.
  306. Proceeding in this way we make PB{|G}
  307. biconnected.
  308. In PB{\{Make_biconnected_graph}} we change the graph while working on it.
  309. But we modify only
  310. those adjacency lists that will not be touched later.
  311. We need the biconnected version of PB{|G} (PB{|G} will be further modified
  312. during the planarity test) in order to construct the planar embedding. So we
  313. store it as a graph PB{|H}. For every edge of PB{\{Gin}} and PB{|G} we
  314. store a link to
  315. its copy in PB{|H}. In addition every edge of PB{|H} is made to know its
  316. reversal.
  317. YB4X8:make PB{|G} biconnectedX${}E{}$6
  318. \{Make_biconnected_graph}(|G);6
  319. X12:make PB{|H} a copy of PB{|G}X;par
  320. U5.fi
  321. M{9}We give the details of the procedure PB{\{Make_biconnected_graph}}. We
  322. first make PB{|G}
  323. connected by linking all roots of the DFS-forest. In a second step we make
  324. PB{|G} biconnected.
  325. YB4X9:auxiliary functionsX${}E{}$6
  326. &{void} \{Make_biconnected_graph}(&{graph} ${}{AND}|G){}$11226
  327. ${}{{}$16
  328. &{node} |v;6
  329. ${}&{node_array}langle&{bool}rangle{}$ ${}\{reached}(|G,39%
  330. \{false});{}$6
  331. &{node} |u${}K|G.\{first_node}(,);{}$7
  332. &{forall_nodes} ${}(|v,39|G){}$5
  333. ${}{{}$16
  334. &{if} ${}(R\{reached}[|v]){}$5
  335. ${}{{}$C{ explore the connected component with root PB{|v} }16
  336. ${}\{DFS}(|G,39|v,39\{reached});{}$6
  337. &{if} ${}(|uI|v){}$5
  338. ${}{{}$C{ link PB{|v}'s component to the first component }16
  339. ${}|G.\{new_edge}(|u,39|v);{}$6
  340. ${}|G.\{new_edge}(|v,39|u);{}$6
  341. 4${}}{}$SHC{end if }26
  342. 4${}}{}$SHC{ end not reached }26
  343. 4${}}{}$SHC{end forall }C{ PB{|G} is now connected. We next make it
  344. biconnected. }26
  345. &{forall_nodes} ${}(|v,39|G){}$15
  346. ${}\{reached}[|v]K\{false};{}$27
  347. ${}&{node_array}langle&{int}rangle{}$ \{dfsnum}(|G);6
  348. ${}&{node_array}langle&{node}rangle{}$ ${}\{parent}(|G,39\{nil});{}$6
  349. &{int} \{dfs_count}${}KT{0};{}$6
  350. ${}&{node_array}langle&{int}rangle{}$ \{lowpt}(|G);7
  351. ${}\{dfs_in_make_biconnected_graph}(|G,39|G.\{first_node}(,),39%
  352. \{dfs_count},39\{reached},39\{dfsnum},39\{lowpt},39\{parent});{}$6
  353. 4${}}{}$SHC{ end PB{\{Make_biconnected_graph}} }2par
  354. As10, 15, 16, 18ETs27.
  355. U2.fi
  356. M{10}We still have to give the procedure PB{\{dfs_in_make_biconnected%
  357. _graph}}. It determines
  358. articulation points and adds appropriate edges whenever it discovers one.
  359. For a proof of correctness we refer the reader to
  360. cite[section IV.6]{Me:book}.
  361. YB4X9:auxiliary functionsX${}mathrel+E{}$6
  362. &{void} \{dfs_in_make_biconnected_graph}(&{graph} ${}{AND}|G,39{}$%
  363. &{node} |v${},39{}$&{int} ${}{AND}\{dfs_count},39&{node_array}langle%
  364. &{bool}rangle{}$ ${}{AND}\{reached},3{-1}39&{node_array}langle&{int}%
  365. rangle{}$ ${}{AND}\{dfsnum},39&{node_array}langle&{int}rangle{}$ ${}{%
  366. AND}\{lowpt},39&{node_array}langle&{node}rangle{}$ ${}{AND}%
  367. \{parent}){}$11226
  368. ${}{{}$16
  369. &{node} |w;6
  370. &{edge} |e;7
  371. ${}\{dfsnum}[|v]K\{dfs_count}PP;{}$6
  372. ${}\{lowpt}[|v]K\{dfsnum}[|v];{}$6
  373. ${}\{reached}[|v]K\{true};{}$6
  374. &{if} ${}(R|G.\{first_adj_edge}(|v)){}$15
  375. &{return};SHC{no children }27
  376. &{node} |u${}K\{target}(|G.\{first_adj_edge}(|v)){}$;SHC{first child
  377. }7
  378. &{forall_adj_edges} ${}(|e,39|v){}$5
  379. ${}{{}$16
  380. ${}|wK\{target}(|e);{}$6
  381. &{if} ${}(R\{reached}[|w]){}$5
  382. ${}{{}$C{ e is a tree edge }16
  383. ${}\{parent}[|w]K|v;{}$6
  384. ${}\{dfs_in_make_biconnected_graph}(|G,39|w,39\{dfs_count},39%
  385. \{reached},39\{dfsnum},39\{lowpt},39\{parent});{}$6
  386. &{if} ${}(\{lowpt}[|w]E\{dfsnum}[|v]){}$5
  387. ${}{{}$C{ PB{|v} is an articulation point. We now add an edge. If PB{|w}
  388. is the first child and PB{|v} has a parent then we connect PB{|w} and PB{%
  389. \{parent}[|v]}, if PB{|w} is a first child and PB{|v} has no parent then
  390. we do nothing. If PB{|w} is not the first child then we connect PB{|w} to
  391. the first child. The net effect of all of this is to link all children of an
  392. articulation point to the first child and the first child to the parent (if it
  393. exists) }16
  394. &{if} ${}(|wE|uW\{parent}[|v]){}$5
  395. ${}{{}$16
  396. ${}|G.\{new_edge}(|w,39\{parent}[|v]);{}$6
  397. ${}|G.\{new_edge}(\{parent}[|v],39|w);{}$6
  398. 4${}}{}$26
  399. &{if} ${}(|wI|u){}$5
  400. ${}{{}$16
  401. ${}|G.\{new_edge}(|u,39|w);{}$6
  402. ${}|G.\{new_edge}(|w,39|u);{}$6
  403. 4${}}{}$26
  404. 4${}}{}$SHC{ end if lowpt = dfsnum }26
  405. ${}\{lowpt}[|v]K\{Min}(\{lowpt}[|v],39\{lowpt}[|w]);{}$6
  406. 4${}}{}$SHC{end tree edge }26
  407. &{else}15
  408. ${}\{lowpt}[|v]K\{Min}(\{lowpt}[|v],39\{dfsnum}[|w]){}$;SHC{non tree
  409. edge }26
  410. 4${}}{}$SHC{ end forall }26
  411. 4${}}{}$SHC{end dfs }2par
  412. fi
  413. M{11}Because we use the function PB{\{dfs_in_make_biconnected_graph}}
  414. before its declaration,
  415. let's add it to the global declarations.
  416. YB4X11:typedefs, global variables and class declarationsX${}E{}$6
  417. &{void} \{dfs_in_make_biconnected_graph}(&{graph} ${}{AND}|G,39{}$%
  418. &{node} |v${},39{}$&{int} ${}{AND}\{dfs_count},39&{node_array}langle%
  419. &{bool}rangle{}$ ${}{AND}\{reached},3{-1}39&{node_array}langle&{int}%
  420. rangle{}$ ${}{AND}\{dfsnum},39&{node_array}langle&{int}rangle{}$ ${}{%
  421. AND}\{lowpt},39&{node_array}langle&{node}rangle{}$ ${}{AND}%
  422. \{parent}){}$;par
  423. As14, 17ETs20.
  424. U2.fi
  425. M{12}We make PB{|H} a copy of PB{|G} and create bidirectional links
  426. between the
  427. vertices and edges of PB{|G} and PB{|H}.
  428. Also, each edge in PB{\{Gin}} gets a link to its copy in PB{|H} and every
  429. edge
  430. of PB{|H} gets to know its reversal. More precisely, PB{$|H[|G[|v]]K%
  431. |v$} for every
  432. node PB{|v} of PB{|G} and PB{$|H[|G[|e]]K|e$} for every edge PB{|e}
  433. of PB{|G}, and
  434. PB{\{companion_in_H}[\{ein}]} is the edge in PB{|H} corresponding to the
  435. edge
  436. PB{\{ein}} of PB{\{Gin}} for every edge PB{\{ein}} of PB{\{Gin}}.
  437. Finally, if PB{$|eK(|u,|v)$} is
  438. an edge of PB{|H} then PB{$\{reversal}[|e]K(|v,|u)$}.
  439. YB4X12:make PB{|H} a copy of PB{|G}X${}E{}$6
  440. $&{GRAPH}langle&{node},39&{edge}rangle{}$ |H;6
  441. ${}&{edge_array}langle&{edge}rangle{}$ \{companion_in_H}(\{Gin});7
  442. ${}{{}$16
  443. &{node} |v;7
  444. &{forall_nodes} ${}(|v,39|G){}$15
  445. ${}|G.\{assign}(|v,39|H.\{new_node}(|v));{}$27
  446. &{edge} |e;7
  447. &{forall_edges} ${}(|e,39|G){}$15
  448. ${}|G.\{assign}(|e,39|H.\{new_edge}(|G[\{source}(|e)],39|G[%
  449. \{target}(|e)],39|e));{}$27
  450. &{edge} \{ein};7
  451. &{forall_edges} ${}(\{ein},39\{Gin}){}$15
  452. ${}\{companion_in_H}[\{ein}]K|G[\{companion_in_G}[\{ein}]];{}$26
  453. 4${}}{}$27
  454. ${}&{edge_array}langle&{edge}rangle{}$ \{reversal}(|H);7
  455. ${}\{compute_correspondence}(|H,39\{reversal}){}$;par
  456. U8.fi
  457. N{1}{13}The Planarity Test.
  458. We are now ready for the planarity test proper. We follow
  459. cite[page 95]{Me:book}. We first compute PB{\{dfsnumber}}s and PB{%
  460. \{parent}}s, we
  461. delete all forward edges and all reversals of tree edges, and we
  462. reorder the adjaceny lists as described in cite[page 101]{Me:book}.
  463. We then test the strong planarity.
  464. The array PB{\{alpha}} is needed for the embedding process. It
  465. records the placement of the subsegments.
  466. YB4X13:test planarityX${}E{}$6
  467. $&{node_array}langle&{int}rangle{}$ \{dfsnum}(|G);6
  468. ${}&{node_array}langle&{node}rangle{}$ ${}\{parent}(|G,39\{nil});{}$7
  469. ${}\{reorder}(|G,39\{dfsnum},39\{parent});{}$7
  470. ${}&{edge_array}langle&{int}rangle{}$ ${}\{alpha}(|G,39T{0});{}$7
  471. ${}{{}$16
  472. ${}&{list}langle&{int}rangle{}$ \{Att};7
  473. ${}\{alpha}[|G.\{first_adj_edge}(|G.\{first_node}(,))]K\{left};{}$6
  474. &{if} ${}(R\{strongly_planar}(|G.\{first_adj_edge}(|G.\{first_node}(%
  475. ,)),39|G,39\{Att},39\{alpha},39\{dfsnum},39\{parent})){}$15
  476. &{return} \{false};26
  477. 4${}}{}$2par
  478. U5.fi
  479. M{14}We need two global constants PB{\{left}} and PB{\{right}}.
  480. YB4X11:typedefs, global variables and class declarationsX${}mathrel+E{}$%
  481. 6
  482. &{const} &{int} \{left}${}KT{1};{}$6
  483. &{const} &{int} \{right}${}KT{2}{}$;par
  484. fi
  485. M{15}We give the details of the procedure PB{\{reorder}}. It first performs
  486. DFS
  487. to compute PB{\{dfsnum}}, PB{\{parent}}, PB{\{lowpt1}} and PB{%
  488. \{lowpt2}}, and the list PB{\{Del}}
  489. of all forward edges and all reversals of tree edges.
  490. It then deletes the edges in PB{\{Del}} and finally it
  491. reorders the edges.
  492. YB4X9:auxiliary functionsX${}mathrel+E{}$6
  493. &{void} \{reorder}(&{graph} ${}{AND}|G,39&{node_array}langle&{int}%
  494. rangle{}$ ${}{AND}\{dfsnum},39&{node_array}langle&{node}rangle{}$ ${}{%
  495. AND}\{parent}){}$11226
  496. ${}{{}$16
  497. &{node} |v;6
  498. ${}&{node_array}langle&{bool}rangle{}$ ${}\{reached}(|G,39%
  499. \{false});{}$6
  500. &{int} \{dfs_count}${}KT{0};{}$6
  501. ${}&{list}langle&{edge}rangle{}$ \{Del};6
  502. ${}&{node_array}langle&{int}rangle{}$ \{lowpt1}(|G)${},{}$ \{lowpt2}(%
  503. |G);7
  504. ${}\{dfs_in_reorder}(\{Del},39|G.\{first_node}(,),39\{dfs_count},%
  505. 39\{reached},39\{dfsnum},39\{lowpt1},39\{lowpt2},39\{parent}){}$;C{
  506. remove forward and reversals of tree edges }7
  507. &{edge} |e;7
  508. &{forall} ${}(|e,39\{Del}){}$15
  509. ${}|G.\{del_edge}(|e){}$;C{ we now reorder adjacency lists as described in
  510. cite[page 101]{Me:book} }27
  511. &{node} |w;6
  512. ${}&{edge_array}langle&{int}rangle{}$ \{cost}(|G);7
  513. &{forall_edges} ${}(|e,39|G){}$5
  514. ${}{{}$16
  515. ${}|vK\{source}(|e);{}$6
  516. ${}|wK\{target}(|e);{}$6
  517. ${}\{cost}[|e]K((\{dfsnum}[|w]<\{dfsnum}[|v])?T{2}*\{dfsnum}[|w]:((%
  518. \{lowpt2}[|w]G\{dfsnum}[|v])?T{2}*\{lowpt1}[|w]:T{2}*\{lowpt1}[|w]+%
  519. T{1}));{}$6
  520. 4${}}{}$26
  521. ${}|G.\{sort_edges}(\{cost});{}$6
  522. 4${}}{}$2par
  523. fi
  524. M{16}We still have to give the procedure PB{\{dfs_in_reorder}}. It's a bit
  525. long but standard.
  526. YB4X9:auxiliary functionsX${}mathrel+E{}$6
  527. &{void} \{dfs_in_reorder}${}(&{list}langle&{edge}rangle{}$ ${}{AND}%
  528. \{Del},39{}$&{node} |v${},39{}$&{int} ${}{AND}\{dfs_count},39&{node%
  529. _array}langle&{bool}rangle{}$ ${}{AND}\{reached},3{-1}39&{node_array}%
  530. langle&{int}rangle{}$ ${}{AND}\{dfsnum},39&{node_array}langle&{int}%
  531. rangle{}$ ${}{AND}\{lowpt1},39&{node_array}langle&{int}rangle{}$ ${}{%
  532. AND}\{lowpt2},3{-1}39&{node_array}langle&{node}rangle{}$ ${}{AND}%
  533. \{parent}){}$11226
  534. ${}{{}$16
  535. &{node} |w;6
  536. &{edge} |e;7
  537. ${}\{dfsnum}[|v]K\{dfs_count}PP;{}$6
  538. ${}\{lowpt1}[|v]K\{lowpt2}[|v]K\{dfsnum}[|v];{}$6
  539. ${}\{reached}[|v]K\{true};{}$6
  540. &{forall_adj_edges} ${}(|e,39|v){}$5
  541. ${}{{}$16
  542. ${}|wK\{target}(|e);{}$6
  543. &{if} ${}(R\{reached}[|w]){}$5
  544. ${}{{}$C{ e is a tree edge }16
  545. ${}\{parent}[|w]K|v;{}$6
  546. ${}\{dfs_in_reorder}(\{Del},39|w,39\{dfs_count},39\{reached},39%
  547. \{dfsnum},39\{lowpt1},39\{lowpt2},39\{parent});{}$6
  548. ${}\{lowpt1}[|v]K\{Min}(\{lowpt1}[|v],39\{lowpt1}[|w]);{}$6
  549. 4${}}{}$SHC{end tree edge }26
  550. &{else}5
  551. ${}{{}$16
  552. ${}\{lowpt1}[|v]K\{Min}(\{lowpt1}[|v],39\{dfsnum}[|w]){}$;SHC{ no
  553. effect for forward edges }6
  554. &{if} ${}((\{dfsnum}[|w]G\{dfsnum}[|v])V|wE\{parent}[|v]{}$)C{
  555. forward edge or reversal of tree edge }16
  556. ${}\{Del}.\{append}(|e);{}$26
  557. 4${}}{}$SHC{end non-tree edge }26
  558. 4${}}{}$SHC{ end forall }C{ we know PB{\{lowpt1}[|v]} at this point and
  559. now make a second pass over all      adjacent edges of PB{|v} to compute PB{%
  560. \{lowpt2}} }26
  561. &{forall_adj_edges} ${}(|e,39|v){}$5
  562. ${}{{}$16
  563. ${}|wK\{target}(|e);{}$6
  564. &{if} ${}(\{parent}[|w]E|v){}$5
  565. ${}{{}$C{ tree edge }16
  566. &{if} ${}(\{lowpt1}[|w]I\{lowpt1}[|v]){}$15
  567. ${}\{lowpt2}[|v]K\{Min}(\{lowpt2}[|v],39\{lowpt1}[|w]);{}$26
  568. ${}\{lowpt2}[|v]K\{Min}(\{lowpt2}[|v],39\{lowpt2}[|w]);{}$6
  569. 4${}}{}$SHC{end tree edge }26
  570. &{else}SHC{ all other edges }6
  571. &{if} ${}(\{lowpt1}[|v]I\{dfsnum}[|w]){}$15
  572. ${}\{lowpt2}[|v]K\{Min}(\{lowpt2}[|v],39\{dfsnum}[|w]);{}$26
  573. 4${}}{}$SHC{end forall }26
  574. 4${}}{}$SHC{end dfs }2par
  575. fi
  576. M{17}Because we use the function PB{\{dfs_in_reorder}} before its
  577. declaration,
  578. let's add it to the global declarations.
  579. YB4X11:typedefs, global variables and class declarationsX${}mathrel+E{}$%
  580. 6
  581. &{void} \{dfs_in_reorder}${}(&{list}langle&{edge}rangle{}$ ${}{AND}%
  582. \{Del},39{}$&{node} |v${},39{}$&{int} ${}{AND}\{dfs_count},39&{node%
  583. _array}langle&{bool}rangle{}$ ${}{AND}\{reached},3{-1}39&{node_array}%
  584. langle&{int}rangle{}$ ${}{AND}\{dfsnum},39&{node_array}langle&{int}%
  585. rangle{}$ ${}{AND}\{lowpt1},39&{node_array}langle&{int}rangle{}$ ${}{%
  586. AND}\{lowpt2},3{-1}39&{node_array}langle&{node}rangle{}$ ${}{AND}%
  587. \{parent}){}$;par
  588. fi
  589. M{18}We now come to the heart of the planarity test: procedure PB{\{strongly%
  590. _planar}}.
  591. It takes a tree edge $e0 = (x,y)$ and tests whether
  592. the segment $S(e0)$ is strongly planar. If  successful it returns  (in PB{%
  593. \{Att}}) the
  594. ordered list of attachments of $S(e0)$ (excluding $x$); high DFS-numbers are
  595. at the front of the list. In PB{\{alpha}} it
  596. records the placement of the subsegments.
  597. PB{\{strongly_planar}} operates in three phases. It first constructs the
  598. cycle $C(e0)$
  599. underlying the segment $S(e0)$. It then constructs the interlacing graph for
  600. the
  601. segments emanating from the spine of the cycle. If this graph is non-bipartite
  602. then the segment $S(e0)$ is non-planar. If it is bipartite then the segment is
  603. planar. In this case the third phase checks whether the segment is strongly
  604. planar and, if so, computes its list of attachments.
  605. YB4X9:auxiliary functionsX${}mathrel+E{}$6
  606. &{bool} \{strongly_planar}(&{edge} \{e0}${},39{}$&{graph} ${}{AND}|G,%
  607. 39&{list}langle&{int}rangle{}$ ${}{AND}\{Att},39&{edge_array}langle%
  608. &{int}rangle{}$ ${}{AND}\{alpha},3{-1}39&{node_array}langle&{int}%
  609. rangle{}$ ${}{AND}\{dfsnum},39&{node_array}langle&{node}rangle{}$ ${}{%
  610. AND}\{parent}){}$11226
  611. ${}{{}$16
  612. X19:determine the cycle $C(e0)$X;6
  613. X21:process all edges leaving the spineX;6
  614. X25:test strong planarity and compute PB{\{Att}}X;6
  615. &{return} \{true};6
  616. 4${}}{}$2par
  617. fi
  618. M{19}We determine the cycle $C(e0)$ by following first edges until a back
  619. edge is encountered. PB{\{wk}} will be the last node on the tree path and %
  620. PB{\{w0}}
  621. is the destination of the back edge. This agrees with the
  622. notation of cite{Me:book}.
  623. YB4X19:determine the cycle $C(e0)$X${}E{}$6
  624. &{node} |x${}K\{source}(\{e0});{}$6
  625. &{node} |y${}K\{target}(\{e0});{}$6
  626. &{edge} |e${}K|G.\{first_adj_edge}(|y);{}$6
  627. &{node} \{wk}${}K|y;{}$7
  628. &{while} ${}(\{dfsnum}[\{target}(|e)]>\{dfsnum}[\{wk}]{}$)SHC{ e is a
  629. tree edge }6
  630. ${}{{}$16
  631. ${}\{wk}K\{target}(|e);{}$6
  632. ${}|eK|G.\{first_adj_edge}(\{wk});{}$6
  633. 4${}}{}$27
  634. &{node} \{w0}${}K\{target}(|e){}$;par
  635. U18.fi
  636. M{20}The second phase of PB{\{strongly_planar}} constructs the connected
  637. components of
  638. the interlacing graph of the segments emananating from the the spine of the
  639. cycle $C(e0)$. We call a connected component a {em block}. For each block
  640. we store the segments comprising its left and right side (lists
  641. PB{\{Lseg}} and PB{\{Rseg}} contain the edges
  642. defining these segments) and the ordered list of attachments of the segments
  643. in the block; lists PB{\{Latt}} and PB{\{Ratt}} contain the DFS-numbers of
  644. the
  645. attachments; high DFS-numbers are at the front of the list. Blocks are
  646. so important that we make them a class.
  647. We need the following operations on blocks.
  648. The constructor takes an edge and a list of attachments and creates
  649. a block having the edge as the only segment in its left side.
  650. PB{\{flip}} interchanges the two sides of a block.
  651. PB{\{head_of_Latt}} and PB{\{head_of_Ratt}} return the first elements
  652. on PB{\{Latt}} and PB{\{Ratt}} respectively
  653. and PB{\{Latt_empty}} and PB{\{Ratt_empty}} check these lists for
  654. emptyness.
  655. PB{\{left_interlace}} checks whether the block interlaces with the left side
  656. of the topmost block of
  657. stack PB{|S}. PB{\{right_interlace}} does the same for the right side.
  658. PB{\{combine}} combines the block with another block PB{\{Bprime}} by
  659. simply concatenating all
  660. lists.
  661. PB{\{clean}} removes the attachment PB{|w} from the block PB{|B} (it is
  662. guaranteed to be the
  663. first attachment of PB{|B}). If the block becomes empty then it records the
  664. placement of all segments in the block in the array PB{\{alpha}} and returns
  665. true.
  666. Otherwise it returns false.
  667. PB{\{add_to_Att}} first makes sure that the right side has no attachment
  668. above PB{\{w0}}
  669. (by
  670. flipping); when PB{\{add_to_Att}} is called at least one side has no
  671. attachment above PB{\{w0}}.
  672. PB{\{add_to_Att}} then adds the lists PB{\{Ratt}} and PB{\{Latt}} to
  673. the output list PB{\{Att}}
  674. and records the placement of all segments in the block in PB{\{alpha}}.
  675. We advise the reader to only skim the rest of the section at this
  676. point and to come back to it when the procedures are first used.
  677. YB4X11:typedefs, global variables and class declarationsX${}mathrel+E{}$%
  678. 6
  679. &{class} &{block} ${}{{}$16
  680. 4&{private}:5
  681. ${}&{list}langle&{int}rangle{}$ \{Latt}${},{}$ \{Ratt};SHC{list of
  682. attachments }6
  683. ${}&{list}langle&{edge}rangle{}$ \{Lseg}${},{}$ \{Rseg};SHC{list of
  684. segments represented by their defining edges }7
  685. 4&{public}:5
  686. &{block}(&{edge} |e${},39&{list}langle&{int}rangle{}$ ${}{AND}|A){}$%
  687. 11226
  688. ${}{{}$16
  689. ${}\{Lseg}.\{append}(|e);{}$6
  690. ${}\{Latt}.\{conc}(|A){}$;SHC{ the other two lists are empty }6
  691. 4${}}{}$27
  692. ${}CM&{block}{}$(,)5
  693. ${}{,}{}$7
  694. &{void} \{flip}(,)11226
  695. ${}{{}$16
  696. ${}&{list}langle&{int}rangle{}$ \{ha};6
  697. ${}&{list}langle&{edge}rangle{}$ \{he};C{ we first interchange PB{%
  698. \{Latt}} and PB{\{Ratt}} and then PB{\{Lseg}} and PB{\{Rseg}} }7
  699. ${}\{ha}.\{conc}(\{Ratt}){}$;5
  700. ${}\{Ratt}.\{conc}(\{Latt}){}$;5
  701. ${}\{Latt}.\{conc}(\{ha});{}$6
  702. ${}\{he}.\{conc}(\{Rseg}){}$;5
  703. ${}\{Rseg}.\{conc}(\{Lseg}){}$;5
  704. ${}\{Lseg}.\{conc}(\{he});{}$6
  705. 4${}}{}$27
  706. &{int} \{head_of_Latt}(,)5
  707. ${}{{}$5
  708. 1&{return} ${}\{Latt}.\{head}(,){}$;5
  709. ${}}{}$27
  710. &{bool} \{empty_Latt}(,)5
  711. ${}{{}$5
  712. 1&{return} ${}\{Latt}.\{empty}(,){}$;5
  713. ${}}{}$27
  714. &{int} \{head_of_Ratt}(,)5
  715. ${}{{}$5
  716. 1&{return} ${}\{Ratt}.\{head}(,){}$;5
  717. ${}}{}$27
  718. &{bool} \{empty_Ratt}(,)5
  719. ${}{{}$5
  720. 1&{return} ${}\{Ratt}.\{empty}(,){}$;5
  721. ${}}{}$27
  722. &{bool} \{left_interlace}${}(&{stack}langle{}$&{block} ${}{*}rangle{}$
  723. ${}{AND}|S){}$11226
  724. ${}{{}$C{ check for interlacing with the left side of the topmost block of %
  725. PB{|S} }16
  726. &{if} ${}(\{Latt}.\{empty}(,)){}$15
  727. ${}\{error_handler}(T{1},39.{"Latt is never empty}).{"});{}$26
  728. &{if} ${}(R|S.\{empty}(,)WR((|S.\{top}(,))MG\{empty_Latt}(,))W%
  729. \{Latt}.\{tail}(,)<(|S.\{top}(,))MG\{head_of_Latt}(,)){}$15
  730. &{return} \{true};26
  731. &{else}15
  732. &{return} \{false};26
  733. 4${}}{}$27
  734. &{bool} \{right_interlace}${}(&{stack}langle{}$&{block} ${}{*}rangle{}$
  735. ${}{AND}|S){}$11226
  736. ${}{{}$C{ check for interlacing with the right side of the topmost block of %
  737. PB{|S} }16
  738. &{if} ${}(\{Latt}.\{empty}(,)){}$15
  739. ${}\{error_handler}(T{1},39.{"Latt is never empty}).{"});{}$26
  740. &{if} ${}(R|S.\{empty}(,)WR((|S.\{top}(,))MG\{empty_Ratt}(,))W%
  741. \{Latt}.\{tail}(,)<(|S.\{top}(,))MG\{head_of_Ratt}(,)){}$15
  742. &{return} \{true};26
  743. &{else}15
  744. &{return} \{false};26
  745. 4${}}{}$27
  746. &{void} \{combine}(&{block} ${}{*}{AND}\{Bprime}){}$11226
  747. ${}{{}$C{ add block Bprime to the rear of PB{$this$} block }16
  748. ${}\{Latt}.\{conc}(\{Bprime}MG\{Latt});{}$6
  749. ${}\{Ratt}.\{conc}(\{Bprime}MG\{Ratt});{}$6
  750. ${}\{Lseg}.\{conc}(\{Bprime}MG\{Lseg});{}$6
  751. ${}\{Rseg}.\{conc}(\{Bprime}MG\{Rseg});{}$6
  752. &{delete} (\{Bprime});6
  753. 4${}}{}$27
  754. &{bool} \{clean}(&{int} \{dfsnum_w}${},39&{edge_array}langle&{int}%
  755. rangle{}$ ${}{AND}\{alpha},39&{node_array}langle&{int}rangle{}$ ${}{%
  756. AND}\{dfsnum}){}$11226
  757. ${}{{}$C{ remove all attachments to PB{|w}; there may be several }16
  758. &{while} ${}(R\{Latt}.\{empty}(,)W\{Latt}.\{head}(,)E\{dfsnum%
  759. _w}){}$15
  760. ${}\{Latt}.\{pop}(,);{}$26
  761. &{while} ${}(R\{Ratt}.\{empty}(,)W\{Ratt}.\{head}(,)E\{dfsnum%
  762. _w}){}$15
  763. ${}\{Ratt}.\{pop}(,);{}$26
  764. &{if} ${}(R\{Latt}.\{empty}(,)VR\{Ratt}.\{empty}(,)){}$15
  765. &{return} \{false};C{PB{\{Latt}} and PB{\{Ratt}} are empty; we record
  766. the placement of the subsegments in PB{\{alpha}}. }27
  767. &{edge} |e;7
  768. &{forall} ${}(|e,39\{Lseg}){}$15
  769. ${}\{alpha}[|e]K\{left};{}$26
  770. &{forall} ${}(|e,39\{Rseg}){}$15
  771. ${}\{alpha}[|e]K\{right};{}$26
  772. &{return} \{true};6
  773. 4${}}{}$27
  774. &{void} \{add_to_Att}${}(&{list}langle&{int}rangle{}$ ${}{AND}\{Att},%
  775. 39{}$&{int} \{dfsnum_w0}${},39&{edge_array}langle&{int}rangle{}$ ${}{%
  776. AND}\{alpha},3{-1}39&{node_array}langle&{int}rangle{}$ ${}{AND}%
  777. \{dfsnum}){}$11226
  778. ${}{{}$C{ add the block to the rear of PB{\{Att}}. Flip if necessary }16
  779. &{if} ${}(R\{Ratt}.\{empty}(,)W\{head_of_Ratt}(,)>\{dfsnum_w0}){}$%
  780. 15
  781. \{flip}(,);26
  782. ${}\{Att}.\{conc}(\{Latt});{}$6
  783. ${}\{Att}.\{conc}(\{Ratt}){}$;C{ This needs some explanation. Note that %
  784. PB{\{Ratt}} is either empty or ${w0}$. Also if PB{\{Ratt}} is non-empty
  785. then all subsequent sets are contained in ${w0}$. So we indeed compute an
  786. ordered set of attachments. }7
  787. &{edge} |e;7
  788. &{forall} ${}(|e,39\{Lseg}){}$15
  789. ${}\{alpha}[|e]K\{left};{}$26
  790. &{forall} ${}(|e,39\{Rseg}){}$15
  791. ${}\{alpha}[|e]K\{right};{}$26
  792. 4${}}{}$226
  793. ${}}{}$;par
  794. fi
  795. M{21}We process the edges leaving the spine of $S(e0)$ starting at node PB{%
  796. \{wk}}
  797. and working backwards. The interlacing graph of the segments emanating from
  798. the cycle is represented as a stack PB{|S} of blocks.
  799. YB4X21:process all edges leaving the spineX${}E{}$6
  800. &{node} |w${}K\{wk};{}$6
  801. ${}&{stack}langle{}$&{block} ${}{*}rangle{}$ |S;7
  802. &{while} ${}(|wI|x){}$5
  803. ${}{{}$16
  804. &{int} \{count}${}KT{0};{}$7
  805. &{forall_adj_edges} ${}(|e,39|w){}$5
  806. ${}{{}$16
  807. ${}\{count}PP;{}$6
  808. &{if} ${}(\{count}IT{1}{}$)SHC{no action for first edge }6
  809. ${}{{}$16
  810. X22:test recursivelyX;6
  811. X23:update stack PB{|S} of attachmentsX;6
  812. 4${}}{}$SHC{ end if }26
  813. 4${}}{}$SHC{end forall }26
  814. X24:prepare for next iterationX;6
  815. ${}|wK\{parent}[|w];{}$6
  816. 4${}}{}$SHC{end while }2par
  817. U18.fi
  818. M{22}Let $e$ be any edge leaving the spine. We need to test whether
  819. $S(e)$ is strongly planar and if so compute its list PB{|A} of attachments.
  820. If $e$ is a tree edge we call our procedure recursively and if $e$ is a
  821. back edge then $S(e)$ is certainly strongly planar and PB{\{target}(|e)} is
  822. the only attachment. If we detect non-planarity we return flase and free
  823. the storage allocated for the blocks of stack PB{|S}.
  824. YB4X22:test recursivelyX${}E{}$6
  825. $&{list}langle&{int}rangle{}$ |A;7
  826. &{if} ${}(\{dfsnum}[|w]<\{dfsnum}[\{target}(|e)]){}$5
  827. ${}{{}$C{ tree edge }16
  828. &{if} ${}(R\{strongly_planar}(|e,39|G,39|A,39\{alpha},39\{dfsnum},%
  829. 39\{parent})){}$5
  830. ${}{{}$16
  831. &{while} ${}(R|S.\{empty}(,)){}$15
  832. &{delete} ${}(|S.\{pop}(,));{}$26
  833. &{return} \{false};6
  834. 4${}}{}$26
  835. 4${}}{}$26
  836. &{else}15
  837. ${}|A.\{append}(\{dfsnum}[\{target}(|e)]){}$;SHC{ a back edge }2par
  838. U21.fi
  839. M{23}The list PB{|A} contains the ordered list of attachments of segment
  840. $S(e)$. We create an new block consisting only of segment $S(e)$ (in its
  841. $L$-part) and then combine this block with the topmost block of stack PB{|S}
  842. as
  843. long as
  844. there is interlacing. We check for interlacing with the $L$-part. If there
  845. is interlacing then we flip the two sides of the topmost block. If there
  846. is still interlacing with the left side then the interlacing graph is
  847. non-bipartite and
  848. we declare the graph non-planar (and also free the storage allocated
  849. for the blocks). Otherwise we check for interlacing with
  850. the R-part. If there is interlacing then we combine PB{|B} with the topmost
  851. block and repeat the process with the new topmost block. If there is no
  852. interlacing then we push block PB{|B} onto PB{|S}.
  853. YB4X23:update stack PB{|S} of attachmentsX${}E{}$6
  854. &{block} ${}{*}|BK{}$&{new} &{block} ${}(|e,39|A);{}$7
  855. &{while} (\{true})5
  856. ${}{{}$16
  857. &{if} ${}(|BMG\{left_interlace}(|S)){}$15
  858. ${}(|S.\{top}(,))MG\{flip}(,);{}$26
  859. &{if} ${}(|BMG\{left_interlace}(|S)){}$5
  860. ${}{{}$16
  861. &{delete} (|B);6
  862. &{while} ${}(R|S.\{empty}(,)){}$15
  863. &{delete} ${}(|S.\{pop}(,));{}$26
  864. &{return} \{false};6
  865. 4${}}{}$26
  866. ;6
  867. &{if} ${}(|BMG\{right_interlace}(|S)){}$15
  868. ${}|BMG\{combine}(|S.\{pop}(,));{}$26
  869. &{else}15
  870. &{break};26
  871. 4${}}{}$SHC{end while }26
  872. ${}|S.\{push}(|B){}$;par
  873. U21.fi
  874. M{24}We have now processed all edges emanating from vertex PB{|w}. Before
  875. starting to
  876. process edges emanating from vertex PB{\{parent}[|w]} we remove PB{%
  877. \{parent}[|w]} from
  878. the list of attachments of the topmost block of stack PB{|S}. If this block
  879. becomes empty then we pop it from the stack and record the placement for all
  880. segments in the block in array PB{\{alpha}}.
  881. YB4X24:prepare for next iterationX${}E{}$6
  882. &{while} ${}(R|S.\{empty}(,)W(|S.\{top}(,))MG\{clean}(\{dfsnum}[%
  883. \{parent}[|w]],39\{alpha},39\{dfsnum})){}$15
  884. &{delete} ${}(|S.\{pop}(,)){}$;2par
  885. U21.fi
  886. M{25}We test the strong planarity of the segment $S(e0)$.
  887. We know at this point that the
  888. interlacing graph is bipartite. Also for each of its connected components the
  889. corresponding block on stack PB{|S} contains the list of attachments below %
  890. PB{|x}.
  891. Let PB{|B} be the topmost block of PB{|S}. If both sides of PB{|B} have
  892. an attachment
  893. above PB{\{w0}} then $S(e0)$ is not strongly planar. We free the storage
  894. allocated for
  895. the blocks and return false. Otherwise (cf. procedure
  896. PB{\{add_to_Att}}) we first make sure that the right side of PB{|B}
  897. attaches only to PB{\{w0}}
  898. (if at all) and then add the two sides of PB{|B} to the output list PB{%
  899. \{Att}}. We also
  900. record the placements of the subsegments in PB{\{alpha}}.
  901. YB4X25:test strong planarity and compute PB{\{Att}}X${}E{}$6
  902. $\{Att}.\{clear}(,);{}$6
  903. &{while} ${}(R|S.\{empty}(,)){}$5
  904. ${}{{}$16
  905. &{block} ${}{*}|BK|S.\{pop}(,);{}$7
  906. &{if} ${}(R(|BMG\{empty_Latt}(,))WR(|BMG\{empty_Ratt}(,))W(|B%
  907. MG\{head_of_Latt}(,)>\{dfsnum}[\{w0}])W(|BMG\{head_of_Ratt}(,)>%
  908. \{dfsnum}[\{w0}])){}$5
  909. ${}{{}$16
  910. &{delete} (|B);6
  911. &{while} ${}(R|S.\{empty}(,)){}$15
  912. &{delete} ${}(|S.\{pop}(,));{}$26
  913. &{return} \{false};6
  914. 4${}}{}$26
  915. ${}|BMG\{add_to_Att}(\{Att},39\{dfsnum}[\{w0}],39\{alpha},39%
  916. \{dfsnum});{}$6
  917. &{delete} (|B);6
  918. 4${}}{}$SHC{end while }C{ Let's not forget (as the book does) that $w0$ is
  919. an attachment of $S(e0)$ except if $w0 = x$. }26
  920. &{if} ${}(\{w0}I|x){}$15
  921. ${}\{Att}.\{append}(\{dfsnum}[\{w0}]){}$;2par
  922. U18.fi
  923. N{1}{26}Constructing the Embedding.    label{embedding}
  924. %%%%%%%%%%%%%%%%%% einbinden von bildern mit Unterschrift %%%%%%%%%%%%%
  925. newcommand{bild}[2]{
  926. begin{figure}[htb]
  927. begin{center}
  928. input{#1.tex}
  929. end{center}
  930. caption{{#2}label{#1}}
  931. end{figure}
  932. }
  933. %%%%%  wird so benutzt: bild{<label>}{<caption>}  %%%%%%%%%%%%%%%%%%%%
  934. %%%%%  z.B. bild{part}{A part of the augmented segment tree structure}
  935. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  936. newtheorem{theorem}{Theorem}
  937. We now discuss how the planarity testing algorithm can be extended
  938. so that it also computes a planar map.
  939. Consider a segment $S(e_0)=C+S(e_1)+ldots +S(e_m)$ consisting of
  940. cycle $C$ and emanating segments $S(e_1),ldots ,S(e_m)$ and
  941. recall that the proofs of Lemmas 8 and 9 describe how
  942. the embeddings of the $S(e_i)$'s have to be combined to yield a
  943. canonical embedding of $S(e_0)$.
  944. Our goal is to turn these proofs into an efficient algorithm.
  945. The proofs of Lemmas 8 and 9 demonstrate two things:
  946. begin{itemize}
  947. item How to test whether $IG(C)$ is bipartite and how to construct
  948. a partition ${L,R}$ of its vertex set, and
  949. item how to construct an embedding of $S(e_0)$ from the embeddings of
  950. the $S(e_i)$'s. This involves flipping of embeddings as we
  951. incrementally construct the embedding of $S(e_0)$.
  952. end{itemize}
  953. Suppose now that some benign agent told us that $IG(C)$ were bipartite
  954. and gave us an appropriate partition ${L,R}$ of its vertex set,
  955. i.e., a partition ${L,R}$ such that no
  956. two segments in $L$ and no two segments in $R$ interlace and such that
  957. $A(e_i)cap {w_1,ldots ,w_{r-1}}=emptyset$ for any segment
  958. $S(e_i)in R$.
  959. Here, as before, $w_0,ldots ,w_r$ denotes the stem of $C$.
  960. Then no flipping would ever be necessary;
  961. we can simply combine the embeddings of the $S(e_i)$'s as prescribed
  962. by the partition ${L,R}$.
  963. More precisely, to construct a canonical embedding of $S(e_0)$ draw
  964. the path $w_0,ldots ,w_k$ (consisting of stem $w_0,ldots ,w_r$,
  965. edge $e_0 = (w_r,w_{r+1})$ and spine $w_{r+1},ldots ,w_k$) as a
  966. vertical upwards directed path, add edge $(w_k,w_0)$, and then for $i$,
  967. $1leq ileq m$, and $S(e_i)in L$ extend the embedding of
  968. $C+S(e_1)+ldots S(e_{i-1})$ by glueing a canonical embedding of
  969. $S(e_i)$ onto the left side of the vertical path, and for $i$,
  970. $1leq ileq m$, and $S(e_i)in R$ extend the embedding of
  971. $C+S(e_1)+ldots +S(e_{i-1})$ by glueing a reversed canonical
  972. embedding of $S(e_i)$ onto the right side of the vertical path.
  973. Similarly, if the goal is to construct a reversed canonical embedding
  974. of $S(e_0)$ then, if $S(e_i)in L$, a reversed canonical embedding of
  975. $S(e_i)$ is glued onto the right side of the vertical path, and if
  976. $S(e_i) in R$, then a canonical embedding of $S(e_i)$ is glued onto the
  977. left side of the vertical path.
  978. Who is the benign agent which tells us that $IG(C)$ is bipartite and
  979. gives us the appropriate partition ${L,R}$ of the segments emanating
  980. from $C=C(e_0)$?
  981. It's the call {em stronglyplanar}($e_0$).
  982. After all, it tests whether $IG(C)$ is bipartite and computes a
  983. bipartition of its vertex set.
  984. Let $S(e)$ be a segment emanating from $C$ and let $B$ be the connected
  985. component of $IG(C)$ containing $S(e)$.
  986. The call {em stronglyplanar}($e_0$) computes $B$ iteratively.
  987. The construction of $B$ is certainly completed when $B$ is popped from
  988. stack $S$.
  989. Put $S(e)$ into $R$ when $S(e)in RB$ at that moment and put $S(e)$
  990. into $L$ otherwise.
  991. With this extension, algorithm {em stronglyplanar} computes the
  992. partition ${L,R}$ of the segments emanating from $C$ in linear time.
  993. We assume for notational convenience that the partition (more precisely,
  994. the union of all partitions for all cycles $C(e_0)$ encountered in the
  995. algorithm) is given as a function $alpha :Sto {L,R}$ where $S$ is
  996. the set of edges for which {em stronglyplanar} is called.
  997. We next give the algorithmic details of the embedding process.
  998. We first use procedure {em stronglyplanar} to compute the mapping
  999. $alpha$.
  1000. We then use a procedure {em embedding} to actually compute an
  1001. embedding.
  1002. The procedure {em embedding} takes two parameters: an edge $e_0$ and
  1003. a flag $tin {L,R}$.
  1004. A call {em embedding}($e_0,L$) computes a canonical embedding of
  1005. $S(e_0)$ and a call {em embedding}($e_0,R$) computes a reversed
  1006. canonical embedding of $S(e_0)$.
  1007. The call {em embedding}($(1,2),L$) embeds the entire graph.
  1008. The embedding of $S(e_0)$ computed by {em embedding}$(e_0,t)$ is
  1009. represented in the following non-standard way:
  1010. begin{enumerate}
  1011. item For the vertices $vin V(e_0)$ we use the standard
  1012. representation, i.e., the cyclic list of the incident
  1013. edges corresponding to the clockwise ordering of the edges
  1014. in the embedding.
  1015. item For the vertices in the stem we use a non-standard representation.
  1016. For each vertex $w_iin{w_0,ldots,w_{r}}$ let the lists
  1017. $AL(w_i)$ and $AR(w_i)$ be such that the catenation of
  1018. $(w_i,w_{i+1})$, $AR(w_i)$, $(w_i,w_{i-1})$, and
  1019. $AL(w_i)$ corresponds to the clockwise ordering of the edges
  1020. incident to $w_i$ in the embedding. Here, $w_{-1}=w_k$.
  1021. Note that $AR(w_i)=emptyset$ for $1leq i<r$ if $t=L$, and
  1022. $AL(w_i)=emptyset$ for $1leq i<r$, if $t=R$.
  1023. The lists $AL(w_i)$, $AR(w_i)$, $0leq ileq r$, are returned in an
  1024. implicit way: $AL(w_r)$ and $AR(w_r)$ are returned as the list
  1025. $T=AL(w_r),(w_r,w_{r+1})$, $AR(w_r)$ and the other lists
  1026. are returned as the list $A=$ $AR(w_{r-1}),ldots,$
  1027. $AR(w_0),(w_0,w_k),AL(w_0),ldots ,AL(w_{r-1})$,
  1028. cf. Figure~ref{result-embedding.pstex_t}.
  1029. end{enumerate}
  1030. bild{result-embedding.pstex_t}{A call {em embedding} $(e_0,t)$ returns lists
  1031. $T$ and $A$.}
  1032. The procedure {em embedding} has the same structure as the procedure
  1033. {em stronglyplanar} and is given in Program 1 on page pageref{program}.
  1034. It first constructs the stem and the spine (line (1)) of cycle $C(e_0)$,
  1035. then walks down the spine (lines (3) to (14)), and finally computes
  1036. the lists $T$ and $A$ it wants to return (lines (15) and (16)).
  1037. We first discuss the walk down the spine.
  1038. Suppose that the walk has reached vertex $w_j$.
  1039. We first recursively process the edges emanating from $w_j$
  1040. (lines (4) to (10)), and then compute the cyclic adjacency list of vertex
  1041. $w_j$ and prepare for the next iteration (lines (11) to (13)).
  1042. We discuss lines (4) to (10) first.
  1043. In general, some number of edges emanating from $w_j$ and all edges
  1044. incident to vertices $w_l$ with $l>j$ will have been processed already.
  1045. In agreement with our previous notation call the processed edges
  1046. $e_1,ldots ,e_{i-1}$.
  1047. We claim that the following statement is an invariant of the loop (4) to (10):
  1048. $T$ concatenated with $(w_j,w_{j-1})$ is the cyclic adjacency list of
  1049. vertex $w_j$ in the embedding of $C+S(e_1)+ldots +S(e_{i-1})$, and
  1050. $AL$ and $AR$ are the catenation of lists $AL(w_0),ldots ,AL(w_{j-1})$
  1051. and $AR(w_{j-1}),ldots ,AR(w_0)$ respectively where $(w_l,w_{l+1})$,
  1052. $AR(w_l), (w_l,w_{l-1}), AL(w_l)$ is the cyclic adjacency
  1053. list of vertex $w_l$, $0leq lleq j-1$, in the embedding of
  1054. $C+S(e_0)+ldots +S(e_{i-1})$.
  1055. The lists $T$, $AL$, and $AR$ are certainly initialized correctly in
  1056. line (2).
  1057. Assume now that we process edge $e'=e_i$ emanating from $w_j$.
  1058. The flag $alpha(e')$ indicates what kind of embedding of $S(e_i)$ is
  1059. needed to build a canonical embedding of $S(e_0)$; the opposite kind of
  1060. embedding of $S(e_i)$ is needed to build a reversed canonical embedding
  1061. of $S(e_0)$.
  1062. So the required kind is given by $toplusalpha(e')$, where
  1063. $Loplus L=Roplus R=L$ and $Loplus R=Roplus L=R$.
  1064. The call {em embedding}$(e',toplusalpha(e'))$ computes the cyclic
  1065. adjacency lists of the vertices in $V(e')$ and returns lists $T'$ and
  1066. $A'$ as defined above.
  1067. If $S(e_i)$ has to be glued to the left side of the vertical path
  1068. $w_0,ldots ,w_k$, i.e., if  $t=alpha(e')$ then we append $T'$ to the front of
  1069. $T$ and $A'$ to
  1070. the end of $AL$, cf. Figure~ref{glueing}.
  1071. Analogously, if $S(e_i)$ has to be glued to the right side of the
  1072. path $w_0,ldots ,w_k$, i.e., if $tnot=alpha(e')$, then we append $T'$
  1073. to the end of $T$ and $A'$ to the front of $AR$.
  1074. This clearly maintains the invariant.
  1075. Suppose now that we have processed all edges emanating from $w_j$.
  1076. Then $(w_j,w_{j-1})$ concatenated with $T$ is the cyclic adjacency list
  1077. of vertex $w_j$ (line (11)).
  1078. begin{figure}[htb]
  1079. begin{center}
  1080. input{glueing.pstex_t}
  1081. end{center}
  1082. caption{label{glueing}
  1083. Glueing $S(e')$ to the left or right side of the path
  1084. $w_0,ldots ,w_k$ respectively.}
  1085. end{figure}
  1086. We next prepare for the treatment of vertex $w_{j-1}$.
  1087. Let $T'$ and $T''$ be the list of darts incident to $w_{j-1}$ from
  1088. the left and from the right respectively and having their other
  1089. endpoint in an already embedded segment.
  1090. List $T'$ is a suffix of $AL$ and list $T''$ is a prefix of $AR$.
  1091. The catenation of $T',(w_{j-1},w_j)$, $T''$, and
  1092. $(w_{j-1},w_{j-2})$ is the current clockwise adjacency list of
  1093. vertex $w_{j-1}$.
  1094. Thus lines (12) and (13) correctly initialize $AL$, $AR$, and $T$ for
  1095. the next iteration.
  1096. Suppose now that all edges emanating from the spine of $C(e_0)$ have
  1097. been processed, i.e., control reaches line (15).
  1098. At this point, list $T$ is the ordered list of darts incident to $w_r$
  1099. (except $(w_r,w_{r-1})$) and the two lists $AL$ and $AR$ are the
  1100. ordered list of darts incident to the two sides of the stem of $C(e_0)$.
  1101. Thus $T$ and the catenation of $AR,(w_0,w_k)$, and
  1102. $AL$ are the two components of the output of {em embedding}$(e_0,t)$.
  1103. We summarize in
  1104. begin{theorem}
  1105. Let $G=(V,E)$ be a planar graph.
  1106. Then $G$ can be turned into a planar map $(G,sigma)$ in linear time.
  1107. end{theorem}
  1108. begin{table}
  1109. ~hrulefill
  1110. begin{tabbing}
  1111. qquad = {bf do} = {bf do} = kill
  1112. > (0) ' {bf procedure} {em embedding}($e_0$: edge, $t$: ${L,R}$)+\
  1113. ($*$ computes an embedding of $S(e_0)$, $e_0=(x,y)$, as described in the text; %
  1114. \
  1115. > it returns the lists $T$ and $A$ defined in the text $*$)-\
  1116. > (1) ' find the spine of segment $S(e_0)$ by starting in node $y$ and always%
  1117. +\
  1118. > take the first edge of every adjacency list until a back edge is \
  1119. > encountered. This back edge leads to node $w_0=lowpt[y]$. \
  1120. > Let $w_0,ldots,w_r$ be the tree path from $w_0$ to $x=w_r$ and \
  1121. > let $w_{r+1}=y,ldots,w_k$ be the spine constructed above. -\
  1122. > (2) ' $AL gets AR gets$ empty list of darts;\
  1123. >     > $T gets (w_k,w_0)$; ` ($*$ a list of darts $*$)\
  1124. > (3) ' {bf for} $j$ {bf from} $k$ {bf downto} $r+1$ \
  1125. > (4) ' {bf do} {bf for} all edges $e'$ (except the first) emanating from
  1126. $w_j$ \
  1127. > (5) ' > {bf do} $(T',A') gets$ {em embedding}$(e',toplusalpha(e'))$\
  1128. > (6) ' > > {bf if} $t=alpha(e')$\
  1129. > (7) ' > > {bf then} $T gets T'$ {bf conc} $T$; $AL gets AL$ {bf
  1130. conc} $A'$\
  1131. > (8) ' > > {bf else} $T gets T$ {bf conc} $T'$; $AR gets A'$ {bf
  1132. conc}  $AR$\
  1133. > (9) ' > > {bf fi}\
  1134. >(10) ' > {bf od}\
  1135. >(11) ' > {bf output} $(w_j,w_{j-1})$ {bf conc} $T$;
  1136. ` ($*$ the cyclic adjacency list of vertex $w_j$ $*$) \
  1137. >(12) ' > {bf let} $AL=AL'$ {bf conc} $T'$ and $AR=T''$
  1138. {bf conc} $AR'$\
  1139. >     > > where $T'$ and $T''$ contain all darts incident
  1140. to $w_{j-1}$;\
  1141. >(13) ' > $ALgets AL'$; $ARgets AR'$; $Tgets
  1142. T'$ {bf conc} $(w_{j-1},w_j)$ {bf conc} $T''$\
  1143. >(14) ' {bf od}\
  1144. >(15) ' $Agets$ $AR$ {bf conc} $(w_0,w_k)$ {bf conc} $AL$;\
  1145. >(16) ' {bf return} $T$ and $A$\
  1146. >(17) ' {bf end}
  1147. end{tabbing}
  1148. ~hrulefill Program 1 label{program} hrulefill
  1149. end{table}
  1150. In our implementation we follow the book except in three minor points. PB{|G}
  1151. has only one directed
  1152. version of each edge but PB{|H} has both. In the embedding
  1153. phase we need both
  1154. directions and therefore construct the embedding of
  1155. PB{|H} and later translate it back to PB{\{Gin}}. Secondly, we do not
  1156. construct the embedding
  1157. of PB{|H} vertex by vertex but in one shot. To that effect we compute a
  1158. labelling
  1159. PB{\{sort_num}} of the edges of PB{|H} and later sort the edges.
  1160. Thirdly, the book makes reference to edges $(w_{i-1},w_i)$
  1161. and their reversals. To make these edges available we compute an array PB{%
  1162. \{tree_edge_into}}
  1163. that contains for each node the incoming tree edge.
  1164. We finally want to remark on our convention for drawing lists.
  1165. In Figures ref{result-embedding.pstex_t}
  1166. and ref{glueing} the arrows indicate the end (!!!) of the lists.
  1167. clearpage
  1168. YB4X26:construct embeddingX${}E{}$6
  1169. ${}{{}$16
  1170. ${}&{list}langle&{edge}rangle{}$ |T${},{}$ |A;SHC{lists of edges of PB{%
  1171. |H} }6
  1172. &{int} \{cur_nr}${}KT{0};{}$6
  1173. ${}&{edge_array}langle&{int}rangle{}$ \{sort_num}(|H);6
  1174. ${}&{node_array}langle&{edge}rangle{}$ \{tree_edge_into}(|G);7
  1175. ${}\{embedding}(|G.\{first_adj_edge}(|G.\{first_node}(,)),39\{left},%
  1176. 39|G,39\{alpha},39\{dfsnum},39|T,39|A,39\{cur_nr},39\{sort%
  1177. _num},39\{tree_edge_into},39\{parent},39\{reversal}){}$;C{ PB{|T}
  1178. contains all edges incident to the first node except the cycle edge into it.
  1179. That edge comprises PB{|A} }6
  1180. ${}|T.\{conc}(|A);{}$7
  1181. &{edge} |e;7
  1182. &{forall} ${}(|e,39|T){}$15
  1183. ${}\{sort_num}[|e]K\{cur_nr}PP;{}$27
  1184. ${}&{edge_array}langle&{int}rangle{}$ \{sort_Gin}(\{Gin});7
  1185. ${}{{}$16
  1186. &{edge} \{ein};7
  1187. &{forall_edges} ${}(\{ein},39\{Gin}){}$15
  1188. ${}\{sort_Gin}[\{ein}]K\{sort_num}[\{companion_in_H}[\{ein}]];{}$26
  1189. 4${}}{}$26
  1190. ${}\{Gin}.\{sort_edges}(\{sort_Gin});{}$6
  1191. 4${}}{}$2par
  1192. U5.fi
  1193. M{27}It remains to describe procedure PB{\{embedding}}.
  1194. YB4X9:auxiliary functionsX${}mathrel+E{}$6
  1195. &{void} \{embedding}(&{edge} \{e0}${},39{}$&{int} |t${},39&{GRAPH}%
  1196. langle&{node},39&{edge}rangle{}$ ${}{AND}|G,39&{edge_array}langle%
  1197. &{int}rangle{}$ ${}{AND}\{alpha},3{-1}39&{node_array}langle&{int}%
  1198. rangle{}$ ${}{AND}\{dfsnum},39&{list}langle&{edge}rangle{}$ ${}{AND}%
  1199. |T,39&{list}langle&{edge}rangle{}$ ${}{AND}|A,39{}$&{int} ${}{AND}%
  1200. \{cur_nr},3{-1}39&{edge_array}langle&{int}rangle{}$ ${}{AND}\{sort%
  1201. _num},39&{node_array}langle&{edge}rangle{}$ ${}{AND}\{tree_edge%
  1202. _into},3{-1}39&{node_array}langle&{node}rangle{}$ ${}{AND}\{parent},%
  1203. 39&{edge_array}langle&{edge}rangle{}$ ${}{AND}\{reversal}){}$11226
  1204. ${}{{}$16
  1205. X28:embed: determine the cycle $C(e0)$X;6
  1206. X29:process the subsegmentsX;6
  1207. X33:prepare the outputX;6
  1208. 4${}}{}$2par
  1209. fi
  1210. M{28}We start by determining the spine cycle. This is precisley as in PB{%
  1211. \{strongly_planar}}.
  1212. We also record for the vertices $w_{r+1}$, $ldots$, $w_k$, and $w_0$ the
  1213. incoming cycle edge either in PB{\{tree_edge_into}} or in the local
  1214. variable PB{\{back_edge_into_w0}}. This is line (1) of Program1.
  1215. YB4X28:embed: determine the cycle $C(e0)$X${}E{}$6
  1216. &{node} |x${}K\{source}(\{e0});{}$6
  1217. &{node} |y${}K\{target}(\{e0});{}$7
  1218. ${}\{tree_edge_into}[|y]K\{e0};{}$7
  1219. &{edge} |e${}K|G.\{first_adj_edge}(|y);{}$6
  1220. &{node} \{wk}${}K|y;{}$7
  1221. &{while} ${}(\{dfsnum}[\{target}(|e)]>\{dfsnum}[\{wk}]{}$)SHC{ e is a
  1222. tree edge }6
  1223. ${}{{}$16
  1224. ${}\{wk}K\{target}(|e);{}$6
  1225. ${}\{tree_edge_into}[\{wk}]K|e;{}$6
  1226. ${}|eK|G.\{first_adj_edge}(\{wk});{}$6
  1227. 4${}}{}$27
  1228. &{node} \{w0}${}K\{target}(|e);{}$6
  1229. &{edge} \{back_edge_into_w0}${}K|e{}$;par
  1230. U27.fi
  1231. M{29}Lines (2) to (14).
  1232. YB4X29:process the subsegmentsX${}E{}$6
  1233. &{node} |w${}K\{wk};{}$6
  1234. ${}&{list}langle&{edge}rangle{}$ \{Al}${},{}$ \{Ar};6
  1235. ${}&{list}langle&{edge}rangle{}$ \{Tprime}${},{}$ \{Aprime};7
  1236. ${}|T.\{clear}(,);{}$6
  1237. ${}|T.\{append}(|G[|e]){}$;SHC{ PB{$|eK(\{wk},\{w0})$} at this point,
  1238. line (2) }6
  1239. &{while} ${}(|wI|x){}$5
  1240. ${}{{}$16
  1241. &{int} \{count}${}KT{0};{}$7
  1242. &{forall_adj_edges} ${}(|e,39|w){}$5
  1243. ${}{{}$16
  1244. ${}\{count}PP;{}$6
  1245. &{if} ${}(\{count}IT{1}{}$)SHC{no action for first edge }6
  1246. ${}{{}$16
  1247. X30:embed recursivelyX;6
  1248. X31:update lists PB{|T}, PB{\{Al}}, and PB{\{Ar}}X;6
  1249. 4${}}{}$SHC{ end if }26
  1250. 4${}}{}$SHC{end forall }26
  1251. X32:compute PB{|w}'s adjacency list and prepare for next iterationX;6
  1252. ${}|wK\{parent}[|w];{}$6
  1253. 4${}}{}$SHC{end while }2par
  1254. U27.fi
  1255. M{30}Line (5). The book does not distinguish between tree and back edges but
  1256. we do
  1257. here.
  1258. YB4X30:embed recursivelyX${}E{}$6
  1259. &{if} ${}(\{dfsnum}[|w]<\{dfsnum}[\{target}(|e)]){}$5
  1260. ${}{{}$C{ tree edge }16
  1261. &{int} \{tprime}${}K((|tE\{alpha}[|e])?\{left}:\{right});{}$7
  1262. ${}\{embedding}(|e,39\{tprime},39|G,39\{alpha},39\{dfsnum},39%
  1263. \{Tprime},39\{Aprime},39\{cur_nr},39\{sort_num},39\{tree_edge%
  1264. _into},39\{parent},39\{reversal});{}$6
  1265. 4${}}{}$26
  1266. &{else}5
  1267. ${}{{}$C{ back edge }16
  1268. ${}\{Tprime}.\{append}(|G[|e]){}$;SHC{$e$ }6
  1269. ${}\{Aprime}.\{append}(\{reversal}[|G[|e]]){}$;SHC{reversal of $e$ }6
  1270. 4${}}{}$2par
  1271. U29.fi
  1272. M{31}Lines (6) to (9).
  1273. YB4X31:update lists PB{|T}, PB{\{Al}}, and PB{\{Ar}}X${}E{}$6
  1274. &{if} ${}(|tE\{alpha}[|e]){}$5
  1275. ${}{{}$16
  1276. ${}\{Tprime}.\{conc}(|T);{}$6
  1277. ${}|T.\{conc}(\{Tprime}){}$;SHC{$T = Tprime conc T$ }6
  1278. ${}\{Al}.\{conc}(\{Aprime}){}$;SHC{$Al = Al conc Aprime$ }6
  1279. 4${}}{}$26
  1280. &{else}5
  1281. ${}{{}$16
  1282. ${}|T.\{conc}(\{Tprime}){}$;SHC{ $ T = T conc Tprime $ }6
  1283. ${}\{Aprime}.\{conc}(\{Ar});{}$6
  1284. ${}\{Ar}.\{conc}(\{Aprime}){}$;SHC{ $ Ar = Aprime conc Ar$ }6
  1285. 4${}}{}$2par
  1286. U29.fi
  1287. M{32}Lines (11) to (13).
  1288. YB4X32:compute PB{|w}'s adjacency list and prepare for next iteration%
  1289. X${}E{}$6
  1290. $|T.\{append}(\{reversal}[|G[\{tree_edge_into}[|w]]]){}$;SHC{
  1291. $(w_{j-1},w_j)$ }6
  1292. &{forall} ${}(|e,39|T){}$15
  1293. ${}\{sort_num}[|e]K\{cur_nr}PP{}$;C{ PB{|w}'s adjacency list is now
  1294. computed; we clear PB{|T} and prepare for the next iteration by moving all
  1295. darts incident to PB{\{parent}[|w]} from PB{\{Al}} and PB{\{Ar}} to PB{%
  1296. |T}. These darts are at the rear end of PB{\{Al}} and at the front end of %
  1297. PB{\{Ar}} }26
  1298. ${}|T.\{clear}(,);{}$6
  1299. &{while} ${}(R\{Al}.\{empty}(,)W\{source}(\{Al}.\{tail}(,))E|G[%
  1300. \{parent}[|w]]{}$)SHC{ PB{\{parent}[|w]} is in PB{|G}, PB{$\{Al}.%
  1301. \{tail}$} in PB{|H} }6
  1302. ${}{{}$16
  1303. ${}|T.\{push}(\{Al}.\{Pop}(,)){}$;SHC{Pop removes from the rear }6
  1304. 4${}}{}$26
  1305. ${}|T.\{append}(|G[\{tree_edge_into}[|w]]){}$;SHC{ push would be
  1306. equivalent }6
  1307. &{while} ${}(R\{Ar}.\{empty}(,)W\{source}(\{Ar}.\{head}(,))E|G[%
  1308. \{parent}[|w]]{}$)SHC{ }6
  1309. ${}{{}$16
  1310. ${}|T.\{append}(\{Ar}.\{pop}(,)){}$;SHC{ pop removes from the front }6
  1311. 4${}}{}$2par
  1312. U29.fi
  1313. M{33}Line (15). Concatenate PB{\{Ar}}, $(w_0,w_r)$, and PB{\{Al}}.
  1314. YB4X33:prepare the outputX${}E{}$6
  1315. $|A.\{clear}(,);{}$6
  1316. ${}|A.\{conc}(\{Ar});{}$6
  1317. ${}|A.\{append}(\{reversal}[|G[\{back_edge_into_w0}]]);{}$6
  1318. ${}|A.\{conc}(\{Al}){}$;par
  1319. U27.fi
  1320. N{1}{34}Efficiency. label{Efficiency}
  1321. Under LEDA 3.0 the space requirement of the first version of PB{\{planar}} is
  1322. approximately
  1323. $160 (n+m) +100 alpha m$ Bytes, where $n$ and $m$ denote the number of nodes
  1324. and edges respectively and $alpha$ is the fraction of edges in the input graph
  1325. that do not have their reversal in the input graph. For the pseudo-random
  1326. planar graphs generated in the demo we have $alpha = 0$ and $m = 4n$ and hence
  1327. the
  1328. space requirement is about $800 n$ Bytes. The second version needs an
  1329. additional
  1330. $54n + 66m$ Bytes.
  1331. The running time of PB{\{planar}} is about $50$ times the running
  1332. time of PB{\{STRONG_COMPONENTS}}. On a 50 MIPS SPARC10 workstation
  1333. the planarity of a
  1334. planar graph with 16000 nodes and 30000 edges ($alpha = 0$) is tested in
  1335. about 10 seconds. It takes 5.4 seconds to make the graph bidirected and
  1336. biconnected, about 3.9 seconds to test its planarity, and
  1337. another 6.1 seconds to
  1338. construct an embedding. The space requirement is about 15 MByte.
  1339. fi
  1340. N{1}{35}A Demo. label{demo}
  1341. The demo allows the user to either interactively construct a graph
  1342. using
  1343. LEDA's graph editor or to construct a random graph, or to
  1344. construct a ``pseudo-random'' planar graph
  1345. (the graph defined by an arrangement of random line segments). The graph is
  1346. then tested for
  1347. planarity. If the graph is planar a straight-line embedding is output. If the
  1348. graph is non-planar a Kuratowski subgraph is highlighted.
  1349. The demo proceeds in cycles. In each cycle we first clear the graphics window %
  1350. PB{|W} and
  1351. the graph PB{|G} and then give the user the choice of a new input graph.
  1352. YB4X35:.{demo.c }X${}E{}$6
  1353. X3:includesX;6
  1354. X37:procedure to draw graphsX;6
  1355. \{main}(,)11 ${$ X38:initiation and declarationsX;6
  1356. &{while} (\{true}) ${$ X39:select graphX;6
  1357. X40:test graph for planarity and show outputX X41:reset windowX;6
  1358. $}$ &{return} T{0}; $}{}$par
  1359. fi
  1360. M{36}We need to include PB{$\{planar}.|h$} and various parts of LEDA.
  1361. YB4X3:includesX${}mathrel+E{}$6
  1362. 8#&{include} .{"planar.h"}6
  1363. 8#&{include} .{<LEDA/graph.h>}6
  1364. 8#&{include} .{<LEDA/graph_alg.h>}6
  1365. 8#&{include} .{<LEDA/window.h>}6
  1366. 8#&{include} .{<LEDA/graph_edit.h>}par
  1367. fi
  1368. M{37}We need a simple procedure to draw a graph in a graphics window. The
  1369. numbering of the nodes is optional.
  1370. YB4X37:procedure to draw graphsX${}E{}$6
  1371. &{void} \{draw_graph}(&{const} &{GRAPH}${}langle&{point},39&{int}%
  1372. rangle{}$ ${}{AND}|G,39{}$&{window} ${}{AND}|W,39{}$&{bool} %
  1373. \{numbering}${}K\{false}){}$11226
  1374. ${}{{}$16
  1375. &{node} |v;6
  1376. &{edge} |e;6
  1377. &{int} |i${}KT{0};{}$7
  1378. &{forall_edges} ${}(|e,39|G){}$15
  1379. ${}|W.\{draw_edge}(|G[\{source}(|e)],39|G[\{target}(|e)],39%
  1380. \{blue});{}$26
  1381. &{if} (\{numbering})16
  1382. &{forall_nodes} ${}(|v,39|G){}$15
  1383. ${}|W.\{draw_int_node}(|G[|v],39|iPP,39\{red});{}$226
  1384. &{else}16
  1385. &{forall_nodes} ${}(|v,39|G){}$15
  1386. ${}|W.\{draw_filled_node}(|G[|v],39\{red});{}$226
  1387. 4${}}{}$2par
  1388. U35.fi
  1389. M{38}We give the user a short explanation of the demo and declare some
  1390. variables.
  1391. YB4X38:initiation and declarationsX${}E{}$6
  1392. &{panel} |P;7
  1393. ${}|P.\{text_item}(.{"This demo illustrat}).{es planarity testing})%
  1394. .{ and planar straight}).{-line"});{}$6
  1395. ${}|P.\{text_item}(.{"embedding. You have}).{ two ways to constru}%
  1396. ).{ct a graph: either i}).{nteractively"});{}$6
  1397. ${}|P.\{text_item}(.{"using the LEDA grap}).{h editor or by calli}%
  1398. ).{ng one of two graph }).{generators."});{}$6
  1399. ${}|P.\{text_item}(.{"The first generator}).{ constructs a random})%
  1400. .{ graph with a certai}).{n"});{}$6
  1401. ${}|P.\{text_item}(.{"number of nodes and}).{ edges (you will be
  1402. }).{asked how many) and }).{the "});{}$6
  1403. ${}|P.\{text_item}(.{"second generator co}).{nstructs a planar gr})%
  1404. .{aph  by intersecting}).{ a certain"});{}$6
  1405. ${}|P.\{text_item}(.{"number of random li}).{ne segments in the u}%
  1406. ).{nit square (you will}).{ be asked how many).}).{"});{}$6
  1407. ${}|P.\{text_item}(.{" "});{}$6
  1408. ${}|P.\{text_item}(.{"The graph is displa}).{yed and then tested }%
  1409. ).{for planarity."});{}$6
  1410. ${}|P.\{text_item}(.{"If the graph is non}).{-planar a Kuratowski}%
  1411. ).{ subgraph is highlig}).{hted."});{}$6
  1412. ${}|P.\{text_item}(.{"If the graph is pla}).{nar, a straight-line}%
  1413. ).{ drawing is produced}).{."});{}$6
  1414. ${}|P.\{button}(.{"continue"});{}$6
  1415. ${}|P.\{open}(,);{}$7
  1416. &{window} |W;6
  1417. ${}&{GRAPH}langle&{point},39&{int}rangle{}$ |G;6
  1418. &{node} |v${},{}$ |w;6
  1419. &{edge} |e;6
  1420. &{int} |n${}KT{250};{}$6
  1421. &{int} |m${}KT{250};{}$6
  1422. &{const} &{double} \{pi}${}KT{3.14};{}$6
  1423. &{panel} \{P1}(.{"PLANARITY TEST"});7
  1424. ${}\{P1}.\{int_item}(.{"|V| = "},39|n,39T{0},39T{500});{}$6
  1425. ${}\{P1}.\{int_item}(.{"|E| = "},39|m,39T{0},39T{500});{}$6
  1426. ${}\{P1}.\{button}(.{"edit"});{}$6
  1427. ${}\{P1}.\{button}(.{"random"});{}$6
  1428. ${}\{P1}.\{button}(.{"planar"});{}$6
  1429. ${}\{P1}.\{button}(.{"quit"});{}$6
  1430. ${}\{P1}.\{text_item}(.{" "});{}$6
  1431. ${}\{P1}.\{text_item}(.{"The first slider as}).{ks for the number
  1432. n }).{of nodes and"});{}$6
  1433. ${}\{P1}.\{text_item}(.{"the second slider a}).{sks for the number
  1434. m}).{ of edges."});{}$6
  1435. ${}\{P1}.\{text_item}(.{"If you select the r}).{andom input button
  1436. t}).{hen a graph with"});{}$6
  1437. ${}\{P1}.\{text_item}(.{"that number of node}).{s and edges is
  1438. const}).{ructed, if you"});{}$6
  1439. ${}\{P1}.\{text_item}(.{"select the planar i}).{nput button then
  1440. 2.5}).{ times square-root o}).{f n"});{}$6
  1441. ${}\{P1}.\{text_item}(.{"random line segment}).{s are chosen and
  1442. int}).{ersected to yield"});{}$6
  1443. ${}\{P1}.\{text_item}(.{"a planar graph with}).{ about n nodes,
  1444. and }).{if you select the"});{}$6
  1445. ${}\{P1}.\{text_item}(.{"edit button then th}).{e graph editor is
  1446. ca}).{lled."});{}$6
  1447. ${}\{P1}.\{text_item}(.{" "}){}$;par
  1448. U35.fi
  1449. M{39}We display the panel PB{\{P1}} until the user makes his choice. Then we
  1450. construct
  1451. the appropriate graph.
  1452. YB4X39:select graphX${}E{}$6
  1453. &{int} \{inp}${}K\{P1}.\{open}(|W){}$;SHC{ P1 is displayed until a
  1454. button is pressed }7
  1455. &{if} ${}(\{inp}ET{3}){}$15
  1456. &{break};SHC{ quit button pressed }26
  1457. ${}|W.\{init}(T{0},39T{1000},39T{0});{}$6
  1458. ${}|W.\{set_node_width}(T{5});{}$6
  1459. &{switch} (\{inp})5
  1460. ${}{{}$16
  1461. 4&{case} T{0}:6
  1462. ${}{{}$SHC{ graph editor }16
  1463. ${}|W.\{set_node_width}(T{10});{}$6
  1464. ${}|G.\{clear}(,);{}$6
  1465. ${}\{graph_edit}(|W,39|G,39\{false});{}$6
  1466. &{break};6
  1467. 4${}}{}$26
  1468. 4&{case} T{1}:6
  1469. ${}{{}$SHC{ random graph }16
  1470. ${}|G.\{clear}(,);{}$6
  1471. ${}\{random_graph}(|G,39|n,39|m){}$;C{ eliminate parallel edges and
  1472. self-loops }6
  1473. \{eliminate_parallel_edges}(|G);7
  1474. ${}&{list}langle&{edge}rangle{}$ \{Del}${}K|G.\{all_edges}(,);{}$7
  1475. &{forall} ${}(|e,39\{Del}){}$16
  1476. &{if} ${}(|G.\{source}(|e)E|G.\{target}(|e)){}$15
  1477. ${}|G.\{del_edge}(|e){}$;C{ draw the graph with its nodes on a circle}22%
  1478. 7
  1479. &{float} \{ang}${}KT{0};{}$7
  1480. &{forall_nodes} ${}(|v,39|G){}$5
  1481. ${}{{}$16
  1482. ${}|G[|v]K&{point}(T{500}+T{400}*\{sin}(\{ang}),39T{500}+T{400}*%
  1483. \{cos}(\{ang}));{}$6
  1484. ${}\{ang}MRL{+{K}}T{2}*\{pi}/|n;{}$6
  1485. 4${}}{}$26
  1486. ${}\{draw_graph}(|G,39|W);{}$6
  1487. &{break};6
  1488. 4${}}{}$26
  1489. 4&{case} T{2}:6
  1490. ${}{{}$SHC{ pseudo-random planar graph }16
  1491. ${}&{node_array}langle&{double}rangle{}$ \{xcoord}(|G);6
  1492. ${}&{node_array}langle&{double}rangle{}$ \{ycoord}(|G);7
  1493. ${}|G.\{clear}(,);{}$6
  1494. ${}\{random_planar_graph}(|G,39\{xcoord},39\{ycoord},39|n);{}$6
  1495. &{forall_nodes} ${}(|v,39|G){}$15
  1496. ${}|G[|v]K&{point}(T{1000}*\{xcoord}[|v],39T{900}*\{ycoord}[|v]);{}$%
  1497. 26
  1498. ${}\{draw_graph}(|G,39|W);{}$6
  1499. &{break};6
  1500. 4${}}{}$26
  1501. 4${}}{}$2par
  1502. U35.fi
  1503. M{40}We test the planarity of our graph PB{|G} using our procedure PB{%
  1504. \{planar}}.
  1505. YB4X40:test graph for planarity and show outputX${}E{}$6
  1506. &{if} ${}(\{PLANAR}(|G,39\{false})){}$5
  1507. ${}{{}$16
  1508. &{if} ${}(|G.\{number_of_nodes}(,)<T{4}){}$15
  1509. ${}|W.\{message}(.{"That's an insult: E}).{very graph with |V| })%
  1510. .{<= 4 is planar"});{}$26
  1511. &{else}5
  1512. ${}{{}$16
  1513. ${}|W.\{message}(.{"G is planar. I comp}).{ute a straight-line })%
  1514. .{embedding ..."}){}$;C{ we first make PB{|G} bidirected. We remember the
  1515. edges added in PB{\{n_edges}} }7
  1516. ${}&{node_array}langle&{int}rangle{}$ \{nr}(|G);6
  1517. ${}&{edge_array}langle&{int}rangle{}$ \{cost}(|G);6
  1518. &{int} \{cur_nr}${}KT{0};{}$6
  1519. &{int} |n${}K|G.\{number_of_nodes}(,);{}$6
  1520. &{node} |v;6
  1521. &{edge} |e;7
  1522. &{forall_nodes} ${}(|v,39|G){}$15
  1523. ${}\{nr}[|v]K\{cur_nr}PP;{}$26
  1524. &{forall_edges} ${}(|e,39|G){}$15
  1525. ${}\{cost}[|e]K((\{nr}[\{source}(|e)]<\{nr}[\{target}(|e)])?|n*%
  1526. \{nr}[\{source}(|e)]+\{nr}[\{target}(|e)]:|n*\{nr}[\{target}(|e)]+%
  1527. \{nr}[\{source}(|e)]);{}$26
  1528. ${}|G.\{sort_edges}(\{cost});{}$7
  1529. ${}&{list}langle&{edge}rangle{}$ |L${}K|G.\{all_edges}(,);{}$6
  1530. ${}&{list}langle&{edge}rangle{}$ \{n_edges};7
  1531. &{while} ${}(R|L.\{empty}(,)){}$5
  1532. ${}{{}$16
  1533. ${}|eK|L.\{pop}(,);{}$6
  1534. &{if} ${}(R|L.\{empty}(,)W\{source}(|e)E\{target}(|L.\{head}(,))W%
  1535. \{target}(|e)E\{source}(|L.\{head}(,))){}$15
  1536. ${}|L.\{pop}(,);{}$26
  1537. &{else}5
  1538. ${}{{}$16
  1539. ${}\{n_edges}.\{append}(|G.\{new_edge}(\{target}(|e),39\{source}(%
  1540. |e)));{}$6
  1541. 4${}}{}$26
  1542. 4${}}{}$26
  1543. \{Make_biconnected_graph}(|G);6
  1544. ${}\{PLANAR}(|G,39\{true});{}$7
  1545. ${}&{node_array}langle&{int}rangle{}$ \{xcoord}(|G)${},{}$ \{ycoord}(%
  1546. |G);7
  1547. ${}\{STRAIGHT_LINE_EMBEDDING}(|G,39\{xcoord},39\{ycoord});{}$7
  1548. &{float} |f${}KT{900.0}/(T{2}*|G.\{number_of_nodes}(,));{}$7
  1549. &{forall_nodes} ${}(|v,39|G){}$15
  1550. ${}|G[|v]K&{point}(|f*\{xcoord}[|v]+T{30},39T{2}*|f*\{ycoord}[|v]+%
  1551. T{30});{}$26
  1552. &{forall} ${}(|e,39\{n_edges}){}$15
  1553. ${}|G.\{del_edge}(|e);{}$26
  1554. ${}|W.\{clear}(,);{}$6
  1555. &{if} ${}(\{inp}ET{0}){}$15
  1556. ${}\{draw_graph}(|G,39|W,39\{true}){}$;SHC{ with node numbering }26
  1557. &{else}15
  1558. ${}\{draw_graph}(|G,39|W);{}$26
  1559. 4${}}{}$26
  1560. 4${}}{}$26
  1561. &{else}5
  1562. ${}{{}$16
  1563. ${}|W.\{message}(.{"Graph is not planar}).{. I compute the Kura})%
  1564. .{towski subgraph ..."});{}$7
  1565. ${}&{list}langle&{edge}rangle{}$ |L;7
  1566. ${}\{PLANAR}(|G,39|L,39\{false});{}$7
  1567. ${}&{node_array}langle&{int}rangle{}$ ${}\{deg}(|G,39T{0});{}$6
  1568. &{int} \{lw}${}K|W.\{set_line_width}(T{3});{}$6
  1569. &{edge} |e;7
  1570. &{forall} ${}(|e,39|L){}$5
  1571. ${}{{}$16
  1572. &{node} |v${}K\{source}(|e);{}$6
  1573. &{node} |w${}K\{target}(|e);{}$7
  1574. ${}\{deg}[|v]PP;{}$6
  1575. ${}\{deg}[|w]PP;{}$6
  1576. ${}|W.\{draw_edge}(|G[|v],39|G[|w]);{}$6
  1577. 4${}}{}$27
  1578. &{int} |i${}KT{1}{}$;C{ We highlight the Kuratowski subgraph. Nodes with
  1579. degree are drawn black. The nodes with larger degree are shown green and
  1580. numbered from 1 to 6 }7
  1581. &{forall_nodes} ${}(|v,39|G){}$5
  1582. ${}{{}$16
  1583. &{if} ${}(\{deg}[|v]ET{2}){}$15
  1584. ${}|W.\{draw_filled_node}(|G[|v],39\{black});{}$26
  1585. &{if} ${}(\{deg}[|v]>T{2}){}$5
  1586. ${}{{}$16
  1587. &{int} \{nw}${}K|W.\{set_node_width}(T{10});{}$7
  1588. ${}|W.\{draw_int_node}(|G[|v],39|iPP,39\{green});{}$6
  1589. ${}|W.\{set_node_width}(\{nw});{}$6
  1590. 4${}}{}$26
  1591. 4${}}{}$26
  1592. ${}|W.\{set_line_width}(\{lw});{}$6
  1593. 4${}}{}$2par
  1594. U35.fi
  1595. M{41}We reset the graphics window.
  1596. YB4X41:reset windowX${}E{}$6
  1597. $|W.\{set_show_coordinates}(\{false});{}$6
  1598. ${}|W.\{set_frame_label}(.{"click any button to}).{ continue"});{}$6
  1599. ${}|W.\{read_mouse}(,){}$;SHC{ wait for a click }6
  1600. ${}|W.\{reset_frame_label}(,);{}$6
  1601. ${}|W.\{set_show_coordinates}(\{true}){}$;par
  1602. U35.fi
  1603. N{1}{42}Some Theory.    label{reprint}
  1604. We give the theory underlying the planarity test as described in
  1605. cite[section IV.10]{Me:book}.
  1606. %Our next ...
  1607. bibliography{/KM/usr/mehlhorn/tex/my}
  1608. bibliographystyle{alpha}
  1609. end{document}
  1610. fi