int  _ColorVertices_InitGraph(graphP theGraph, int N)
{
    ColorVerticesContext *context = NULL;
    gp_FindExtension(theGraph, COLORVERTICES_ID, (void *)&context);

    if (context == NULL)
    {
        return NOTOK;
    }
    else
    {
        theGraph->N = N;
        theGraph->edgeOffset = 2*N;
        if (theGraph->arcCapacity == 0)
        	theGraph->arcCapacity = 2*DEFAULT_EDGE_LIMIT*N;

        // Create custom structures, initialized at graph level,
        // uninitialized at vertex and graph node levels.
        if (_ColorVertices_CreateStructures(context) != OK)
        {
            return NOTOK;
        }

        // This call initializes the base graph structures, but it also
        // initializes the custom graphnode and vertex level structures
        // due to the overloads of InitGraphNode and InitVertexRec
        context->functions.fpInitGraph(theGraph, N);
    }

    return OK;
}
void _K33Search_EmbedBackEdgeToDescendant(graphP theGraph, int RootSide, int RootVertex, int W, int WPrevLink)
{
    K33SearchContext *context = NULL;
    gp_FindExtension(theGraph, K33SEARCH_ID, (void *)&context);

    if (context != NULL)
    {
        // K33 search may have been attached, but not enabled
        if (theGraph->embedFlags == EMBEDFLAGS_SEARCHFORK33)
        {
        	// Get the fwdArc from the adjacentTo field, and use it to get the backArc
            int backArc = gp_GetTwinArc(theGraph, gp_GetVertexPertinentEdge(theGraph, W));

            // Remove the backArc from the backArcList
            if (context->VI[W].backArcList == backArc)
            {
                if (gp_GetNextArc(theGraph, backArc) == backArc)
                     context->VI[W].backArcList = NIL;
                else context->VI[W].backArcList = gp_GetNextArc(theGraph, backArc);
            }

            gp_SetNextArc(theGraph, gp_GetPrevArc(theGraph, backArc), gp_GetNextArc(theGraph, backArc));
            gp_SetPrevArc(theGraph, gp_GetNextArc(theGraph, backArc), gp_GetPrevArc(theGraph, backArc));
        }

        // Invoke the superclass version of the function
        context->functions.fpEmbedBackEdgeToDescendant(theGraph, RootSide, RootVertex, W, WPrevLink);
    }
}
int  _K33Search_HandleBlockedBicomp(graphP theGraph, int v, int RootVertex, int R)
{
	K33SearchContext *context = NULL;

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

    if (theGraph->embedFlags == EMBEDFLAGS_SEARCHFORK33)
    {
		// If R is the root of a descendant bicomp of v, we push it, but then we know the search for K3,3
    	// will be successful and return NONEMBEDDABLE because this condition corresponds to minor A, which
    	// is a K3,3.  Thus, an "OK to proceed with Walkdown searching elsewhere" result cannot happen,
    	// so we don't have to test for it to detect if we have to pop these two back off the stack.
    	if (R != RootVertex)
    	    sp_Push2(theGraph->theStack, R, 0);

    	// The possible results here are NONEMBEDDABLE if a K3,3 homeomorph is found, or OK if only
    	// a K5 was found and unblocked such that it is OK for the Walkdown to continue searching
    	// elsewhere.  Note that the OK result can only happen if RootVertex==R since minor E can only
    	// happen on a child bicomp of vertex v, not a descendant bicomp.
    	return _SearchForK33InBicomp(theGraph, context, v, RootVertex);
    }
    else
    {
    	return context->functions.fpHandleBlockedBicomp(theGraph, v, RootVertex, R);
    }

    return NOTOK;
}
void _K33Search_InitVertexRec(graphP theGraph, int I)
{
    K33SearchContext *context = NULL;
    gp_FindExtension(theGraph, K33SEARCH_ID, (void *)&context);

    if (context != NULL)
    {
        context->functions.fpInitVertexRec(theGraph, I);
        _InitK33SearchVertexRec(context, I);
    }
}
int gp_AddExtension(graphP theGraph,
                    int  *pModuleID,
                    void *context,
                    void *(*dupContext)(void *, void *),
                    void (*freeContext)(void *),
                    graphFunctionTableP functions)
{
    graphExtensionP newExtension = NULL;

    if (theGraph == NULL || pModuleID == NULL ||
        context == NULL || dupContext == NULL || freeContext == NULL ||
        functions == NULL)
    {
        return NOTOK;
    }

    // If the extension already exists, then don't redefine it.
    if (gp_FindExtension(theGraph, *pModuleID, NULL) == TRUE)
    {
        return NOTOK;
    }

    // Assign a unique ID to the extension if it does not already have one
    if (*pModuleID == 0)
    {
    	*pModuleID = ++moduleIDGenerator;
    }

    // Allocate the new extension
    if ((newExtension = (graphExtensionP) malloc(sizeof(graphExtension))) == NULL)
    {
        return NOTOK;
    }

    // Assign the data payload of the extension
    newExtension->moduleID = *pModuleID;
    newExtension->context = context;
    newExtension->dupContext = dupContext;
    newExtension->freeContext = freeContext;
    newExtension->functions = functions;

    _OverloadFunctions(theGraph, functions);

    // Make the new linkages
    newExtension->next = (struct graphExtension *) theGraph->extensions;
    theGraph->extensions = newExtension;

    // The new extension was successfully added
    return OK;

}
void _K4Search_ReinitializeGraph(graphP theGraph)
{
    K4SearchContext *context = NULL;
    gp_FindExtension(theGraph, K4SEARCH_ID, (void *)&context);

    if (context != NULL)
    {
		// Reinitialize the graph
		context->functions.fpReinitializeGraph(theGraph);

		// Do the reinitialization that is specific to this module
		_K4Search_InitStructures(context);
    }
}
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;
}
void _K33Search_ReinitializeGraph(graphP theGraph)
{
    K33SearchContext *context = NULL;
    gp_FindExtension(theGraph, K33SEARCH_ID, (void *)&context);

    if (context != NULL)
    {
		// Reinitialize the graph
		context->functions.fpReinitializeGraph(theGraph);

		// Do the reinitialization that is specific to this module
		_K33Search_InitStructures(context);
		LCReset(context->separatedDFSChildLists);
		LCReset(context->bin);
    }
}
/********************************************************************
 _K33Search_MergeVertex()

 Overload of merge vertex that does basic behavior but also removes
 the DFS child associated with R from the separatedDFSChildList of W.
 ********************************************************************/
