graphStructure.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) 1997-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 GRAPHSTRUCTURE_C
00008 
00009 #include <stdlib.h>
00010 
00011 #include "graph_boyer.h"
00012 
00013 /********************************************************************
00014  Private functions, except exported within library
00015  ********************************************************************/
00016 void _InitGraphNode (graphP theGraph,
00017                      int I);
00018 void _ClearIsolatorContext (graphP theGraph);
00019 void _FillVisitedFlags (graphP theGraph,
00020                         int FillValue);
00021 void _FillVisitedFlagsInBicomp (graphP theGraph,
00022                                 int BicompRoot,
00023                                 int FillValue);
00024 void _FillVisitedFlagsInOtherBicomps (graphP theGraph,
00025                                       int BicompRoot,
00026                                       int FillValue);
00027 void _SetVertexTypeInBicomp (graphP theGraph,
00028                              int BicompRoot,
00029                              int theType);
00030 
00031 /********************************************************************
00032  Private functions.
00033  ********************************************************************/
00034 void _ClearGraph (graphP theGraph);
00035 void _InitVertexRec (graphP theGraph,
00036                      int I);
00037 int _GetRandomNumber (int NMin,
00038                       int NMax);
00039 void _AddArc (graphP theGraph,
00040               int u,
00041               int v,
00042               int arcPos,
00043               int link);
00044 void _HideArc (graphP theGraph,
00045                int arcPos);
00046 
00047 /********************************************************************
00048  gp_New()
00049  Constructor for graph object.
00050  Can create two graphs if restricted to no dynamic memory.
00051  ********************************************************************/
00052 graphP gp_New ()
00053 {
00054   graphP theGraph = (graphP) malloc (sizeof (BM_graph));
00055   if (theGraph != NULL)
00056 
00057   {
00058     theGraph->G = NULL;
00059     theGraph->V = NULL;
00060     theGraph->BicompLists = NULL;
00061     theGraph->DFSChildLists = NULL;
00062     theGraph->theStack = NULL;
00063     theGraph->buckets = NULL;
00064     theGraph->bin = NULL;
00065     theGraph->extFace = NULL;
00066     _ClearGraph (theGraph);
00067   }
00068   return theGraph;
00069 }
00070 
00071 
00072 /********************************************************************
00073  gp_InitGraph()
00074  Allocates memory for graph and vertex records now that N is known.
00075  For G, we need N vertex nodes, N more vertex nodes for root copies,
00076         (2 * EDGE_LIMIT * N) edge records.
00077  For V, we need N vertex records.
00078  The BicompLists and DFSChildLists are of size N and start out empty.
00079  The stack, initially empty, is made big enough for a pair of integers per
00080         edge record, or 2 * 2 * EDGE_LIMIT * N.
00081  buckets and bin are both O(n) in size.  They are used by
00082         CreateSortedSeparatedDFSChildLists()
00083  Returns OK on success, NOTOK on all failures.
00084  ********************************************************************/
00085 int gp_InitGraph (graphP theGraph,
00086                   int N)
00087 {
00088   int I;
00089   _ClearGraph (theGraph);
00090 
00091 /* Allocate memory as described above */
00092   if ((theGraph->G =
00093        (graphNodeP) malloc ((2 + 2 * EDGE_LIMIT) * N *
00094                             sizeof (graphNode))) == NULL || (theGraph->V =
00095                                                              (vertexRecP)
00096                                                              malloc (N *
00097                                                                      sizeof
00098                                                                      (vertexRec)))
00099       == NULL || (theGraph->BicompLists =
00100                   LCNew (N)) == NULL || (theGraph->DFSChildLists =
00101                                          LCNew (N)) ==
00102       NULL || (theGraph->theStack =
00103                sp_New (2 * 2 * EDGE_LIMIT * N)) ==
00104       NULL || (theGraph->buckets =
00105                (int *) malloc (N * sizeof (int))) ==
00106       NULL || (theGraph->bin = LCNew (N)) == NULL || (theGraph->extFace =
00107                                                       (extFaceLinkRecP)
00108                                                       malloc (2 * N *
00109                                                               sizeof
00110                                                               (extFaceLinkRec)))
00111       == NULL || 0)
00112 
00113   {
00114     _ClearGraph (theGraph);
00115     return NOTOK;
00116   }
00117 
00118 /* Initialize memory */
00119   theGraph->N = N;
00120   for (I = 0; I < (2 + 2 * EDGE_LIMIT) * N; I++)
00121     _InitGraphNode (theGraph, I);
00122   for (I = 0; I < N; I++)
00123     _InitVertexRec (theGraph, I);
00124   for (I = 0; I < 2 * N; I++)
00125 
00126   {
00127     theGraph->extFace[I].link[0] = theGraph->extFace[I].link[1] = NIL;
00128     theGraph->extFace[I].inversionFlag = 0;
00129   }
00130   return OK;
00131 }
00132 
00133 
00134 /********************************************************************
00135  _InitGraphNode()
00136  Sets the fields in a single graph node structure to initial values
00137  ********************************************************************/
00138 void _InitGraphNode (graphP theGraph,
00139                      int I)
00140 {
00141   theGraph->G[I].id = NIL;
00142   theGraph->G[I].v = theGraph->G[I].link[0] = theGraph->G[I].link[1] = NIL;
00143   theGraph->G[I].visited = 0;
00144   theGraph->G[I].type = TYPE_UNKNOWN;
00145   theGraph->G[I].sign = 1;
00146 }
00147 
00148 
00149 /********************************************************************
00150  _InitVertexRec()
00151  Sets the fields in a single vertex record to initial values
00152  ********************************************************************/
00153 void _InitVertexRec (graphP theGraph,
00154                      int I)
00155 {
00156   theGraph->V[I].leastAncestor = theGraph->V[I].Lowpoint = I;
00157   theGraph->V[I].DFSParent = NIL;
00158   theGraph->V[I].adjacentTo = NIL;
00159   theGraph->V[I].pertinentBicompList = NIL;
00160   theGraph->V[I].separatedDFSChildList = NIL;
00161   theGraph->V[I].fwdArcList = NIL;
00162 }
00163 
00164 
00165 /********************************************************************
00166  _ClearIsolatorContext()
00167  ********************************************************************/
00168 void _ClearIsolatorContext (graphP theGraph)
00169 {
00170   isolatorContextP IC = &theGraph->IC;
00171   IC->minorType = 0;
00172   IC->v = IC->r = IC->x = IC->y = IC->w = IC->px = IC->py = IC->z = IC->ux =
00173     IC->dx = IC->uy = IC->dy = IC->dw = IC->uz = IC->dz = NIL;
00174 }
00175 
00176 
00177 /********************************************************************
00178  _FillVisitedFlags()
00179  ********************************************************************/
00180 void _FillVisitedFlags (graphP theGraph,
00181                         int FillValue)
00182 {
00183   int i,
00184     limit;
00185   for (i = 0, limit = 2 * (theGraph->N + theGraph->M); i < limit; i++)
00186     theGraph->G[i].visited = FillValue;
00187 }
00188 
00189 
00190 /********************************************************************
00191  _FillVisitedFlagsInBicomp()
00192  ********************************************************************/
00193 void _FillVisitedFlagsInBicomp (graphP theGraph,
00194                                 int BicompRoot,
00195                                 int FillValue)
00196 {
00197   int V,
00198     J;
00199   sp_ClearStack (theGraph->theStack);
00200   sp_Push (theGraph->theStack, BicompRoot);
00201   while (sp_NonEmpty (theGraph->theStack))
00202 
00203   {
00204     sp_Pop (theGraph->theStack, V);
00205     theGraph->G[V].visited = FillValue;
00206     J = theGraph->G[V].link[0];
00207     while (J >= 2 * theGraph->N)
00208 
00209     {
00210       theGraph->G[J].visited = FillValue;
00211       if (theGraph->G[J].type == EDGE_DFSCHILD)
00212         sp_Push (theGraph->theStack, theGraph->G[J].v);
00213       J = theGraph->G[J].link[0];
00214     }
00215   }
00216 }
00217 
00218 
00219 /********************************************************************
00220  _FillVisitedFlagsInOtherBicomps()
00221  Typically, we want to clear or set all visited flags in the graph
00222  (see _FillVisitedFlags).  However, in some algorithms this would be
00223  too costly, so it is necessary to clear or set the visited flags only
00224  in one bicomp (see _FillVisitedFlagsInBicomp), then do some processing
00225  that sets some of the flags then performs some tests.  If the tests
00226  are positive, then we can clear or set all the visited flags in the
00227  other bicomps (the processing may have set the visited flags in the
00228  one bicomp in a particular way that we want to retain, so we skip
00229  the given bicomp).
00230  ********************************************************************/
00231 void _FillVisitedFlagsInOtherBicomps (graphP theGraph,
00232                                       int BicompRoot,
00233                                       int FillValue)
00234 {
00235   int R,
00236     N;
00237   N = theGraph->N;
00238   for (R = N; R < 2 * N; R++)
00239     if (theGraph->G[R].v != NIL && R != BicompRoot)
00240       _FillVisitedFlagsInBicomp (theGraph, R, FillValue);
00241 }
00242 
00243 
00244 /********************************************************************
00245  _SetVertexTypeInBicomp()
00246  ********************************************************************/
00247 void _SetVertexTypeInBicomp (graphP theGraph,
00248                              int BicompRoot,
00249                              int theType)
00250 {
00251   int V,
00252     J;
00253   sp_ClearStack (theGraph->theStack);
00254   sp_Push (theGraph->theStack, BicompRoot);
00255   while (sp_NonEmpty (theGraph->theStack))
00256 
00257   {
00258     sp_Pop (theGraph->theStack, V);
00259     theGraph->G[V].type = theType;
00260     J = theGraph->G[V].link[0];
00261     while (J >= 2 * theGraph->N)
00262 
00263     {
00264       if (theGraph->G[J].type == EDGE_DFSCHILD)
00265         sp_Push (theGraph->theStack, theGraph->G[J].v);
00266       J = theGraph->G[J].link[0];
00267     }
00268   }
00269 }
00270 
00271 
00272 /********************************************************************
00273  _ClearGraph()
00274  Clears all memory used by the graph, restoring it to the state it
00275  was in immediately after gp_New() created it.
00276  ********************************************************************/
00277 void _ClearGraph (graphP theGraph)
00278 {
00279   if (theGraph->G != NULL)
00280 
00281   {
00282     free (theGraph->G);
00283     theGraph->G = NULL;
00284   }
00285   if (theGraph->V != NULL)
00286 
00287   {
00288     free (theGraph->V);
00289     theGraph->V = NULL;
00290   }
00291   theGraph->N = theGraph->M = 0;
00292   theGraph->internalFlags = theGraph->embedFlags = 0;
00293   _ClearIsolatorContext (theGraph);
00294   LCFree (&theGraph->BicompLists);
00295   LCFree (&theGraph->DFSChildLists);
00296   sp_Free (&theGraph->theStack);
00297   if (theGraph->buckets != NULL)
00298 
00299   {
00300     free (theGraph->buckets);
00301     theGraph->buckets = NULL;
00302   }
00303   LCFree (&theGraph->bin);
00304   if (theGraph->extFace != NULL)
00305 
00306   {
00307     free (theGraph->extFace);
00308     theGraph->extFace = NULL;
00309   }
00310 }
00311 
00312 
00313 /********************************************************************
00314  gp_ReinitializeGraph()
00315  Reinitializes a graph, restoring it to the state it was in immediately 
00316  gp_InitGraph() processed it.
00317  ********************************************************************/
00318 void gp_ReinitializeGraph (graphP theGraph)
00319 {
00320   int N = theGraph->N,
00321     I;
00322   theGraph->M = 0;
00323   theGraph->internalFlags = theGraph->embedFlags = 0;
00324   for (I = 0; I < (2 + 2 * EDGE_LIMIT) * N; I++)
00325     _InitGraphNode (theGraph, I);
00326   for (I = 0; I < N; I++)
00327     _InitVertexRec (theGraph, I);
00328   for (I = 0; I < 2 * N; I++)
00329 
00330   {
00331     theGraph->extFace[I].link[0] = theGraph->extFace[I].link[1] = NIL;
00332     theGraph->extFace[I].inversionFlag = 0;
00333   }
00334   _ClearIsolatorContext (theGraph);
00335   LCReset (theGraph->BicompLists);
00336   LCReset (theGraph->DFSChildLists);
00337   sp_ClearStack (theGraph->theStack);
00338   LCReset (theGraph->bin);
00339 }
00340 
00341 
00342 /********************************************************************
00343  gp_Free()
00344  Frees G and V, then the graph record.  Then sets your pointer to NULL
00345  (so you must pass the address of your pointer).
00346  ********************************************************************/
00347 void gp_Free (graphP * pGraph)
00348 {
00349   if (pGraph == NULL)
00350     return;
00351   if (*pGraph == NULL)
00352     return;
00353   _ClearGraph (*pGraph);
00354   free (*pGraph);
00355   *pGraph = NULL;
00356 }
00357 
00358 
00359 /********************************************************************
00360  gp_CopyGraph()
00361  Copies the content of the srcGraph into the dstGraph.  The dstGraph
00362  must have been previously initialized with the same number of 
00363  vertices as the srcGraph (e.g. gp_InitGraph(dstGraph, srcGraph->N).
00364 
00365  Returns OK for success, NOTOK for failure.
00366  ********************************************************************/
00367 int gp_CopyGraph (graphP dstGraph,
00368                   graphP srcGraph)
00369 {
00370   int I;
00371 
00372   /* Parameter checks */
00373   if (dstGraph == NULL || srcGraph == NULL)
00374     return NOTOK;
00375   if (dstGraph->N != srcGraph->N)
00376     return NOTOK;
00377   for (I = 0; I < (2 + 2 * EDGE_LIMIT) * srcGraph->N; I++)
00378     dstGraph->G[I] = srcGraph->G[I];
00379   for (I = 0; I < srcGraph->N; I++)
00380     dstGraph->V[I] = srcGraph->V[I];
00381   for (I = 0; I < 2 * srcGraph->N; I++)
00382 
00383   {
00384     dstGraph->extFace[I].link[0] = srcGraph->extFace[I].link[0];
00385     dstGraph->extFace[I].link[1] = srcGraph->extFace[I].link[1];
00386     dstGraph->extFace[I].inversionFlag = srcGraph->extFace[I].inversionFlag;
00387   }
00388   dstGraph->N = srcGraph->N;
00389   dstGraph->M = srcGraph->M;
00390   dstGraph->internalFlags = srcGraph->internalFlags;
00391   dstGraph->embedFlags = srcGraph->embedFlags;
00392   dstGraph->IC = srcGraph->IC;
00393   LCCopy (dstGraph->BicompLists, srcGraph->BicompLists);
00394   LCCopy (dstGraph->DFSChildLists, srcGraph->DFSChildLists);
00395   sp_Copy (dstGraph->theStack, srcGraph->theStack);
00396   return OK;
00397 }
00398 
00399 
00400 /********************************************************************
00401  gp_DupGraph()
00402  ********************************************************************/
00403 graphP gp_DupGraph (graphP theGraph)
00404 {
00405   graphP result;
00406   if ((result = gp_New ()) == NULL)
00407     return NULL;
00408   if (gp_InitGraph (result, theGraph->N) != OK
00409       || gp_CopyGraph (result, theGraph) != OK)
00410 
00411   {
00412     gp_Free (&result);
00413     return NULL;
00414   }
00415   return result;
00416 }
00417 
00418 
00419 /********************************************************************
00420  gp_CreateRandomGraph()
00421 
00422  Creates a randomly generated graph.  First a tree is created by
00423  connecting each vertex to some successor.  Then a random number of
00424  additional random edges are added.  If an edge already exists, then
00425  we retry until a non-existent edge is picked.
00426 
00427  This function assumes the caller has already called srand().
00428  ********************************************************************/
00429 int gp_CreateRandomGraph (graphP theGraph)
00430 {
00431   int N,
00432     I,
00433     M,
00434     u,
00435     v;
00436   N = theGraph->N;
00437 
00438 /* Generate a random tree; note that this method virtually guarantees
00439         that the graph will be renumbered, but it is linear time.
00440         Also, we are not generating the DFS tree but rather a tree
00441         that simply ensures the resulting random graph is connected. */
00442   for (I = 1; I < N; I++)
00443     if (gp_AddEdge (theGraph, _GetRandomNumber (0, I - 1), 0, I, 0) != OK)
00444       return NOTOK;
00445 
00446 /* Generate a random number of additional edges
00447         (actually, leave open a small chance that no
00448         additional edges will be added). */
00449   M = _GetRandomNumber (7 * N / 8, EDGE_LIMIT * N);
00450   if (M > N * (N - 1) / 2)
00451     M = N * (N - 1) / 2;
00452   for (I = N - 1; I < M; I++)
00453 
00454   {
00455     u = _GetRandomNumber (0, N - 2);
00456     v = _GetRandomNumber (u + 1, N - 1);
00457     if (gp_IsNeighbor (theGraph, u, v))
00458       I--;
00459 
00460     else
00461 
00462     {
00463       if (gp_AddEdge (theGraph, u, 0, v, 0) != OK)
00464         return NOTOK;
00465     }
00466   }
00467   return OK;
00468 }
00469 
00470 
00471 /********************************************************************
00472  _GetRandomNumber()
00473  This function generates a random number between NMin and NMax
00474  inclusive.  It assumes that the caller has called srand().
00475  It calls rand(), but before truncating to the proper range,
00476  it adds the high bits of the rand() result into the low bits.
00477  The result of this is that the randomness appearing in the
00478  truncated bits also has an affect on the non-truncated bits.
00479  I used the same technique to improve the spread of hashing functions
00480  in my Jan.98 Dr. Dobb's Journal article  "Resizable Data Structures".
00481  ********************************************************************/
00482 int _GetRandomNumber (int NMin,
00483                       int NMax)
00484 {
00485   int N = rand ();
00486   if (NMax < NMin)
00487     return NMin;
00488   N += ((N & 0xFFFF0000) >> 16);
00489   N += ((N & 0x0000FF00) >> 8);
00490 
00491   /* mg & de : change */
00492   if (N < 0)
00493     N = -N;
00494   N %= (NMax - NMin + 1);
00495   return N + NMin;
00496 }
00497 
00498 
00499 /********************************************************************
00500  _getUnprocessedChild()
00501  Support routine for gp_Create RandomGraphEx(), this function
00502  obtains a child of the given vertex in the randomly generated
00503  tree that has not yet been processed.  NIL is returned if the 
00504  given vertex has no unprocessed children
00505  
00506  ********************************************************************/
00507 int _getUnprocessedChild (graphP theGraph,
00508                           int parent)
00509 {
00510   int J = theGraph->G[parent].link[0];
00511   int JTwin = gp_GetTwinArc (theGraph, J);
00512   int child = theGraph->G[J].v;
00513 
00514   /* The tree edges were added to the link[0] side of each vertex, 
00515    * and we move processed tree edge records to the link[1] side,
00516    * so if the immediate link[0] edge record is not a tree edge
00517    * then we return NIL because the vertex has no remaining
00518    * unprocessed children */
00519   if (theGraph->G[J].type == TYPE_UNKNOWN)
00520     return NIL;
00521 
00522   /* if the child has already been processed, then all children
00523    * have been pushed to the link[1] side and we have just encountered
00524    * the first child we processed, so there are no remaining
00525    * unprocessed children */
00526   if (theGraph->G[J].visited)
00527     return NIL;
00528 
00529   /* We have found an edge leading to an unprocessed child, so
00530    * we mark it as processed so that it doesn't get returned
00531    * again in future iterations. */
00532   theGraph->G[J].visited = 1;
00533   theGraph->G[JTwin].visited = 1;
00534 
00535   /* Now we move the edge record in the parent vertex to the
00536    * link[1] side of that vertex. */
00537   if (theGraph->G[J].link[0] != theGraph->G[J].link[1])
00538 
00539   {
00540     theGraph->G[parent].link[0] = theGraph->G[J].link[0];
00541     theGraph->G[theGraph->G[J].link[0]].link[1] = parent;
00542     theGraph->G[J].link[0] = parent;
00543     theGraph->G[J].link[1] = theGraph->G[parent].link[1];
00544     theGraph->G[theGraph->G[parent].link[1]].link[0] = J;
00545     theGraph->G[parent].link[1] = J;
00546   }
00547 
00548   /* Now we move the edge record in the child vertex to the
00549    * link[1] of the child. */
00550   if (theGraph->G[J].link[0] != theGraph->G[J].link[1])
00551 
00552   {
00553     theGraph->G[theGraph->G[JTwin].link[0]].link[1] =
00554       theGraph->G[JTwin].link[1];
00555     theGraph->G[theGraph->G[JTwin].link[1]].link[0] =
00556       theGraph->G[JTwin].link[0];
00557     theGraph->G[JTwin].link[0] = child;
00558     theGraph->G[JTwin].link[1] = theGraph->G[child].link[1];
00559     theGraph->G[theGraph->G[child].link[1]].link[0] = JTwin;
00560     theGraph->G[child].link[1] = JTwin;
00561   }
00562 
00563   /* Now we set the child's parent and return the child. */
00564   theGraph->V[child].DFSParent = parent;
00565   return child;
00566 }
00567 
00568 
00569 /********************************************************************
00570  _hasUnprocessedChild()
00571  Support routine for gp_Create RandomGraphEx(), this function
00572  obtains a child of the given vertex in the randomly generated
00573  tree that has not yet been processed.  False (0) is returned
00574  unless the given vertex has an unprocessed child.
00575  ********************************************************************/
00576 int _hasUnprocessedChild (graphP theGraph,
00577                           int parent)
00578 {
00579   int J = theGraph->G[parent].link[0];
00580   if (theGraph->G[J].type == TYPE_UNKNOWN)
00581     return 0;
00582   if (theGraph->G[J].visited)
00583     return 0;
00584   return 1;
00585 }
00586 
00587 
00588 /********************************************************************
00589  gp_CreateRandomGraphEx()
00590  Given a graph structure with a pre-specified number of vertices N,
00591  this function creates a graph with the specified number of edges.
00592 
00593  If numEdges <= 3N-6, then the graph generated is planar.  If 
00594  numEdges is larger, then a maximal planar graph is generated, then
00595  (numEdges - 3N + 6) additional random edges are added.
00596 
00597  This function assumes the caller has already called srand().
00598  ********************************************************************/
00599 int gp_CreateRandomGraphEx (graphP theGraph,
00600                             int numEdges)
00601 {
00602 
00603 #define EDGE_TREE_RANDOMGEN (TYPE_UNKNOWN+1)
00604   int N,
00605     I,
00606     arc,
00607     M,
00608     root,
00609     v,
00610     c,
00611     p,
00612     last,
00613     u,
00614     J,
00615     e;
00616   N = theGraph->N;
00617   if (numEdges > EDGE_LIMIT * N)
00618     numEdges = EDGE_LIMIT * N;
00619 
00620 /* Generate a random tree. */
00621   for (I = 1; I < N; I++)
00622 
00623   {
00624     v = _GetRandomNumber (0, I - 1);
00625     if (gp_AddEdge (theGraph, v, 0, I, 0) != OK)
00626       return NOTOK;
00627 
00628     else
00629 
00630     {
00631       arc = 2 * N + 2 * theGraph->M - 2;
00632       theGraph->G[arc].type = EDGE_TREE_RANDOMGEN;
00633       theGraph->G[gp_GetTwinArc (theGraph, arc)].type = EDGE_TREE_RANDOMGEN;
00634       theGraph->G[arc].visited = 0;
00635       theGraph->G[gp_GetTwinArc (theGraph, arc)].visited = 0;
00636     }
00637   }
00638 
00639 /* Add edges up to the limit or until the graph is maximal planar. */
00640   M = numEdges <= 3 * N - 6 ? numEdges : 3 * N - 6;
00641   root = 0;
00642   v = last = _getUnprocessedChild (theGraph, root);
00643   while (v != root && theGraph->M < M)
00644 
00645   {
00646     c = _getUnprocessedChild (theGraph, v);
00647     if (c != NIL)
00648 
00649     {
00650       if (last != v)
00651 
00652       {
00653         if (gp_AddEdge (theGraph, last, 1, c, 1) != OK)
00654           return NOTOK;
00655       }
00656       if (gp_AddEdge (theGraph, root, 1, c, 1) != OK)
00657         return NOTOK;
00658       v = last = c;
00659     }
00660 
00661     else
00662 
00663     {
00664       p = theGraph->V[v].DFSParent;
00665       while (p != NIL && (c = _getUnprocessedChild (theGraph, p)) == NIL)
00666 
00667       {
00668         v = p;
00669         p = theGraph->V[v].DFSParent;
00670         if (p != NIL && p != root)
00671 
00672         {
00673           if (gp_AddEdge (theGraph, last, 1, p, 1) != OK)
00674             return NOTOK;
00675         }
00676       }
00677       if (p != NIL)
00678 
00679       {
00680         if (p == root)
00681 
00682         {
00683           if (gp_AddEdge (theGraph, v, 1, c, 1) != OK)
00684             return NOTOK;
00685           if (v != last)
00686 
00687           {
00688             if (gp_AddEdge (theGraph, last, 1, c, 1) != OK)
00689               return NOTOK;
00690           }
00691         }
00692 
00693         else
00694 
00695         {
00696           if (gp_AddEdge (theGraph, last, 1, c, 1) != OK)
00697             return NOTOK;
00698         }
00699         if (p != root)
00700 
00701         {
00702           if (gp_AddEdge (theGraph, root, 1, c, 1) != OK)
00703             return NOTOK;
00704           last = c;
00705         }
00706         v = c;
00707       }
00708     }
00709   }
00710 
00711 /* Add additional edges if the limit has not yet been reached. */
00712   while (theGraph->M < numEdges)
00713 
00714   {
00715     u = _GetRandomNumber (0, N - 1);
00716     v = _GetRandomNumber (0, N - 1);
00717     if (u != v && !gp_IsNeighbor (theGraph, u, v))
00718       if (gp_AddEdge (theGraph, u, 0, v, 0) != OK)
00719         return NOTOK;
00720   }
00721 
00722 /* Clear the edge types back to 'unknown' */
00723   for (e = 0; e < numEdges; e++)
00724 
00725   {
00726     J = 2 * N + 2 * e;
00727     theGraph->G[J].type = TYPE_UNKNOWN;
00728     theGraph->G[gp_GetTwinArc (theGraph, J)].type = TYPE_UNKNOWN;
00729     theGraph->G[J].visited = 0;
00730     theGraph->G[gp_GetTwinArc (theGraph, J)].visited = 0;
00731   }
00732 
00733 /* Put all DFSParent indicators back to NIL */
00734   for (I = 0; I < N; I++)
00735     theGraph->V[I].DFSParent = NIL;
00736   return OK;
00737 
00738 #undef EDGE_TREE_RANDOMGEN
00739 }
00740 
00741 
00742 /********************************************************************
00743  gp_IsNeighbor()
00744  Checks whether v is already in u's adjacency list.
00745  Returns 1 for yes, 0 for no.
00746  ********************************************************************/
00747 int gp_IsNeighbor (graphP theGraph,
00748                    int u,
00749                    int v)
00750 {
00751   int J;
00752   J = theGraph->G[u].link[0];
00753   while (J >= 2 * theGraph->N)
00754 
00755   {
00756     if (theGraph->G[J].v == v)
00757       return 1;
00758     J = theGraph->G[J].link[0];
00759   }
00760   return 0;
00761 }
00762 
00763 
00764 /********************************************************************
00765  gp_GetVertexDegree()
00766 
00767  Counts the number of edge records in the adjacency list of a given
00768  vertex V.  The while loop condition is 2N or higher because our
00769  data structure keeps records at locations 0 to N-1 for vertices
00770  AND N to 2N-1 for copies of vertices.  So edge records are stored
00771  at locations 2N and above.
00772  ********************************************************************/
00773 int gp_GetVertexDegree (graphP theGraph,
00774                         int v)
00775 {
00776   int J,
00777     degree;
00778   if (theGraph == NULL || v == NIL)
00779     return 0;
00780   degree = 0;
00781   J = theGraph->G[v].link[0];
00782   while (J >= 2 * theGraph->N)
00783 
00784   {
00785     degree++;
00786     J = theGraph->G[J].link[0];
00787   }
00788   return degree;
00789 }
00790 
00791 
00792 /********************************************************************
00793  _AddArc()
00794  This routine adds arc (u,v) to u's edge list, storing the record for
00795  v at position arcPos.  The record is either added to the link[0] or
00796  link[1] side of vertex u, depending on the link parameter.
00797  The links of a vertex record can be viewed as previous (link[0]) and
00798  next (link[1]) pointers.  Thus, an edge record is appended to u's
00799  list by hooking it to u.link[0], and it is prepended by hooking it
00800  to u.link[1].  The use of exclusive-or (i.e. 1^link) is simply to get
00801  the other link (if link is 0 then 1^link is 1, and vice versa).
00802  ********************************************************************/
00803 void _AddArc (graphP theGraph,
00804               int u,
00805               int v,
00806               int arcPos,
00807               int link)
00808 {
00809   theGraph->G[arcPos].v = v;
00810   if (theGraph->G[u].link[0] == NIL)
00811 
00812   {
00813     theGraph->G[u].link[0] = theGraph->G[u].link[1] = arcPos;
00814     theGraph->G[arcPos].link[0] = theGraph->G[arcPos].link[1] = u;
00815   }
00816 
00817   else
00818 
00819   {
00820     int u0 = theGraph->G[u].link[link];
00821     theGraph->G[arcPos].link[link] = u0;
00822     theGraph->G[arcPos].link[1 ^ link] = u;
00823     theGraph->G[u].link[link] = arcPos;
00824     theGraph->G[u0].link[1 ^ link] = arcPos;
00825   }
00826 }
00827 
00828 
00829 /********************************************************************
00830  gp_AddEdge()
00831  Adds the undirected edge (u,v) to the graph by placing edge records
00832  representing u into v's circular edge record list and v into u's
00833  circular edge record list.
00834 
00835  upos receives the location in G where the u record in v's list will be
00836         placed, and vpos is the location in G of the v record we placed in
00837  u's list.  These are used to initialize the short circuit links.
00838 
00839  ulink (0|1) indicates whether the edge record to v in u's list should
00840         become adjacent to u by its 0 or 1 link, i.e. u[ulink] == vpos.
00841  vlink (0|1) indicates whether the edge record to u in v's list should
00842         become adjacent to v by its 0 or 1 link, i.e. v[vlink] == upos.
00843 
00844  ********************************************************************/
00845 int gp_AddEdge (graphP theGraph,
00846                 int u,
00847                 int ulink,
00848                 int v,
00849                 int vlink)
00850 {
00851   int upos,
00852     vpos;
00853   if (theGraph == NULL || u < 0 || v < 0 || u >= 2 * theGraph->N
00854       || v >= 2 * theGraph->N)
00855     return NOTOK;
00856 
00857   /* We enforce the edge limit */
00858   if (theGraph->M >= EDGE_LIMIT * theGraph->N)
00859     return NONEMBEDDABLE;
00860   vpos = 2 * theGraph->N + 2 * theGraph->M;
00861   upos = gp_GetTwinArc (theGraph, vpos);
00862   _AddArc (theGraph, u, v, vpos, ulink);
00863   _AddArc (theGraph, v, u, upos, vlink);
00864   theGraph->M++;
00865   return OK;
00866 }
00867 
00868 
00869 /********************************************************************
00870  _HideArc()
00871  This routine removes an arc from an edge list, but does not delete
00872  it from the data structure.  Many algorithms must temporarily remove
00873  an edge, perform some calculation, and eventually put the edge back.
00874  This routine supports that operation.
00875 
00876  The neighboring adjacency list nodes are cross-linked, but the
00877  link[0] and link[1] fields of the arc are retained so it can
00878  reinsert itself when _RestoreArc() is called.
00879  ********************************************************************/
00880 void _HideArc (graphP theGraph,
00881                int arcPos)
00882 {
00883   int link0,
00884     link1;
00885   link0 = theGraph->G[arcPos].link[0];
00886   link1 = theGraph->G[arcPos].link[1];
00887   if (link0 == NIL || link1 == NIL)
00888     return;
00889   theGraph->G[link0].link[1] = link1;
00890   theGraph->G[link1].link[0] = link0;
00891 }
00892 
00893 
00894 /********************************************************************
00895  _RestoreArc()
00896  This routine reinserts an arc into the edge list from which it
00897  was previously removed by _HideArc().
00898 
00899  The assumed processing model is that arcs will be restored in reverse
00900  of the order in which they were hidden, i.e. it is assumed that the
00901  hidden arcs will be pushed on a stack and the arcs will be popped
00902  from the stack for restoration.
00903  ********************************************************************/
00904 void _RestoreArc (graphP theGraph,
00905                   int arcPos)
00906 {
00907   int link0,
00908     link1;
00909   link0 = theGraph->G[arcPos].link[0];
00910   link1 = theGraph->G[arcPos].link[1];
00911   if (link0 == NIL || link1 == NIL)
00912     return;
00913   theGraph->G[link0].link[1] = arcPos;
00914   theGraph->G[link1].link[0] = arcPos;
00915 }
00916 
00917 
00918 /********************************************************************
00919  gp_HideEdge()
00920  This routine removes an arc and its twin arc from its edge list,
00921  but does not delete them from the data structure.  Many algorithms must
00922  temporarily remove an edge, perform some calculation, and eventually
00923  put the edge back. This routine supports that operation.
00924 
00925  For each arc, the neighboring adjacency list nodes are cross-linked,
00926  but the link[0] and link[1] fields of the arc are retained so it can
00927  be reinserted by calling gp_RestoreEdge().
00928  ********************************************************************/
00929 void gp_HideEdge (graphP theGraph,
00930                   int arcPos)
00931 {
00932   _HideArc (theGraph, arcPos);
00933   _HideArc (theGraph, gp_GetTwinArc (theGraph, arcPos));
00934 }
00935 
00936 
00937 /********************************************************************
00938  gp_RestoreEdge()
00939  This routine reinserts an arc and its twin arc into the edge list
00940  from which it was previously removed by gp_HideEdge().
00941 
00942  The assumed processing model is that edges will be restored in
00943  reverse of the order in which they were hidden, i.e. it is assumed
00944  that the hidden edges will be pushed on a stack and the edges will
00945  be popped from the stack for restoration.
00946 
00947  Note: Since both arcs of an edge are restored, only one arc need
00948         be pushed on the stack for restoration.  This routine
00949         restores the two arcs in the opposite order from the order
00950         in which they are hidden by gp_HideEdge().
00951  ********************************************************************/
00952 void gp_RestoreEdge (graphP theGraph,
00953                      int arcPos)
00954 {
00955   _RestoreArc (theGraph, gp_GetTwinArc (theGraph, arcPos));
00956   _RestoreArc (theGraph, arcPos);
00957 }
00958 
00959 
00960 /****************************************************************************
00961  gp_DeleteEdge()
00962  
00963  This function deletes the given edge record J and its twin, reducing the 
00964  number of edges M in the graph.
00965  Before the Jth record is deleted, its link[nextLink] is collected as the
00966  return result.  This is useful because it is the 'next' edge record in the
00967  adjacency list of a vertex, which is otherwise hard to obtain from record
00968  J once it is deleted.
00969  ****************************************************************************/
00970 int gp_DeleteEdge (graphP theGraph,
00971                    int J,
00972                    int nextLink)
00973 {
00974   int JTwin = gp_GetTwinArc (theGraph, J);
00975   int N = theGraph->N,
00976     M = theGraph->M;
00977   int nextArc,
00978     JPos,
00979     MPos,
00980     i;
00981 
00982 /* Calculate the nextArc after J so that, when J is deleted, the return result
00983         informs a calling loop of the next edge to be processed. */
00984   nextArc = theGraph->G[J].link[nextLink];
00985 
00986 /* Delete the edge records J and JTwin. */
00987   theGraph->G[theGraph->G[J].link[0]].link[1] = theGraph->G[J].link[1];
00988   theGraph->G[theGraph->G[J].link[1]].link[0] = theGraph->G[J].link[0];
00989   theGraph->G[theGraph->G[JTwin].link[0]].link[1] = theGraph->G[JTwin].link[1];
00990   theGraph->G[theGraph->G[JTwin].link[1]].link[0] = theGraph->G[JTwin].link[0];
00991 
00992 /* If records J and JTwin are not the last in the edge record array, then
00993         we move the last two edge records to replace J and JTwin.
00994         Also, if nextArc is moved in this process (i.e. if it is part of
00995         the last edge that is moved to replace J and JTwin), then we
00996         change the nextArc variable so that it continues to indicate the
00997         next edge record after J in the adjacency list containing J. */
00998   JPos = (J < JTwin ? J : JTwin) - 2 * N;
00999   MPos = 2 * (M - 1);
01000   if (JPos < MPos)
01001 
01002   {
01003     for (i = 0; i <= 1; i++, JPos++, MPos++)
01004 
01005     {
01006       if (nextArc == 2 * N + MPos)
01007         nextArc = 2 * N + JPos;
01008       theGraph->G[2 * N + JPos] = theGraph->G[2 * N + MPos];
01009       theGraph->G[theGraph->G[2 * N + JPos].link[0]].link[1] = 2 * N + JPos;
01010       theGraph->G[theGraph->G[2 * N + JPos].link[1]].link[0] = 2 * N + JPos;
01011     }
01012   }
01013 
01014 /* Now we reduce the number of edges in the data structure, and then
01015         return the previously calculated successor of J. */
01016   theGraph->M--;
01017   return nextArc;
01018 }

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