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); } }
void _AddBackEdge(graphP theGraph, int ancestor, int descendant) { int fwdArc, backArc; /* We get the two edge records of the back edge to embed. */ fwdArc = theGraph->V[ancestor].fwdArcList; while (gp_IsArc(theGraph, fwdArc)) { if (theGraph->G[fwdArc].v == descendant) break; fwdArc = gp_GetNextArc(theGraph, fwdArc); if (fwdArc == theGraph->V[ancestor].fwdArcList) fwdArc = NIL; } if (fwdArc == NIL) return; backArc = gp_GetTwinArc(theGraph, fwdArc); /* The forward arc is removed from the fwdArcList of the ancestor. */ if (theGraph->V[ancestor].fwdArcList == fwdArc) { if (gp_GetNextArc(theGraph, fwdArc) == fwdArc) theGraph->V[ancestor].fwdArcList = NIL; else theGraph->V[ancestor].fwdArcList = gp_GetNextArc(theGraph, fwdArc); } gp_SetNextArc(theGraph, gp_GetPrevArc(theGraph, fwdArc), gp_GetNextArc(theGraph, fwdArc)); gp_SetPrevArc(theGraph, gp_GetNextArc(theGraph, fwdArc), gp_GetPrevArc(theGraph, fwdArc)); /* The forward arc is added to the adjacency list of the ancestor. */ gp_SetPrevArc(theGraph, fwdArc, gp_AdjacencyListEndMark(ancestor)); gp_SetNextArc(theGraph, fwdArc, gp_GetFirstArc(theGraph, ancestor)); gp_SetPrevArc(theGraph, gp_GetFirstArc(theGraph, ancestor), fwdArc); gp_SetFirstArc(theGraph, ancestor, fwdArc); /* The back arc is added to the adjacency list of the descendant. */ gp_SetPrevArc(theGraph, backArc, gp_AdjacencyListEndMark(descendant)); gp_SetNextArc(theGraph, backArc, gp_GetFirstArc(theGraph, descendant)); gp_SetPrevArc(theGraph, gp_GetFirstArc(theGraph, descendant), backArc); gp_SetFirstArc(theGraph, descendant, backArc); theGraph->G[backArc].v = ancestor; }
void _AddBackEdge(graphP theGraph, int ancestor, int descendant) { int fwdArc, backArc; /* We get the two edge records of the back edge to embed. */ fwdArc = gp_GetVertexFwdArcList(theGraph, ancestor); while (gp_IsArc(fwdArc)) { if (gp_GetNeighbor(theGraph, fwdArc) == descendant) break; fwdArc = gp_GetNextArc(theGraph, fwdArc); if (fwdArc == gp_GetVertexFwdArcList(theGraph, ancestor)) fwdArc = NIL; } if (gp_IsNotArc(fwdArc)) return; backArc = gp_GetTwinArc(theGraph, fwdArc); /* The forward arc is removed from the fwdArcList of the ancestor. */ if (gp_GetVertexFwdArcList(theGraph, ancestor) == fwdArc) { if (gp_GetNextArc(theGraph, fwdArc) == fwdArc) gp_SetVertexFwdArcList(theGraph, ancestor, NIL); else gp_SetVertexFwdArcList(theGraph, ancestor, gp_GetNextArc(theGraph, fwdArc)); } gp_SetNextArc(theGraph, gp_GetPrevArc(theGraph, fwdArc), gp_GetNextArc(theGraph, fwdArc)); gp_SetPrevArc(theGraph, gp_GetNextArc(theGraph, fwdArc), gp_GetPrevArc(theGraph, fwdArc)); /* The forward arc is added to the adjacency list of the ancestor. */ gp_SetPrevArc(theGraph, fwdArc, NIL); gp_SetNextArc(theGraph, fwdArc, gp_GetFirstArc(theGraph, ancestor)); gp_SetPrevArc(theGraph, gp_GetFirstArc(theGraph, ancestor), fwdArc); gp_SetFirstArc(theGraph, ancestor, fwdArc); /* The back arc is added to the adjacency list of the descendant. */ gp_SetPrevArc(theGraph, backArc, NIL); gp_SetNextArc(theGraph, backArc, gp_GetFirstArc(theGraph, descendant)); gp_SetPrevArc(theGraph, gp_GetFirstArc(theGraph, descendant), backArc); gp_SetFirstArc(theGraph, descendant, backArc); gp_SetNeighbor(theGraph, backArc, ancestor); }
/******************************************************************** _CreateBackArcLists() ********************************************************************/ void _CreateBackArcLists(graphP theGraph, K33SearchContext *context) { int v, e, eTwin, ancestor; for (v = gp_GetFirstVertex(theGraph); gp_VertexInRange(theGraph, v); v++) { e = gp_GetVertexFwdArcList(theGraph, v); while (gp_IsArc(e)) { // Get the ancestor endpoint and the associated back arc ancestor = gp_GetNeighbor(theGraph, e); eTwin = gp_GetTwinArc(theGraph, e); // Put it into the back arc list of the ancestor if (gp_IsNotArc(context->VI[ancestor].backArcList)) { context->VI[ancestor].backArcList = eTwin; gp_SetPrevArc(theGraph, eTwin, eTwin); gp_SetNextArc(theGraph, eTwin, eTwin); } else { int eHead = context->VI[ancestor].backArcList; int eTail = gp_GetPrevArc(theGraph, eHead); gp_SetPrevArc(theGraph, eTwin, eTail); gp_SetNextArc(theGraph, eTwin, eHead); gp_SetPrevArc(theGraph, eHead, eTwin); gp_SetNextArc(theGraph, eTail, eTwin); } // Advance to the next forward edge e = gp_GetNextArc(theGraph, e); if (e == gp_GetVertexFwdArcList(theGraph, v)) e = NIL; } } }
int _ReadAdjList(graphP theGraph, FILE *Infile) { int N, I, W, ErrorCode, adjList, J; if (Infile == NULL) return NOTOK; fgetc(Infile); /* Skip the N= */ fgetc(Infile); fscanf(Infile, " %d ", &N); /* Read N */ if (gp_InitGraph(theGraph, N) != OK) { printf("Failed to init graph"); return NOTOK; } // Clear the visited members of the vertices so they can be used // during the adjacency list read operation for (I=0; I < N; I++) theGraph->G[I].visited = 0; // Do the adjacency list read operation for each vertex in order for (I = 0, ErrorCode = OK; I < N && ErrorCode==OK; I++) { // Read the vertex number fscanf(Infile, "%d", &theGraph->G[I].v); // The vertices are expected to be in numeric ascending order if (theGraph->G[I].v != I) return NOTOK; // Skip the colon after the vertex number fgetc(Infile); // If the vertex already has a non-empty adjacency list, then it is // the result of adding edges during processing of preceding vertices. // The list is removed from the current vertex I and saved for use // during the read operation for I. Adjacencies to preceding vertices // are pulled from this list, if present, or added as directed edges // if not. Adjacencies to succeeding vertices are added as undirected // edges, and will be corrected later if the succeeding vertex does not // have the matching adjacency using the following mechanism. After the // read operation for a vertex I, any adjacency nodes left in the saved // list are converted to directed edges from the preceding vertex to I. adjList = gp_GetFirstArc(theGraph, I); if (gp_IsArc(theGraph, adjList)) { // Store the adjacency node location in the visited member of each // of the preceding vertices to which I is adjacent so that we can // efficiently detect the adjacency during the read operation and // efficiently find the adjacency node. J = gp_GetFirstArc(theGraph, I); while (gp_IsArc(theGraph, J)) { theGraph->G[theGraph->G[J].v].visited = J; J = gp_GetNextArc(theGraph, J); } // Make the adjacency list circular, for later ease of processing gp_SetPrevArc(theGraph, adjList, gp_GetLastArc(theGraph, I)); gp_SetNextArc(theGraph, gp_GetLastArc(theGraph, I), adjList); // Remove the list from the vertex gp_SetFirstArc(theGraph, I, gp_AdjacencyListEndMark(I)); gp_SetLastArc(theGraph, I, gp_AdjacencyListEndMark(I)); } // Read the adjacency list. while (1) { // Read the next adjacent vertex, with NIL indicating the list end fscanf(Infile, " %d ", &W); if (W < 0) break; // Vertex numbers must be less than N if (W >= N) ErrorCode = NOTOK; // Loop edges are not supported, but no reason to throw an error if they occur // If a loop occurs, we just do like the ostrich and ignore it else if (W == I) ErrorCode = OK; // If the adjacency is to a succeeding, higher numbered vertex, // then we'll add an undirected edge for now else if (I < W) { ErrorCode = gp_AddEdge(theGraph, I, 0, W, 0); } // If the adjacency is to a preceding, lower numbered vertex, then // we have to pull the adjacency node from the preexisting adjList, // if it is there, and if not then we have to add a directed edge. else { // If the adjacency node (arc) already exists, then we add it // as the new first arc of the vertex and delete it from adjList if (theGraph->G[W].visited) { J = theGraph->G[W].visited; // Remove the arc J from the adjList construct theGraph->G[W].visited = 0; if (adjList == J) { if ((adjList = gp_GetNextArc(theGraph, J)) == J) adjList = NIL; } gp_SetPrevArc(theGraph, gp_GetNextArc(theGraph, J), gp_GetPrevArc(theGraph, J)); gp_SetNextArc(theGraph, gp_GetPrevArc(theGraph, J), gp_GetNextArc(theGraph, J)); gp_AttachFirstArc(theGraph, I, J); } // If an adjacency node to the lower numbered vertex W does not // already exist, then we make a new directed arc from the current // vertex I to W. else { // It is added as the new first arc in both vertices ErrorCode = gp_AddEdge(theGraph, I, 0, W, 0); if (ErrorCode == OK) // Note that this call also sets OUTONLY on the twin arc gp_SetDirection(theGraph, gp_GetFirstArc(theGraph, W), EDGEFLAG_DIRECTION_INONLY); } } if (ErrorCode != OK) break; } // If there are still adjList entries after the read operation // then those entries are not representative of full undirected edges. // Rather, they represent incoming directed arcs from other vertices // into vertex I. They need to be added back into I's adjacency list but // marked as "INONLY", while the twin is marked "OUTONLY" (by the same function). while (gp_IsArc(theGraph, adjList)) { J = adjList; theGraph->G[theGraph->G[J].v].visited = 0; if ((adjList = gp_GetNextArc(theGraph, J)) == J) adjList = NIL; gp_SetPrevArc(theGraph, gp_GetNextArc(theGraph, J), gp_GetPrevArc(theGraph, J)); gp_SetNextArc(theGraph, gp_GetPrevArc(theGraph, J), gp_GetNextArc(theGraph, J)); gp_AttachFirstArc(theGraph, I, J); gp_SetDirection(theGraph, J, EDGEFLAG_DIRECTION_INONLY); } } return ErrorCode; }
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); }