graphIsolator.c

Go to the documentation of this file.
00001 /* Copyright (c) 2005 by John M. Boyer, All Rights Reserved.  Please see
00002  * License.txt for use and redistribution license. */
00003 /* Copyright (c) 1999-2003 by John M. Boyer, All Rights Reserved.
00004         This code may not be reproduced or disseminated in whole or in part 
00005         without the written permission of the author. */
00006 
00007 #define GRAPHISOLATOR_C
00008 
00009 #include "graph_boyer.h"
00010 
00011 /* Imported functions */
00012 extern void _FillVisitedFlags (graphP,
00013                                int);
00014 extern int _GetNextVertexOnExternalFace (graphP theGraph,
00015                                          int curVertex,
00016                                          int *pPrevLink);
00017 extern int _JoinBicomps (graphP theGraph);
00018 extern void _RecordPertinentChildBicomp (graphP theGraph,
00019                                          int I,
00020                                          int RootVertex);
00021 extern int _GetPertinentChildBicomp (graphP theGraph,
00022                                      int W);
00023 extern int _ChooseTypeOfNonplanarityMinor (graphP theGraph,
00024                                            int I,
00025                                            int R);
00026 
00027 /* Private function declarations (exported within system) */
00028 int _IsolateKuratowskiSubgraph (graphP theGraph,
00029                                 int I);
00030 int _FindUnembeddedEdgeToAncestor (graphP theGraph,
00031                                    int cutVertex,
00032                                    int *pAncestor,
00033                                    int *pDescendant);
00034 int _FindUnembeddedEdgeToCurVertex (graphP theGraph,
00035                                     int cutVertex,
00036                                     int *pDescendant);
00037 int _FindUnembeddedEdgeToSubtree (graphP theGraph,
00038                                   int ancestor,
00039                                   int SubtreeRoot,
00040                                   int *pDescendant);
00041 int _MarkDFSPath (graphP theGraph,
00042                   int ancestor,
00043                   int descendant);
00044 int _MarkPathAlongBicompExtFace (graphP theGraph,
00045                                  int startVert,
00046                                  int endVert);
00047 int _AddAndMarkEdge (graphP theGraph,
00048                      int ancestor,
00049                      int descendant);
00050 void _AddBackEdge (graphP theGraph,
00051                    int ancestor,
00052                    int descendant);
00053 int _DeleteUnmarkedVerticesAndEdges (graphP theGraph);
00054 int _InitializeIsolatorContext (graphP theGraph);
00055 int _IsolateMinorA (graphP theGraph);
00056 int _IsolateMinorB (graphP theGraph);
00057 int _IsolateMinorC (graphP theGraph);
00058 int _IsolateMinorD (graphP theGraph);
00059 int _IsolateMinorE (graphP theGraph);
00060 int _IsolateMinorE1 (graphP theGraph);
00061 int _IsolateMinorE2 (graphP theGraph);
00062 int _IsolateMinorE3 (graphP theGraph);
00063 int _IsolateMinorE4 (graphP theGraph);
00064 int _GetLeastAncestorConnection (graphP theGraph,
00065                                  int cutVertex);
00066 int _MarkDFSPathsToDescendants (graphP theGraph);
00067 int _AddAndMarkUnembeddedEdges (graphP theGraph);
00068 
00069 /****************************************************************************
00070  gp_IsolateKuratowskiSubgraph()
00071  ****************************************************************************/
00072 int _IsolateKuratowskiSubgraph (graphP theGraph,
00073                                 int I)
00074 {
00075 
00076 /*
00077 int  RetVal;
00078 */
00079   int RetVal = NOTOK;
00080 
00081 /* Begin by determining which of the non-planarity Minors was encountered
00082         and the principal bicomp on which the isolator will focus attention. */
00083   if (_ChooseTypeOfNonplanarityMinor (theGraph, I, NIL) != OK)
00084     return NOTOK;
00085   if (_InitializeIsolatorContext (theGraph) != OK)
00086     return NOTOK;
00087 
00088 /* Call the appropriate isolator */
00089   if (theGraph->IC.minorType & FLAGS_MINOR_A)
00090     RetVal = _IsolateMinorA (theGraph);
00091 
00092   else if (theGraph->IC.minorType & FLAGS_MINOR_B)
00093     RetVal = _IsolateMinorB (theGraph);
00094 
00095   else if (theGraph->IC.minorType & FLAGS_MINOR_C)
00096     RetVal = _IsolateMinorC (theGraph);
00097 
00098   else if (theGraph->IC.minorType & FLAGS_MINOR_D)
00099     RetVal = _IsolateMinorD (theGraph);
00100 
00101   else if (theGraph->IC.minorType & FLAGS_MINOR_E)
00102     RetVal = _IsolateMinorE (theGraph);
00103 
00104 /* Delete the unmarked edges and vertices, and return */
00105   if (RetVal == OK)
00106     RetVal = _DeleteUnmarkedVerticesAndEdges (theGraph);
00107   return RetVal;
00108 }
00109 
00110 
00111 /****************************************************************************
00112  _InitializeIsolatorContext()
00113  ****************************************************************************/
00114 int _InitializeIsolatorContext (graphP theGraph)
00115 {
00116   isolatorContextP IC = &theGraph->IC;
00117 
00118 /* Obtains the edges connecting X and Y to ancestors of the current vertex */
00119   if (_FindUnembeddedEdgeToAncestor (theGraph, IC->x, &IC->ux, &IC->dx) !=
00120       OK || _FindUnembeddedEdgeToAncestor (theGraph, IC->y, &IC->uy,
00121                                            &IC->dy) != OK)
00122     return NOTOK;
00123 
00124 /* For Minor B, we seek the last pertinent child biconnected component, which
00125      is externally active, and obtain the DFS child in its root edge.
00126      This child is the subtree root containing vertices with connections to
00127      both the current vertex and an ancestor of the current vertex. */
00128   if (theGraph->IC.minorType & FLAGS_MINOR_B)
00129 
00130   {
00131     int SubtreeRoot =
00132       LCGetPrev (theGraph->BicompLists, theGraph->V[IC->w].pertinentBicompList,
00133                  NIL);
00134     IC->uz = theGraph->V[SubtreeRoot].Lowpoint;
00135     if (_FindUnembeddedEdgeToSubtree (theGraph, IC->v, SubtreeRoot, &IC->dw)
00136         != OK
00137         || _FindUnembeddedEdgeToSubtree (theGraph, IC->uz, SubtreeRoot,
00138                                          &IC->dz) != OK)
00139       return NOTOK;
00140   }
00141 
00142 /* For all other minors, we obtain  */
00143 
00144   else
00145 
00146   {
00147     if (_FindUnembeddedEdgeToCurVertex (theGraph, IC->w, &IC->dw) != OK)
00148       return NOTOK;
00149     if (theGraph->IC.minorType & FLAGS_MINOR_E)
00150       if (_FindUnembeddedEdgeToAncestor (theGraph, IC->z, &IC->uz, &IC->dz) !=
00151           OK)
00152         return NOTOK;
00153   }
00154   return OK;
00155 }
00156 
00157 
00158 /****************************************************************************
00159  _IsolateMinorA(): Isolate a K3,3 homeomorph 
00160  ****************************************************************************/
00161 int _IsolateMinorA (graphP theGraph)
00162 {
00163   isolatorContextP IC = &theGraph->IC;
00164   if (_MarkPathAlongBicompExtFace (theGraph, IC->r, IC->r) != OK
00165       || _MarkDFSPath (theGraph, MIN (IC->ux, IC->uy), IC->r) != OK
00166       || _MarkDFSPathsToDescendants (theGraph) != OK
00167       || _JoinBicomps (theGraph) != OK
00168       || _AddAndMarkUnembeddedEdges (theGraph) != OK)
00169     return NOTOK;
00170   return OK;
00171 }
00172 
00173 
00174 /****************************************************************************
00175  _IsolateMinorB(): Isolate a K3,3 homeomorph 
00176  ****************************************************************************/
00177 int _IsolateMinorB (graphP theGraph)
00178 {
00179   isolatorContextP IC = &theGraph->IC;
00180   if (_MarkPathAlongBicompExtFace (theGraph, IC->r, IC->r) != OK
00181       || _MarkDFSPath (theGraph, MIN3 (IC->ux, IC->uy, IC->uz),
00182                        MAX3 (IC->ux, IC->uy,
00183                              IC->uz)) !=
00184       OK || _MarkDFSPathsToDescendants (theGraph) !=
00185       OK || _JoinBicomps (theGraph) !=
00186       OK || _AddAndMarkUnembeddedEdges (theGraph) != OK)
00187     return NOTOK;
00188   return OK;
00189 }
00190 
00191 
00192 /****************************************************************************
00193  _IsolateMinorC(): Isolate a K3,3 homeomorph 
00194  ****************************************************************************/
00195 int _IsolateMinorC (graphP theGraph)
00196 {
00197   isolatorContextP IC = &theGraph->IC;
00198   if (theGraph->G[IC->px].type == VERTEX_HIGH_RXW)
00199 
00200   {
00201     int highY = theGraph->G[IC->py].type == VERTEX_HIGH_RYW ? IC->py : IC->y;
00202     if (_MarkPathAlongBicompExtFace (theGraph, IC->r, highY) != OK)
00203       return NOTOK;
00204   }
00205 
00206   else
00207 
00208   {
00209     if (_MarkPathAlongBicompExtFace (theGraph, IC->x, IC->r) != OK)
00210       return NOTOK;
00211   }
00212   if (_MarkDFSPathsToDescendants (theGraph) != OK
00213       || _MarkDFSPath (theGraph, MIN (IC->ux, IC->uy), IC->r) != OK
00214       || _JoinBicomps (theGraph) != OK
00215       || _AddAndMarkUnembeddedEdges (theGraph) != OK)
00216     return NOTOK;
00217   return OK;
00218 }
00219 
00220 
00221 /****************************************************************************
00222  _IsolateMinorD(): Isolate a K3,3 homeomorph 
00223  ****************************************************************************/
00224 int _IsolateMinorD (graphP theGraph)
00225 {
00226   isolatorContextP IC = &theGraph->IC;
00227   if (_MarkPathAlongBicompExtFace (theGraph, IC->x, IC->y) != OK
00228       || _MarkDFSPath (theGraph, MIN (IC->ux, IC->uy), IC->r) != OK
00229       || _MarkDFSPathsToDescendants (theGraph) != OK
00230       || _JoinBicomps (theGraph) != OK
00231       || _AddAndMarkUnembeddedEdges (theGraph) != OK)
00232     return NOTOK;
00233   return OK;
00234 }
00235 
00236 
00237 /****************************************************************************
00238  _IsolateMinorE()
00239  ****************************************************************************/
00240 int _IsolateMinorE (graphP theGraph)
00241 {
00242   isolatorContextP IC = &theGraph->IC;
00243 
00244 /* Minor E1: Isolate a K3,3 homeomorph */
00245   if (IC->z != IC->w)
00246     return _IsolateMinorE1 (theGraph);
00247 
00248 /* Minor E2: Isolate a K3,3 homeomorph */
00249   if (IC->uz > MAX (IC->ux, IC->uy))
00250     return _IsolateMinorE2 (theGraph);
00251 
00252 /* Minor E3: Isolate a K3,3 homeomorph */
00253   if (IC->uz < MAX (IC->ux, IC->uy) && IC->ux != IC->uy)
00254     return _IsolateMinorE3 (theGraph);
00255 
00256 /* Minor E4: Isolate a K3,3 homeomorph */
00257 
00258   else if (IC->x != IC->px || IC->y != IC->py)
00259     return _IsolateMinorE4 (theGraph);
00260 
00261 /* Minor E: Isolate a K5 homeomorph */
00262   if (_MarkPathAlongBicompExtFace (theGraph, IC->r, IC->r) != OK
00263       || _MarkDFSPath (theGraph, MIN3 (IC->ux, IC->uy, IC->uz), IC->r) != OK
00264       || _MarkDFSPathsToDescendants (theGraph) != OK
00265       || _JoinBicomps (theGraph) != OK
00266       || _AddAndMarkUnembeddedEdges (theGraph) != OK)
00267     return NOTOK;
00268   return OK;
00269 }
00270 
00271 
00272 /****************************************************************************
00273  _IsolateMinorE1()
00274 
00275  Reduce to Minor C if the vertex Z responsible for external activity
00276  below the X-Y path does not equal the pertinent vertex W.
00277  ****************************************************************************/
00278 int _IsolateMinorE1 (graphP theGraph)
00279 {
00280   isolatorContextP IC = &theGraph->IC;
00281   if (theGraph->G[IC->z].type == VERTEX_LOW_RXW)
00282 
00283   {
00284     theGraph->G[IC->px].type = VERTEX_HIGH_RXW;
00285     IC->x = IC->z;
00286     IC->ux = IC->uz;
00287     IC->dx = IC->dz;
00288   }
00289 
00290   else if (theGraph->G[IC->z].type == VERTEX_LOW_RYW)
00291 
00292   {
00293     theGraph->G[IC->py].type = VERTEX_HIGH_RYW;
00294     IC->y = IC->z;
00295     IC->uy = IC->uz;
00296     IC->dy = IC->dz;
00297   }
00298 
00299   else
00300     return NOTOK;
00301   IC->z = IC->uz = IC->dz = NIL;
00302   theGraph->IC.minorType ^= FLAGS_MINOR_E;
00303   theGraph->IC.minorType |= (FLAGS_MINOR_C | FLAGS_MINOR_E1);
00304   return _IsolateMinorC (theGraph);
00305 }
00306 
00307 
00308 /****************************************************************************
00309  _IsolateMinorE2()
00310 
00311  If uZ (which is the ancestor of I that is adjacent to Z) is a 
00312  descendant of both uY and uX, then we reduce to Minor A
00313  ****************************************************************************/
00314 int _IsolateMinorE2 (graphP theGraph)
00315 {
00316   isolatorContextP IC = &theGraph->IC;
00317   _FillVisitedFlags (theGraph, 0);
00318   IC->v = IC->uz;
00319   IC->dw = IC->dz;
00320   IC->z = IC->uz = IC->dz = NIL;
00321   theGraph->IC.minorType ^= FLAGS_MINOR_E;
00322   theGraph->IC.minorType |= (FLAGS_MINOR_A | FLAGS_MINOR_E2);
00323   return _IsolateMinorA (theGraph);
00324 }
00325 
00326 
00327 /****************************************************************************
00328  _IsolateMinorE3()
00329  ****************************************************************************/
00330 int _IsolateMinorE3 (graphP theGraph)
00331 {
00332   isolatorContextP IC = &theGraph->IC;
00333   if (IC->ux < IC->uy)
00334 
00335   {
00336     if (_MarkPathAlongBicompExtFace (theGraph, IC->r, IC->px) != OK
00337         || _MarkPathAlongBicompExtFace (theGraph, IC->w, IC->y) != OK)
00338       return NOTOK;
00339   }
00340 
00341   else
00342 
00343   {
00344     if (_MarkPathAlongBicompExtFace (theGraph, IC->x, IC->w) != OK
00345         || _MarkPathAlongBicompExtFace (theGraph, IC->py, IC->r) != OK)
00346       return NOTOK;
00347   }
00348   if (_MarkDFSPath (theGraph, MIN3 (IC->ux, IC->uy, IC->uz), IC->r) != OK
00349       || _MarkDFSPathsToDescendants (theGraph) != OK
00350       || _JoinBicomps (theGraph) != OK
00351       || _AddAndMarkUnembeddedEdges (theGraph) != OK)
00352     return NOTOK;
00353   theGraph->IC.minorType |= FLAGS_MINOR_E3;
00354   return OK;
00355 }
00356 
00357 
00358 /****************************************************************************
00359  _IsolateMinorE4()
00360  ****************************************************************************/
00361 int _IsolateMinorE4 (graphP theGraph)
00362 {
00363   isolatorContextP IC = &theGraph->IC;
00364   if (IC->px != IC->x)
00365 
00366   {
00367     if (_MarkPathAlongBicompExtFace (theGraph, IC->r, IC->w) != OK
00368         || _MarkPathAlongBicompExtFace (theGraph, IC->py, IC->r) != OK)
00369       return NOTOK;
00370   }
00371 
00372   else
00373 
00374   {
00375     if (_MarkPathAlongBicompExtFace (theGraph, IC->r, IC->px) != OK
00376         || _MarkPathAlongBicompExtFace (theGraph, IC->w, IC->r) != OK)
00377       return NOTOK;
00378   }
00379   if (_MarkDFSPath
00380       (theGraph, MIN3 (IC->ux, IC->uy, IC->uz),
00381        MAX3 (IC->ux, IC->uy,
00382              IC->uz)) != OK || _MarkDFSPathsToDescendants (theGraph) !=
00383       OK || _JoinBicomps (theGraph) !=
00384       OK || _AddAndMarkUnembeddedEdges (theGraph) != OK)
00385     return NOTOK;
00386   theGraph->IC.minorType |= FLAGS_MINOR_E4;
00387   return OK;
00388 }
00389 
00390 
00391 /****************************************************************************
00392  _GetLeastAncestorConnection()
00393 
00394  This function searches for an ancestor of the current vertex I adjacent by a
00395  cycle edge to the given cutVertex or one of its DFS descendants appearing in
00396  a separated bicomp. The given cutVertex is assumed to be externally active 
00397  such that either the leastAncestor or the lowpoint of a separated DFS child 
00398  is less than I.  We obtain the minimum possible connection from the cutVertex 
00399  to an ancestor of I.
00400  ****************************************************************************/
00401 int _GetLeastAncestorConnection (graphP theGraph,
00402                                  int cutVertex)
00403 {
00404   int subtreeRoot = theGraph->V[cutVertex].separatedDFSChildList;
00405   int ancestor = theGraph->V[cutVertex].leastAncestor;
00406   if (subtreeRoot != NIL && ancestor > theGraph->V[subtreeRoot].Lowpoint)
00407     ancestor = theGraph->V[subtreeRoot].Lowpoint;
00408   return ancestor;
00409 }
00410 
00411 
00412 /****************************************************************************
00413  _FindUnembeddedEdgeToAncestor()
00414 
00415  This function searches for an ancestor of the current vertex I adjacent by a
00416  cycle edge to the given cutVertex or one of its DFS descendants appearing in
00417  a separated bicomp.
00418 
00419  The given cutVertex is assumed to be externally active such that either the
00420  leastAncestor or the lowpoint of a separated DFS child is less than I.
00421  We obtain the minimum possible connection from the cutVertex to an ancestor
00422  of I, then compute the descendant accordingly.
00423  ****************************************************************************/
00424 int _FindUnembeddedEdgeToAncestor (graphP theGraph,
00425                                    int cutVertex,
00426                                    int *pAncestor,
00427                                    int *pDescendant)
00428 {
00429   *pAncestor = _GetLeastAncestorConnection (theGraph, cutVertex);
00430   if (*pAncestor == theGraph->V[cutVertex].leastAncestor)
00431 
00432   {
00433     *pDescendant = cutVertex;
00434     return OK;
00435   }
00436 
00437   else
00438 
00439   {
00440     int subtreeRoot = theGraph->V[cutVertex].separatedDFSChildList;
00441     return _FindUnembeddedEdgeToSubtree (theGraph, *pAncestor, subtreeRoot,
00442                                          pDescendant);
00443   }
00444 }
00445 
00446 
00447 /****************************************************************************
00448  _FindUnembeddedEdgeToCurVertex()
00449 
00450  Given the current vertex I, we search for an edge connecting I to either
00451  a given pertinent vertex W or one of its DFS descendants in the subtree
00452  indicated by the the last pertinent child biconnected component.
00453  ****************************************************************************/
00454 int _FindUnembeddedEdgeToCurVertex (graphP theGraph,
00455                                     int cutVertex,
00456                                     int *pDescendant)
00457 {
00458   int RetVal = OK,
00459     I = theGraph->IC.v;
00460   if (theGraph->V[cutVertex].adjacentTo != NIL)
00461     *pDescendant = cutVertex;
00462 
00463   else
00464 
00465   {
00466     int subtreeRoot = theGraph->V[cutVertex].pertinentBicompList;
00467     RetVal =
00468       _FindUnembeddedEdgeToSubtree (theGraph, I, subtreeRoot, pDescendant);
00469   }
00470   return RetVal;
00471 }
00472 
00473 
00474 /****************************************************************************
00475  _FindUnembeddedEdgeToSubtree()
00476 
00477  Given the root vertex of a DFS subtree and an ancestor of that subtree,
00478  find a vertex in the subtree that is adjacent to the ancestor by a
00479  cycle edge.
00480  ****************************************************************************/
00481 int _FindUnembeddedEdgeToSubtree (graphP theGraph,
00482                                   int ancestor,
00483                                   int SubtreeRoot,
00484                                   int *pDescendant)
00485 {
00486   int J,
00487     Z,
00488     ZNew;
00489   *pDescendant = NIL;
00490 
00491 /* If SubtreeRoot is a root copy, then we change to the DFS child in the
00492         DFS tree root edge of the bicomp rooted by SubtreeRoot. */
00493   if (SubtreeRoot >= theGraph->N)
00494     SubtreeRoot -= theGraph->N;
00495 
00496 /* Find the least descendant of the cut vertex incident to the ancestor. */
00497   J = theGraph->V[ancestor].fwdArcList;
00498   while (J != NIL)
00499 
00500   {
00501     if (theGraph->G[J].v >= SubtreeRoot)
00502 
00503     {
00504       if (*pDescendant == NIL || *pDescendant > theGraph->G[J].v)
00505         *pDescendant = theGraph->G[J].v;
00506     }
00507     J = theGraph->G[J].link[0];
00508     if (J == theGraph->V[ancestor].fwdArcList)
00509       J = NIL;
00510   }
00511   if (*pDescendant == NIL)
00512     return NOTOK;
00513 
00514 /* Make sure the identified descendant actually descends from the cut vertex */
00515   Z = *pDescendant;
00516   while (Z != SubtreeRoot)
00517 
00518   {
00519     ZNew = theGraph->V[Z].DFSParent;
00520     if (ZNew == NIL || ZNew == Z)
00521       return NOTOK;
00522     Z = ZNew;
00523   }
00524 
00525 /* Return successfully */
00526   return OK;
00527 }
00528 
00529 
00530 /****************************************************************************
00531  _MarkPathAlongBicompExtFace()
00532 
00533  Sets the visited flags of vertices and edges on the external face of a
00534  bicomp from startVert to endVert, inclusive, by following the link[0] out of
00535  each visited vertex.
00536  ****************************************************************************/
00537 int _MarkPathAlongBicompExtFace (graphP theGraph,
00538                                  int startVert,
00539                                  int endVert)
00540 {
00541   int Z,
00542     ZPrevLink,
00543     ZPrevArc;
00544 
00545 /* Mark the start vertex (and if it is a root copy, mark the parent copy too. */
00546   theGraph->G[startVert].visited = 1;
00547 
00548 /* For each vertex visited after the start vertex, mark the vertex and the
00549         edge used to get there.  Stop after marking the ending vertex. */
00550   Z = startVert;
00551 
00552   do
00553 
00554   {
00555     ZPrevLink = 1;
00556     Z = _GetNextVertexOnExternalFace (theGraph, Z, &ZPrevLink);
00557     ZPrevArc = theGraph->G[Z].link[ZPrevLink];
00558     theGraph->G[ZPrevArc].visited = 1;
00559     theGraph->G[gp_GetTwinArc (theGraph, ZPrevArc)].visited = 1;
00560     theGraph->G[Z].visited = 1;
00561   } while (Z != endVert);
00562   return OK;
00563 }
00564 
00565 
00566 /****************************************************************************
00567  _MarkDFSPath()
00568 
00569  Sets visited flags of vertices and edges from descendant to ancestor,
00570  including root copy vertices, and including the step of hopping from
00571  a root copy to its parent copy.
00572 
00573  The DFSParent of a vertex indicates the next vertex to visit, so we
00574  search the adjacency list looking for the edge leading either to the
00575  DFSParent or to a root copy of the DFSParent.  We start by marking the
00576  descendant, then traverse up the DFS tree, stopping after we mark
00577  the ancestor.
00578  ****************************************************************************/
00579 int _MarkDFSPath (graphP theGraph,
00580                   int ancestor,
00581                   int descendant)
00582 {
00583   int J,
00584     parent,
00585     Z,
00586     N;
00587   N = theGraph->N;
00588 
00589   /* If we are marking from a root vertex upward, then go up to the parent
00590    * copy before starting the loop */
00591   if (descendant >= N)
00592     descendant = theGraph->V[descendant - N].DFSParent;
00593 
00594   /* Mark the lowest vertex */
00595   theGraph->G[descendant].visited = 1;
00596 
00597   /* Mark all ancestors of the lowest vertex, and the edges used to reach
00598    * them, up to the given ancestor vertex. */
00599   while (descendant != ancestor)
00600 
00601   {
00602 
00603     /* Get the parent vertex */
00604     parent = theGraph->V[descendant].DFSParent;
00605 
00606     /* If the descendant was a DFS tree root, then obviously
00607      * we aren't going to find the ancestor, so something is wrong. */
00608     if (parent == NIL || parent == descendant)
00609       return NOTOK;
00610 
00611     /* Find the edge from descendant that leads either to
00612      * parent or to a root copy of the parent. 
00613      * When the edge is found, mark it and break the loop */
00614     J = theGraph->G[descendant].link[0];
00615     while (J >= 2 * theGraph->N)
00616 
00617     {
00618       Z = theGraph->G[J].v;
00619 
00620       /*
00621        * if (Z < N && Z == parent ||
00622        * Z >= N && theGraph->V[Z-N].DFSParent == parent)
00623        */
00624       if ((Z < N && Z == parent) ||
00625           (Z >= N && theGraph->V[Z - N].DFSParent == parent))
00626 
00627       {
00628         theGraph->G[J].visited = 1;
00629         theGraph->G[gp_GetTwinArc (theGraph, J)].visited = 1;
00630         break;
00631       }
00632       J = theGraph->G[J].link[0];
00633     }
00634 
00635     /* Mark the parent copy of the DFS parent */
00636     theGraph->G[parent].visited = 1;
00637 
00638     /* Hop to the parent */
00639     descendant = parent;
00640   }
00641   return OK;
00642 }
00643 
00644 
00645 /****************************************************************************
00646  _MarkDFSPathsToDescendants()
00647  ****************************************************************************/
00648 int _MarkDFSPathsToDescendants (graphP theGraph)
00649 {
00650   isolatorContextP IC = &theGraph->IC;
00651   if (_MarkDFSPath (theGraph, IC->x, IC->dx) != OK
00652       || _MarkDFSPath (theGraph, IC->y, IC->dy) != OK)
00653     return NOTOK;
00654   if (IC->dw != NIL)
00655     if (_MarkDFSPath (theGraph, IC->w, IC->dw) != OK)
00656       return NOTOK;
00657   if (IC->dz != NIL)
00658     if (_MarkDFSPath (theGraph, IC->w, IC->dz) != OK)
00659       return NOTOK;
00660   return OK;
00661 }
00662 
00663 
00664 /****************************************************************************
00665  _AddAndMarkUnembeddedEdges()
00666  ****************************************************************************/
00667 int _AddAndMarkUnembeddedEdges (graphP theGraph)
00668 {
00669   isolatorContextP IC = &theGraph->IC;
00670   if (_AddAndMarkEdge (theGraph, IC->ux, IC->dx) != OK
00671       || _AddAndMarkEdge (theGraph, IC->uy, IC->dy) != OK)
00672     return NOTOK;
00673   if (IC->dw != NIL)
00674     if (_AddAndMarkEdge (theGraph, IC->v, IC->dw) != OK)
00675       return NOTOK;
00676   if (IC->dz != NIL)
00677     if (_AddAndMarkEdge (theGraph, IC->uz, IC->dz) != OK)
00678       return NOTOK;
00679   return OK;
00680 }
00681 
00682 
00683 /****************************************************************************
00684  _AddAndMarkEdge()
00685 
00686  Adds edge records for the edge (ancestor, descendant) and marks the edge
00687  records and vertex structures that represent the edge.
00688  ****************************************************************************/
00689 int _AddAndMarkEdge (graphP theGraph,
00690                      int ancestor,
00691                      int descendant)
00692 {
00693   _AddBackEdge (theGraph, ancestor, descendant);
00694 
00695   /* Mark the edge so it is not deleted */
00696   theGraph->G[ancestor].visited = 1;
00697   theGraph->G[theGraph->G[ancestor].link[0]].visited = 1;
00698   theGraph->G[theGraph->G[descendant].link[0]].visited = 1;
00699   theGraph->G[descendant].visited = 1;
00700   return OK;
00701 }
00702 
00703 
00704 /****************************************************************************
00705  _AddBackEdge()
00706  
00707  This function transfers the edge records for the edge between the ancestor 
00708  and descendant from the forward edge list of the ancestor to the adjacency
00709  lists of the ancestor and descendant.   
00710  ****************************************************************************/
00711 void _AddBackEdge (graphP theGraph,
00712                    int ancestor,
00713                    int descendant)
00714 {
00715   int fwdArc,
00716     backArc;
00717 
00718   /* We get the two edge records of the back edge to embed. */
00719   fwdArc = theGraph->V[ancestor].fwdArcList;
00720   while (fwdArc != NIL)
00721 
00722   {
00723     if (theGraph->G[fwdArc].v == descendant)
00724       break;
00725     fwdArc = theGraph->G[fwdArc].link[0];
00726     if (fwdArc == theGraph->V[ancestor].fwdArcList)
00727       fwdArc = NIL;
00728   }
00729   if (fwdArc == NIL)
00730     return;
00731   backArc = gp_GetTwinArc (theGraph, fwdArc);
00732 
00733   /* The forward arc is removed from the fwdArcList of the ancestor. */
00734   if (theGraph->V[ancestor].fwdArcList == fwdArc)
00735 
00736   {
00737     if (theGraph->G[fwdArc].link[0] == fwdArc)
00738       theGraph->V[ancestor].fwdArcList = NIL;
00739 
00740     else
00741       theGraph->V[ancestor].fwdArcList = theGraph->G[fwdArc].link[0];
00742   }
00743   theGraph->G[theGraph->G[fwdArc].link[0]].link[1] =
00744     theGraph->G[fwdArc].link[1];
00745   theGraph->G[theGraph->G[fwdArc].link[1]].link[0] =
00746     theGraph->G[fwdArc].link[0];
00747 
00748   /* The forward arc is added to the adjacency list of the ancestor. */
00749   theGraph->G[fwdArc].link[1] = ancestor;
00750   theGraph->G[fwdArc].link[0] = theGraph->G[ancestor].link[0];
00751   theGraph->G[theGraph->G[ancestor].link[0]].link[1] = fwdArc;
00752   theGraph->G[ancestor].link[0] = fwdArc;
00753 
00754   /* The back arc is added to the adjacency list of the descendant. */
00755   theGraph->G[backArc].v = ancestor;
00756   theGraph->G[backArc].link[1] = descendant;
00757   theGraph->G[backArc].link[0] = theGraph->G[descendant].link[0];
00758   theGraph->G[theGraph->G[descendant].link[0]].link[1] = backArc;
00759   theGraph->G[descendant].link[0] = backArc;
00760 }
00761 
00762 
00763 /****************************************************************************
00764  _DeleteUnmarkedVerticesAndEdges()
00765 
00766  For each vertex, traverse its adjacency list and delete all unvisited edges.
00767  ****************************************************************************/
00768 int _DeleteUnmarkedVerticesAndEdges (graphP theGraph)
00769 {
00770   int I,
00771     J,
00772     fwdArc,
00773     descendant;
00774 
00775   /* All of the forward and back arcs of all of the edge records
00776    * were removed from the adjacency lists in the planarity algorithm
00777    * preprocessing.  We now put them back into the adjacency lists
00778    * (and we do not mark them), so they can be properly deleted below. */
00779   for (I = 0; I < theGraph->N; I++)
00780 
00781   {
00782     while (theGraph->V[I].fwdArcList != NIL)
00783 
00784     {
00785       fwdArc = theGraph->V[I].fwdArcList;
00786       descendant = theGraph->G[fwdArc].v;
00787       _AddBackEdge (theGraph, I, descendant);
00788     }
00789   }
00790 
00791   /* Now we delete all unmarked edges.  We don't delete vertices
00792    * from the embedding, but the ones we should delete will become
00793    * degree zero. */
00794   for (I = 0; I < theGraph->N; I++)
00795 
00796   {
00797     J = theGraph->G[I].link[0];
00798     while (J >= 2 * theGraph->N)
00799 
00800     {
00801       if (theGraph->G[J].visited)
00802         J = theGraph->G[J].link[0];
00803 
00804       else
00805         J = gp_DeleteEdge (theGraph, J, 0);
00806     }
00807   }
00808   return OK;
00809 }

Generated on Thu Oct 20 14:58:41 2005 for DominoParitySeparator by  doxygen 1.4.5