void _K33Search_MergeVertex(graphP theGraph, int W, int WPrevLink, int R)
{
    K33SearchContext *context = NULL;
    gp_FindExtension(theGraph, K33SEARCH_ID, (void *)&context);

    if (context != NULL)
    {
        if (theGraph->embedFlags == EMBEDFLAGS_SEARCHFORK33)
        {
            int theList = context->VI[W].separatedDFSChildList;
            theList = LCDelete(context->separatedDFSChildLists, theList, gp_GetDFSChildFromRoot(theGraph, R));
            context->VI[W].separatedDFSChildList = theList;
        }

        context->functions.fpMergeVertex(theGraph, W, WPrevLink, R);
    }
}
void _K33Search_ReinitializeGraph(graphP theGraph)
{
    K33SearchContext *context = NULL;
    gp_FindExtension(theGraph, K33SEARCH_ID, (void *)&context);

    if (context != NULL)
    {
        // Reinitialization can go much faster if the underlying
        // init graph node and vertex rec functions are called,
        // rather than the overloads of this module, because it
        // avoids lots of unnecessary gp_FindExtension() calls.
        if (theGraph->functions.fpInitGraphNode == _K33Search_InitGraphNode &&
            theGraph->functions.fpInitVertexRec == _K33Search_InitVertexRec)
        {
            // Restore the graph function pointers
            theGraph->functions.fpInitGraphNode = context->functions.fpInitGraphNode;
            theGraph->functions.fpInitVertexRec = context->functions.fpInitVertexRec;

            // Reinitialize the graph
            context->functions.fpReinitializeGraph(theGraph);

            // Restore the function pointers that attach this feature
            theGraph->functions.fpInitGraphNode = _K33Search_InitGraphNode;
            theGraph->functions.fpInitVertexRec = _K33Search_InitVertexRec;

            // Do the reinitialization that is specific to this module
            _K33Search_InitStructures(context);
            LCReset(context->sortedDFSChildLists);
        }

        // If optimization is not possible, then just stick with what works.
        // Reinitialize the graph-level structure and then invoke the
        // reinitialize function.
        else
        {
            LCReset(context->sortedDFSChildLists);

            // The underlying function fpReinitializeGraph() implicitly initializes the K33
            // structures due to the overloads of fpInitGraphNode() and fpInitVertexRec().
            // It just does so less efficiently because each invocation of InitGraphNode
            // and InitVertexRec has to look up the extension again.
            //// _K33Search_InitStructures(context);
            context->functions.fpReinitializeGraph(theGraph);
        }
    }
}
int  _K23Search_HandleBlockedEmbedIteration(graphP theGraph, int I)
{
    if (theGraph->embedFlags == EMBEDFLAGS_SEARCHFORK23)
        return _SearchForK23(theGraph, I);

    else
    {
        K23SearchContext *context = NULL;
        gp_FindExtension(theGraph, K23SEARCH_ID, (void *)&context);

        if (context != NULL)
        {
            return context->functions.fpHandleBlockedEmbedIteration(theGraph, I);
        }
    }

    return NOTOK;
}
void _K33Search_CreateDFSTreeEmbedding(graphP theGraph)
{
    K33SearchContext *context = NULL;
    gp_FindExtension(theGraph, K33SEARCH_ID, (void *)&context);

    if (context != NULL)
    {
        // When searching for K_{3,3} homeomorphs, we need the
        // list of DFS children for each vertex, which gets lost
        // during the initial tree embedding (each DFS tree child
        // arc is moved to the root copy of the vertex)

        if (theGraph->embedFlags == EMBEDFLAGS_SEARCHFORK33)
        {
            int I, J, N;

            N = theGraph->N;

            for (I=0; I<N; I++)
            {
                J = gp_GetFirstArc(theGraph, I);

                // If a vertex has any DFS children, the edges
                // to them are stored in descending order of
                // the DFI's along the successor arc pointers, so
                // we traverse them and prepend each to the
                // ascending order sortedDFSChildList

                while (theGraph->G[J].type == EDGE_DFSCHILD)
                {
                    context->V[I].sortedDFSChildList =
                        LCPrepend(context->sortedDFSChildLists,
                                    context->V[I].sortedDFSChildList,
                                    theGraph->G[J].v);

                    J = gp_GetNextArc(theGraph, J);
                }
            }
        }

        // Invoke the superclass version of the function
        context->functions.fpCreateDFSTreeEmbedding(theGraph);
    }
}
int  gp_AttachK23Search(graphP theGraph)
{
     K23SearchContext *context = NULL;

     // If the K2,3 search feature has already been attached to the graph
     // then there is no need to attach it again
     gp_FindExtension(theGraph, K23SEARCH_ID, (void *)&context);
     if (context != NULL)
     {
         return OK;
     }

     // Allocate a new extension context
     context = (K23SearchContext *) malloc(sizeof(K23SearchContext));
     if (context == NULL)
     {
         return NOTOK;
     }

     // Put the overload functions into the context function table.
     // gp_AddExtension will overload the graph's functions with these, and
     // return the base function pointers in the context function table
     memset(&context->functions, 0, sizeof(graphFunctionTable));

     context->functions.fpHandleBlockedEmbedIteration = _K23Search_HandleBlockedEmbedIteration;
     context->functions.fpEmbedPostprocess = _K23Search_EmbedPostprocess;
     context->functions.fpCheckEmbeddingIntegrity = _K23Search_CheckEmbeddingIntegrity;
     context->functions.fpCheckObstructionIntegrity = _K23Search_CheckObstructionIntegrity;

     // Store the K23 search context, including the data structure and the
     // function pointers, as an extension of the graph
     if (gp_AddExtension(theGraph, &K23SEARCH_ID, (void *) context,
                         _K23Search_DupContext, _K23Search_FreeContext,
                         &context->functions) != OK)
     {
         _K23Search_FreeContext(context);
         return NOTOK;
     }

     return OK;
}
int  _K33Search_CheckEmbeddingIntegrity(graphP theGraph, graphP origGraph)
{
     if (theGraph->embedFlags == EMBEDFLAGS_SEARCHFORK33)
     {
         return OK;
     }

     // When not searching for K3,3, we let the superclass do the work
     else
     {
        K33SearchContext *context = NULL;
        gp_FindExtension(theGraph, K33SEARCH_ID, (void *)&context);

        if (context != NULL)
        {
            return context->functions.fpCheckEmbeddingIntegrity(theGraph, origGraph);
        }
     }

     return NOTOK;
}
int  _K33Search_EmbeddingInitialize(graphP theGraph)
{
    K33SearchContext *context = NULL;
    gp_FindExtension(theGraph, K33SEARCH_ID, (void *)&context);

    if (context != NULL)
    {
    	if (context->functions.fpEmbeddingInitialize(theGraph) != OK)
    		return NOTOK;

        if (theGraph->embedFlags == EMBEDFLAGS_SEARCHFORK33)
        {
        	_CreateBackArcLists(theGraph, context);
        	_CreateSeparatedDFSChildLists(theGraph, context);
        }

        return OK;
    }

    return NOTOK;
}
int  _K33Search_InitGraph(graphP theGraph, int N)
{
    K33SearchContext *context = NULL;
    gp_FindExtension(theGraph, K33SEARCH_ID, (void *)&context);

    if (context == NULL)
        return NOTOK;

	theGraph->N = N;
	theGraph->NV = N;
	if (theGraph->arcCapacity == 0)
		theGraph->arcCapacity = 2*DEFAULT_EDGE_LIMIT*N;

	if (_K33Search_CreateStructures(context) != OK ||
		_K33Search_InitStructures(context) != OK)
		return NOTOK;

	context->functions.fpInitGraph(theGraph, N);

    return OK;
}
int  _K33Search_CheckObstructionIntegrity(graphP theGraph, graphP origGraph)
{
     // When searching for K3,3, we ensure that theGraph is a subgraph of
     // the original graph and that it contains a K3,3 homeomorph
     if (theGraph->embedFlags == EMBEDFLAGS_SEARCHFORK33)
     {
         int  degrees[5], imageVerts[6];

         if (_TestSubgraph(theGraph, origGraph) != TRUE)
         {
             return NOTOK;
         }

         if (_getImageVertices(theGraph, degrees, 4, imageVerts, 6) != OK)
         {
             return NOTOK;
         }

         if (_TestForK33GraphObstruction(theGraph, degrees, imageVerts) == TRUE)
         {
             return OK;
         }

         return NOTOK;
     }

     // When not searching for K3,3, we let the superclass do the work
     else
     {
        K33SearchContext *context = NULL;
        gp_FindExtension(theGraph, K33SEARCH_ID, (void *)&context);

        if (context != NULL)
        {
            return context->functions.fpCheckObstructionIntegrity(theGraph, origGraph);
        }
     }

     return NOTOK;
}
int  _K33Search_EmbedPostprocess(graphP theGraph, int v, int edgeEmbeddingResult)
{
     // For K3,3 search, we just return the edge embedding result because the
     // search result has been obtained already.
     if (theGraph->embedFlags == EMBEDFLAGS_SEARCHFORK33)
     {
         return edgeEmbeddingResult;
     }

     // When not searching for K3,3, we let the superclass do the work
     else
     {
        K33SearchContext *context = NULL;
        gp_FindExtension(theGraph, K33SEARCH_ID, (void *)&context);

        if (context != NULL)
        {
            return context->functions.fpEmbedPostprocess(theGraph, v, edgeEmbeddingResult);
        }
     }

     return NOTOK;
}
int  _K33Search_InitGraph(graphP theGraph, int N)
{
    K33SearchContext *context = NULL;
    gp_FindExtension(theGraph, K33SEARCH_ID, (void *)&context);

    if (context == NULL)
        return NOTOK;
    {
        theGraph->N = N;
        theGraph->edgeOffset = 2*N;
        if (theGraph->arcCapacity == 0)
        	theGraph->arcCapacity = 2*DEFAULT_EDGE_LIMIT*N;

        if (_K33Search_CreateStructures(context) != OK)
            return NOTOK;

        // This call initializes the base graph structures, but it also
        // initializes the custom graphnode and vertex level structures
        // due to the overloads of InitGraphNode and InitVertexRec
        context->functions.fpInitGraph(theGraph, N);
    }

    return OK;
}
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;
}
int _K33Search_CreateFwdArcLists(graphP theGraph)
{
    K33SearchContext *context = NULL;

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

    // For isolating a K_{3,3} homeomorph, we need the forward edges
    // of each vertex to be in sorted order by DFI of descendants.
    // Otherwise we just drop through to the normal processing...

    if (theGraph->embedFlags == EMBEDFLAGS_SEARCHFORK33)
    {
    int I, Jcur, Jnext, ancestor;

        // for each vertex v in order, we follow each of its back edges
        // to the twin forward edge in an ancestor u, then we move
        // the forward edge to the fwdArcList of u.  Since this loop
        // processes vertices in order, the fwdArcList of each vertex
        // will be in order by the neighbor indicated by the forward edges.

        for (I=0; I < theGraph->N; I++)
        {
        	// Skip this vertex if it has no edges
        	Jnext = gp_GetLastArc(theGraph, I);
        	if (!gp_IsArc(theGraph, Jnext))
        		continue;

            // Skip the forward edges, which are in succession at the
        	// end of the arc list (last and its predecessors)
            while (theGraph->G[Jnext].type == EDGE_FORWARD)
                Jnext = gp_GetPrevArc(theGraph, Jnext);

            // Now we want to put all the back arcs in a backArcList, too.
            // Since we've already skipped past the forward arcs, we continue
            // with the predecessor arcs until we either run out of arcs or
            // we find a DFS child arc (the DFS child arcs are in succession
            // at the beginning of the arc list, so when a child arc is
            // encountered in the predecessor direction, then there won't be
            // any more back arcs.
            while (gp_IsArc(theGraph, Jnext) &&
                   theGraph->G[Jnext].type != EDGE_DFSCHILD)
            {
                Jcur = Jnext;
                Jnext = gp_GetPrevArc(theGraph, Jnext);

                if (theGraph->G[Jcur].type == EDGE_BACK)
                {
                    // Remove the back arc from I's adjacency list
                	gp_DetachArc(theGraph, Jcur);

                    // Put the back arc in the backArcList
                    if (context->V[I].backArcList == NIL)
                    {
                        context->V[I].backArcList = Jcur;
                        gp_SetPrevArc(theGraph, Jcur, Jcur);
                        gp_SetNextArc(theGraph, Jcur, Jcur);
                    }
                    else
                    {
                    	gp_AttachArc(theGraph, NIL, context->V[I].backArcList, 1, Jcur);
                    }

                    // Determine the ancestor of vertex I to which Jcur connects
                    ancestor = theGraph->G[Jcur].v;

                    // Go to the forward arc in the ancestor
                    Jcur = gp_GetTwinArc(theGraph, Jcur);

                    // Remove the forward arc from the ancestor's adjacency list
                	gp_DetachArc(theGraph, Jcur);

                    // Add the forward arc to the end of the fwdArcList.
                    if (theGraph->V[ancestor].fwdArcList == NIL)
                    {
                        theGraph->V[ancestor].fwdArcList = Jcur;
                        gp_SetPrevArc(theGraph, Jcur, Jcur);
                        gp_SetNextArc(theGraph, Jcur, Jcur);
                    }
                    else
                    {
                    	gp_AttachArc(theGraph, NIL, theGraph->V[ancestor].fwdArcList, 1, Jcur);
                    }
                }
            }
        }

        // Since the fwdArcLists have been created, we do not fall through
        // to run the superclass implementation
        return OK;
    }

    // If we're not actually running a K3,3 search, then we just run the
    // superclass implementation
    return context->functions.fpCreateFwdArcLists(theGraph);
}
/********************************************************************
 gp_GetExtension()

 Calling this function is equivalent to invoking gp_FindExtension()
 except that some debuggers have difficulty stepping into a function
 that (properly) start by setting a local variable pointer to NULL
 when the debugger has watch expressions that dereference a pointer
 of the same name.  In such cases,

 MyContext *context = NULL;
 gp_FindExtension(theGraph, MYEXTENSION_ID, &context);

 can be replaced by

 MyContext *context = gp_GetExtension(theGraph, MYEXTENSION_ID);

 @param theGraph - the graph whose extension list is to be searched
 @param moduleID - the identifier of the module whose extension context is desired
 @return void pointer to the extension if found, or NULL if not found.
 ********************************************************************/
