int  _K33Search_MergeBicomps(graphP theGraph, int v, int RootVertex, int W, int WPrevLink)
{
    K33SearchContext *context = NULL;
    gp_FindExtension(theGraph, K33SEARCH_ID, (void *)&context);

    if (context != NULL)
    {
        /* If the merge is blocked, then a K_{3,3} homeomorph is isolated,
           and NONEMBEDDABLE is returned so that the Walkdown terminates */

        if (theGraph->embedFlags == EMBEDFLAGS_SEARCHFORK33)
        {
        int mergeBlocker;

            // We want to test all merge points on the stack
            // as well as W, since the connection will go
            // from W.  So we push W as a 'degenerate' merge point.
            sp_Push2(theGraph->theStack, W, WPrevLink);
            sp_Push2(theGraph->theStack, NIL, NIL);

			if (_SearchForMergeBlocker(theGraph, context, v, &mergeBlocker) != OK)
				return NOTOK;

			if (gp_IsVertex(mergeBlocker))
			{
				if (_FindK33WithMergeBlocker(theGraph, context, v, mergeBlocker) != OK)
					return NOTOK;

				return NONEMBEDDABLE;
			}

            // If no merge blocker was found, then remove W from the stack.
            sp_Pop2(theGraph->theStack, W, WPrevLink);
            sp_Pop2(theGraph->theStack, W, WPrevLink);
        }

        // If the merge was not blocked, then we perform the merge
        // When not doing a K3,3 search, then the merge is not
        // blocked as far as the K3,3 search method is concerned
        // Another algorithms could overload MergeBicomps and block
        // merges under certain conditions, but those would be based
        // on data maintained by the extension that implements the
        // other algorithm-- if *that* algorithm is the one being run
        return context->functions.fpMergeBicomps(theGraph, v, RootVertex, W, WPrevLink);
    }

    return NOTOK;
}
Example #2
0
int  _FindNonplanarityBicompRoot(graphP theGraph)
{
int  R, tempChild, fwdArc, W=NIL, C=NIL, I=theGraph->IC.v;

/* If the stack is non-empty, then the Walkdown stopped on a descendant
    bicomp, not one rooted by I.  We need to get that root before the
    stack is destroyed by other routines. */

     if (sp_NonEmpty(theGraph->theStack))
     {
         int e;

         sp_Pop2(theGraph->theStack, R, e);
         return R;
     }

/* Obtain the forward arc of an unembedded back edge from I to one of its
    descendants (edges are removed from the forward arc list as they are
    embedded, so the list will be empty if all edges were embedded). */

    if ((fwdArc = theGraph->V[I].fwdArcList) == NIL)
        return NIL;

    W = theGraph->G[fwdArc].v;

/* Find the greatest DFS child C of I that is less than W.  This will
    give us the ancestor of W that is a child of I.  Since the
    ancestors of I have not been processed by the planarity algorithm,
    the separatedDFSChildList of I contains all the children of I. */

    tempChild = theGraph->V[I].separatedDFSChildList;

    while (tempChild != NIL)
    {
        if (tempChild > C && tempChild < W)
            C = tempChild;

        tempChild = LCGetNext(theGraph->DFSChildLists,
                              theGraph->V[I].separatedDFSChildList, tempChild);
    }

    if (C == NIL) return NIL;

/* The root vertex of a bicomp rooted by edge (I, C) is located at
        position C+N in our data structures */

     R = C + theGraph->N;
     return R;
}
int  _K4Search_HandleBlockedBicomp(graphP theGraph, int v, int RootVertex, int R)
{
	K4SearchContext *context = NULL;

	gp_FindExtension(theGraph, K4SEARCH_ID, (void *)&context);
	if (context == NULL)
		return NOTOK;

    if (theGraph->embedFlags == EMBEDFLAGS_SEARCHFORK4)
    {
    	int RetVal = OK;

    	// If invoked on a descendant bicomp, then we push its root then search once
    	// since not finding a K4 homeomorph will also clear the blockage and allow
    	// the Walkdown to continue walking down
    	if (R != RootVertex)
    	{
    	    sp_Push2(theGraph->theStack, R, 0);
            if ((RetVal = _SearchForK4InBicomp(theGraph, context, v, R)) == OK)
            {
            	// If the Walkdown will be told it is OK to continue, then we have to take the descendant
            	// bicomp root back off the stack so the Walkdown can try to descend to it again.
            	int dummy;
            	sp_Pop2(theGraph->theStack, R, dummy);

            	// And we have to clear the indicator of the minor A that was reduced, since it was eliminated.
            	theGraph->IC.minorType = 0;
            }
    	}

    	// Otherwise, if invoked on a child bicomp rooted by a virtual copy of v,
    	// then we search for a K4 homeomorph, and if OK is returned, then that indicates
    	// the blockage has been cleared and it is OK to Walkdown the bicomp.
    	// But the Walkdown finished, already, so we launch it again.
    	// If the Walkdown returns OK then all forward arcs were embedded.  If NONEMBEDDABLE
    	// is returned, then the bicomp got blocked again, so we have to reiterate the K4 search
    	else
    	{
    		// If Walkdown has recursively called this handler on the bicomp rooted by RootVertex,
    		// then it is still blocked, so we just return NONEMBEDDABLE, which causes Walkdown to
    		// return to the loop below and signal that the loop should invoke the Walkdown again.
    		if (context->handlingBlockedBicomp)
    			return NONEMBEDDABLE;

    		context->handlingBlockedBicomp = TRUE;
    		do {
    			// Detect whether bicomp can be used to find a K4 homeomorph.  It it does, then
    			// it returns NONEMBEDDABLE so we break the search because we found the desired K4
    			// If OK is returned, then the blockage was cleared and it is OK to Walkdown again.
    			if ((RetVal = _SearchForK4InBicomp(theGraph, context, v, RootVertex)) != OK)
    				break;

    			// Walkdown again to embed more edges.  If Walkdown returns OK, then all remaining
    			// edges to its descendants are embedded, so we'll get out of this loop. If Walkdown
    			// detects that it still has not embedded all the edges to descendants of the bicomp's
    			// root edge child, then Walkdown calls this routine again, and the above non-reentrancy
    			// code returns NONEMBEDDABLE, causing this loop to search again for a K4.
    			theGraph->IC.minorType = 0;
    			RetVal = theGraph->functions.fpWalkDown(theGraph, v, RootVertex);

    			// Except if the Walkdown returns NONEMBEDDABLE due to finding a K4 homeomorph entangled
    			// with a descendant bicomp (the R != RootVertex case above), then it was found
    			// entangled with Minor A, so we can stop the search if minor A is detected
    			if (theGraph->IC.minorType & MINORTYPE_A)
    				break;

    		} while (RetVal == NONEMBEDDABLE);
			context->handlingBlockedBicomp = FALSE;
    	}

    	return RetVal;
    }
    else
    {
    	return context->functions.fpHandleBlockedBicomp(theGraph, v, RootVertex, R);
    }

    return NOTOK;
}
Example #4
0
int  gp_CreateDFSTree(graphP theGraph)
{
stackP theStack;
int N, DFI = 0, I, uparent, u, e, J;

#ifdef PROFILE
platform_time start, end;
platform_GetTime(start);
#endif

     if (theGraph==NULL) return NOTOK;
     if (theGraph->internalFlags & FLAGS_DFSNUMBERED) return OK;

     gp_LogLine("\ngraphPreprocess.c/gp_CreateDFSTree() start");

     N = theGraph->N;
     theStack  = theGraph->theStack;

/* There are 2M edge records (arcs) and for each we can push 2 integers,
        so a stack of 2 * arcCapacity integers suffices.
        This is already in theGraph structure, so we make sure it's empty,
        then clear all visited flags in prep for the Depth first search. */

     if (sp_GetCapacity(theStack) < 2*gp_GetArcCapacity(theGraph))
    	 return NOTOK;

     sp_ClearStack(theStack);

     for (I=0; I < N; I++)
          theGraph->G[I].visited = 0;

/* This outer loop causes the connected subgraphs of a disconnected
        graph to be numbered */

     for (I=0; I < N && DFI < N; I++)
     {
          if (theGraph->V[I].DFSParent != NIL)
              continue;

          sp_Push2(theStack, NIL, NIL);
          while (sp_NonEmpty(theStack))
          {
              sp_Pop2(theStack, uparent, e);
              u = uparent == NIL ? I : theGraph->G[e].v;

              if (!theGraph->G[u].visited)
              {
            	  gp_LogLine(gp_MakeLogStr3("V=%d, DFI=%d, Parent=%d", u, DFI, uparent));

            	  theGraph->G[u].visited = 1;
                  theGraph->G[u].v = DFI++;
                  theGraph->V[u].DFSParent = uparent;
                  if (e != NIL)
                  {
                      theGraph->G[e].type = EDGE_DFSCHILD;
                      theGraph->G[gp_GetTwinArc(theGraph, e)].type = EDGE_DFSPARENT;

                      // We want the child arcs to be at the beginning
                      // of the adjacency list.
                      gp_MoveArcToFirst(theGraph, uparent, e);
                  }

                  /* Push edges to all unvisited neighbors. These will be either
                        tree edges to children or forward arcs of back edges */

                  J = gp_GetFirstArc(theGraph, u);
                  while (gp_IsArc(theGraph, J))
                  {
                      if (!theGraph->G[theGraph->G[J].v].visited)
                          sp_Push2(theStack, u, J);
                      J = gp_GetNextArc(theGraph, J);
                  }
              }
              else
              {
                  // If the edge leads to a visited vertex, then it is
            	  // the forward arc of a back edge.
                  theGraph->G[e].type = EDGE_FORWARD;
                  theGraph->G[gp_GetTwinArc(theGraph, e)].type = EDGE_BACK;

                  // We want all of the forward edges to descendants to
                  // be at the end of the adjacency list.
                  // The tree edge to the parent and the back edges to ancestors
                  // are in the middle, between the child edges and forward edges.
                  gp_MoveArcToLast(theGraph, uparent, e);
              }
          }
     }

     gp_LogLine("graphPreprocess.c/gp_CreateDFSTree() end\n");

     theGraph->internalFlags |= FLAGS_DFSNUMBERED;

#ifdef PROFILE
platform_GetTime(end);
printf("DFS in %.3lf seconds.\n", platform_GetDuration(start,end));
#endif

     return OK;
}