void *gp_GetExtension(graphP theGraph, int moduleID)
{
	void *context = NULL;
	int result = gp_FindExtension(theGraph, moduleID, &context);
	return result ? context : NULL;
}
Example #23
0
int gp_ColorVertices(graphP theGraph)
{
    ColorVerticesContext *context = NULL;
    int v, deg;
    int u=0, w=0, contractible;

    // Attach the algorithm if it is not already attached
	if (gp_AttachColorVertices(theGraph) != OK)
		return NOTOK;

	// Ensure there is enough stack to perform this operation.
	// At a maximum, the graph reduction will push 7N+M integers.
	// One integer is pushed per edge that is hidden. Plus, whether
	// a vertex is hidden or identified with another vertex, 7 integers
	// are used to store enough information to restore it.
	if (sp_NonEmpty(theGraph->theStack))
		return NOTOK;

	if (sp_GetCapacity(theGraph->theStack) < 7*theGraph->N + theGraph->M)
	{
		stackP newStack = sp_New(7*theGraph->N + theGraph->M);
		if (newStack == NULL)
			return NOTOK;
		sp_Free(&theGraph->theStack);
		theGraph->theStack = newStack;
	}

	// Get the extension context and reinitialize it if necessary
    gp_FindExtension(theGraph, COLORVERTICES_ID, (void *)&context);

    if (context->color[0] > -1)
    	_ColorVertices_Reinitialize(context);

    // Initialize the degree lists, and provide a color for any trivial vertices
    for (v = 0; v < theGraph->N; v++)
    {
    	deg = gp_GetVertexDegree(theGraph, v);
    	_AddVertexToDegList(context, theGraph, v, deg);

    	if (deg == 0)
    		context->color[v] = 0;
    }

    // Initialize the visited flags so they can be used during reductions
    _FillVisitedFlags(theGraph, 0);

    // Reduce the graph using minimum degree selection
    while (context->numVerticesToReduce > 0)
    {
    	v = _GetVertexToReduce(context, theGraph);

    	// Find out if v is contractible and the neighbors to contract
    	contractible = _GetContractibleNeighbors(context, v, &u, &w);

    	// Remove the vertex from the graph. This calls the fpHideEdge
    	// overload, which performs the correct _RemoveVertexFromDegList()
    	// and _AddVertexToDegList() operations on v and its neighbors.
    	if (gp_HideVertex(theGraph, v) != OK)
    		return NOTOK;

    	// If v was contractibile, then identify u and w
    	if (contractible)
    	{
    		if (gp_IdentifyVertices(theGraph, u, w, NIL) != OK)
    			return NOTOK;
    	}
    }

    // Restore the graph one vertex at a time, coloring each vertex distinctly
    // from its neighbors as it is restored.
    context->colorDetector = (int *) calloc(theGraph->N, sizeof(int));
    if (context->colorDetector == NULL)
    	return NOTOK;

    if (gp_RestoreVertices(theGraph) != OK)
    	return NOTOK;

    free(context->colorDetector);
    context->colorDetector = NULL;

	return OK;
}
int  gp_AttachK33Search(graphP theGraph)
{
     K33SearchContext *context = NULL;

     // If the K3,3 search feature has already been attached to the graph,
     // then there is no need to attach it again
     gp_FindExtension(theGraph, K33SEARCH_ID, (void *)&context);
     if (context != NULL)
     {
         return OK;
     }

     // Allocate a new extension context
     context = (K33SearchContext *) malloc(sizeof(K33SearchContext));
     if (context == NULL)
     {
         return NOTOK;
     }

     // First, tell the context that it is not initialized
     context->initialized = 0;

     // Save a pointer to theGraph in the context
     context->theGraph = theGraph;

     // Put the overload functions into the context function table.
     // gp_AddExtension will overload the graph's functions with these, and
     // return the base function pointers in the context function table
     memset(&context->functions, 0, sizeof(graphFunctionTable));

     context->functions.fpEmbeddingInitialize = _K33Search_EmbeddingInitialize;
     context->functions.fpEmbedBackEdgeToDescendant = _K33Search_EmbedBackEdgeToDescendant;
     context->functions.fpMergeBicomps = _K33Search_MergeBicomps;
     context->functions.fpMergeVertex = _K33Search_MergeVertex;
     context->functions.fpHandleBlockedBicomp = _K33Search_HandleBlockedBicomp;
     context->functions.fpEmbedPostprocess = _K33Search_EmbedPostprocess;
     context->functions.fpCheckEmbeddingIntegrity = _K33Search_CheckEmbeddingIntegrity;
     context->functions.fpCheckObstructionIntegrity = _K33Search_CheckObstructionIntegrity;

     context->functions.fpInitGraph = _K33Search_InitGraph;
     context->functions.fpReinitializeGraph = _K33Search_ReinitializeGraph;
     context->functions.fpEnsureArcCapacity = _K33Search_EnsureArcCapacity;

     _K33Search_ClearStructures(context);

     // Store the K33 search context, including the data structure and the
     // function pointers, as an extension of the graph
     if (gp_AddExtension(theGraph, &K33SEARCH_ID, (void *) context,
                         _K33Search_DupContext, _K33Search_FreeContext,
                         &context->functions) != OK)
     {
         _K33Search_FreeContext(context);
         return NOTOK;
     }

     // Create the K33-specific structures if the size of the graph is known
     // Attach functions are always invoked after gp_New(), but if a graph
     // extension must be attached before gp_Read(), then the attachment
     // also happens before gp_InitGraph(), which means N==0.
     // However, sometimes a feature is attached after gp_InitGraph(), in
     // which case N > 0
     if (theGraph->N > 0)
     {
         if (_K33Search_CreateStructures(context) != OK ||
             _K33Search_InitStructures(context) != OK)
         {
             _K33Search_FreeContext(context);
             return NOTOK;
         }
     }

     return OK;
}
Example #25
0
char *_RenderToString(graphP theEmbedding)
{
    DrawPlanarContext *context = NULL;
    gp_FindExtension(theEmbedding, DRAWPLANAR_ID, (void *) &context);

    if (context != NULL)
    {
        int N = theEmbedding->N;
        int M = theEmbedding->M;
        int I, J, e, Mid, Pos;
        char *visRep = (char *) malloc(sizeof(char) * ((M+1) * 2*N + 1));
        char numBuffer[32];

        if (visRep == NULL)
            return NULL;

        if (sp_NonEmpty(context->theGraph->edgeHoles))
        {
            free(visRep);
            return NULL;
        }

        // Clear the space
        for (I = 0; I < N; I++)
        {
            for (J=0; J < M; J++)
            {
                visRep[(2*I) * (M+1) + J] = ' ';
                visRep[(2*I+1) * (M+1) + J] = ' ';
            }

            visRep[(2*I) * (M+1) + M] = '\n';
            visRep[(2*I+1) * (M+1) + M] = '\n';
        }

        // Draw the vertices
        for (I = 0; I < N; I++)
        {
            Pos = context->G[I].pos;
            for (J=context->G[I].start; J<=context->G[I].end; J++)
                visRep[(2*Pos) * (M+1) + J] = '-';

            // Draw vertex label
            Mid = (context->G[I].start + context->G[I].end)/2;
            sprintf(numBuffer, "%d", I);
            if ((unsigned)(context->G[I].end - context->G[I].start + 1) >= strlen(numBuffer))
            {
                strncpy(visRep + (2*Pos) * (M+1) + Mid, numBuffer, strlen(numBuffer));
            }
            // If the vertex width is less than the label width, then fail gracefully
            else
            {
                if (strlen(numBuffer)==2)
                    visRep[(2*Pos) * (M+1) + Mid] = numBuffer[0];
                else
                    visRep[(2*Pos) * (M+1) + Mid] = '*';

                visRep[(2*Pos+1) * (M+1) + Mid] = numBuffer[strlen(numBuffer)-1];
            }
        }

        // Draw the edges
        for (e=0; e<M; e++)
        {
            J = 2*N + 2*e;
            Pos = context->G[J].pos;
            for (I=context->G[J].start; I<context->G[J].end; I++)
            {
                if (I > context->G[J].start)
                    visRep[(2*I) * (M+1) + Pos] = '|';
                visRep[(2*I+1) * (M+1) + Pos] = '|';
            }
        }

        // Null terminate string and return it
        visRep[(M+1) * 2*N] = '\0';
        return visRep;
    }

    return NULL;
}
int  gp_AttachColorVertices(graphP theGraph)
{
     ColorVerticesContext *context = NULL;

     // If the vertex coloring feature has already been attached to the graph,
     // then there is no need to attach it again
     gp_FindExtension(theGraph, COLORVERTICES_ID, (void *)&context);
     if (context != NULL)
     {
         return OK;
     }

     // Allocate a new extension context
     context = (ColorVerticesContext *) malloc(sizeof(ColorVerticesContext));
     if (context == NULL)
     {
         return NOTOK;
     }

     // First, tell the context that it is not initialized
     context->initialized = 0;

     // Save a pointer to theGraph in the context
     context->theGraph = theGraph;

     // Put the overload functions into the context function table.
     // gp_AddExtension will overload the graph's functions with these, and
     // return the base function pointers in the context function table
     memset(&context->functions, 0, sizeof(graphFunctionTable));

     context->functions.fpInitGraph = _ColorVertices_InitGraph;
     context->functions.fpReinitializeGraph = _ColorVertices_ReinitializeGraph;

     context->functions.fpReadPostprocess = _ColorVertices_ReadPostprocess;
     context->functions.fpWritePostprocess = _ColorVertices_WritePostprocess;

     context->functions.fpHideEdge = _ColorVertices_HideEdge;
     context->functions.fpIdentifyVertices = _ColorVertices_IdentifyVertices;
     context->functions.fpRestoreVertex = _ColorVertices_RestoreVertex;

     _ColorVertices_ClearStructures(context);

     // Store the context, including the data structure and the
     // function pointers, as an extension of the graph
     if (gp_AddExtension(theGraph, &COLORVERTICES_ID, (void *) context,
                         _ColorVertices_DupContext, _ColorVertices_FreeContext,
                         &context->functions) != OK)
     {
         _ColorVertices_FreeContext(context);
         return NOTOK;
     }

     // Create the algorithm-specific structures if the size of the graph is known
     // Attach functions are typically invoked after gp_New(), but if a graph
     // extension must be attached before gp_Read(), then the attachment
     // also happens before gp_InitGraph() because gp_Read() invokes init only
     // after it reads the order N of the graph.  Hence, this attach call would
     // occur when N==0 in the case of gp_Read().
     // But if a feature is attached after gp_InitGraph(), then N > 0 and so we
     // need to create and initialize all the custom data structures
     if (theGraph->N > 0)
     {
         if (_ColorVertices_CreateStructures(context) != OK ||
             _ColorVertices_InitStructures(context) != OK)
         {
             _ColorVertices_FreeContext(context);
             return NOTOK;
         }
     }

     return OK;
}