Exemple #1
0
int _AddAndMarkEdge(graphP theGraph, int ancestor, int descendant)
{
    _AddBackEdge(theGraph, ancestor, descendant);

    /* Mark the edge so it is not deleted */

    gp_SetVertexVisited(theGraph, ancestor);
    gp_SetEdgeVisited(theGraph, gp_GetFirstArc(theGraph, ancestor));
    gp_SetEdgeVisited(theGraph, gp_GetFirstArc(theGraph, descendant));
    gp_SetVertexVisited(theGraph, descendant);

    return OK;
}
Exemple #2
0
int _AddAndMarkEdge(graphP theGraph, int ancestor, int descendant)
{
    _AddBackEdge(theGraph, ancestor, descendant);

    /* Mark the edge so it is not deleted */

    theGraph->G[ancestor].visited = 1;
    theGraph->G[gp_GetFirstArc(theGraph, ancestor)].visited = 1;
    theGraph->G[gp_GetFirstArc(theGraph, descendant)].visited = 1;
    theGraph->G[descendant].visited = 1;

    return OK;
}
int gp_ColorVerticesIntegrityCheck(graphP theGraph, graphP origGraph)
{
    int v, w, e;
    ColorVerticesContext *context = (ColorVerticesContext *) gp_GetExtension(theGraph, COLORVERTICES_ID);

    if (theGraph == NULL || origGraph == NULL || context == NULL)
        return NOTOK;

    if (gp_GetNumColorsUsed(theGraph) <= 0 && theGraph->M > 0)
        return NOTOK;

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

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

    for (v = gp_GetFirstVertex(theGraph); gp_VertexInRange(theGraph, v); v++)
    {
        e = gp_GetFirstArc(theGraph, v);
        while (gp_IsArc(e))
        {
            w = gp_GetNeighbor(theGraph, e);
            if (context->color[v] < 0 || context->color[v] == context->color[w])
                return NOTOK;

            e = gp_GetNextArc(theGraph, e);
        }
    }

    return OK;
}
int _GetContractibleNeighbors(ColorVerticesContext *context, int v, int *pu, int *pw)
{
	int lowDegreeNeighbors[5], i, j, n=0, J;
	graphP theGraph = context->theGraph;

	// This method is only applicable to degree 5 vertices
	if (_GetVertexDegree(context, v) != 5)
		return FALSE;

	// Get all neighbors of degree at most 7
    J = gp_GetFirstArc(theGraph, v);
    while (gp_IsArc(theGraph, J))
    {
    	if (_GetVertexDegree(context, theGraph->G[J].v) <= 7)
    		lowDegreeNeighbors[n++] = theGraph->G[J].v;
        J = gp_GetNextArc(theGraph, J);
    }

    // Seek the pair of *non-adjacent* low degree neighbors
    for (i=0; i < (n-1); i++)
    	for (j=i+1; j < n; j++)
    		if (!gp_IsNeighbor(theGraph, lowDegreeNeighbors[i], lowDegreeNeighbors[j]))
    		{
    			*pu = lowDegreeNeighbors[i];
    			*pw = lowDegreeNeighbors[j];
    			return TRUE;
    		}

    // The desired pair of neighbors was not found
    return FALSE;
}
int gp_ColorVerticesIntegrityCheck(graphP theGraph, graphP origGraph)
{
	int I, J, w;
    ColorVerticesContext *context = (ColorVerticesContext *) gp_GetExtension(theGraph, COLORVERTICES_ID);

    if (theGraph == NULL || origGraph == NULL || context == NULL)
        return NOTOK;

    if (gp_GetNumColorsUsed(theGraph) <= 0 && theGraph->M > 0)
    	return NOTOK;

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

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

    for (I=0; I < theGraph->N; I++)
    {
        J = gp_GetFirstArc(theGraph, I);
        while (gp_IsArc(theGraph, J))
        {
             w = theGraph->G[J].v;
             if (context->color[I] < 0 || context->color[I] == context->color[w])
            	 return NOTOK;

             J = gp_GetNextArc(theGraph, J);
        }
    }

	return OK;
}
Exemple #6
0
int  _DeleteUnmarkedVerticesAndEdges(graphP theGraph)
{
    int  v, e;

    /* All of the forward and back arcs of all of the edge records
       were removed from the adjacency lists in the planarity algorithm
       preprocessing.  We now put them back into the adjacency lists
       (and we do not mark them), so they can be properly deleted below. */

    for (v = gp_GetFirstVertex(theGraph); gp_VertexInRange(theGraph, v); v++)
    {
        while (gp_IsArc(e = gp_GetVertexFwdArcList(theGraph, v)))
            _AddBackEdge(theGraph, v, gp_GetNeighbor(theGraph, e));
    }

    /* Now we delete all unmarked edges.  We don't delete vertices from the
       embedding, but the ones we should delete will become degree zero. */

    for (v = gp_GetFirstVertex(theGraph); gp_VertexInRange(theGraph, v); v++)
    {
        e = gp_GetFirstArc(theGraph, v);
        while (gp_IsArc(e))
        {
            if (gp_GetEdgeVisited(theGraph, e))
                e = gp_GetNextArc(theGraph, e);
            else e = gp_DeleteEdge(theGraph, e, 0);
        }
    }

    return OK;
}
Exemple #7
0
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;
}
Exemple #8
0
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);
}
Exemple #9
0
/****************************************************************************
 _MarkDFSPath()

 Sets visited flags of vertices and edges from descendant to ancestor,
 including root copy vertices, and including the step of hopping from
 a root copy to its parent copy.

 At each vertex, the edge record is obtained whose type indicates that it
 leads to the DFS parent.  An earlier implementation just used the DFS parent
 member of the vertex, but then had to find the edge to mark anyway.
 This method is more generalized because some extension algorithms reduce
 DFS paths to single DFS tree edges, in which case the edge record with type
 EDGE_TYPE_PARENT may indicate the DFS paent or an ancestor.
 ****************************************************************************/
int  _MarkDFSPath(graphP theGraph, int ancestor, int descendant)
{
    int  e, parent;

    // If we are marking from a root (virtual) vertex upward, then go up to the parent
    // copy before starting the loop
    if (gp_IsVirtualVertex(theGraph, descendant))
        descendant = gp_GetPrimaryVertexFromRoot(theGraph, descendant);

    // Mark the lowest vertex (the one with the highest number).
    gp_SetVertexVisited(theGraph, descendant);

    // Mark all ancestors of the lowest vertex, and the edges used to reach
    // them, up to the given ancestor vertex.
    while (descendant != ancestor)
    {
        if (gp_IsNotVertex(descendant))
            return NOTOK;

        // If we are at a bicomp root, then ascend to its parent copy and
        // mark it as visited.
        if (gp_IsVirtualVertex(theGraph, descendant))
        {
            parent = gp_GetPrimaryVertexFromRoot(theGraph, descendant);
        }

        // If we are on a regular, non-virtual vertex then get the edge to the parent,
        // mark the edge, then fall through to the code that marks the parent vertex.
        else
        {
            // Scan the edges for the one marked as the DFS parent
            parent = NIL;
            e = gp_GetFirstArc(theGraph, descendant);
            while (gp_IsArc(e))
            {
                if (gp_GetEdgeType(theGraph, e) == EDGE_TYPE_PARENT)
                {
                    parent = gp_GetNeighbor(theGraph, e);
                    break;
                }
                e = gp_GetNextArc(theGraph, e);
            }

            // Sanity check on the data structure integrity
            if (gp_IsNotVertex(parent))
                return NOTOK;

            // Mark the edge
            gp_SetEdgeVisited(theGraph, e);
            gp_SetEdgeVisited(theGraph, gp_GetTwinArc(theGraph, e));
        }

        // Mark the parent, then hop to the parent and reiterate
        gp_SetVertexVisited(theGraph, parent);
        descendant = parent;
    }

    return OK;
}
Exemple #10
0
int  _MarkDFSPath(graphP theGraph, int ancestor, int descendant)
{
int  J, parent, Z, N;

     N = theGraph->N;

     /* If we are marking from a root vertex upward, then go up to the parent
        copy before starting the loop */

     if (descendant >= N)
         descendant = theGraph->V[descendant-N].DFSParent;

     /* Mark the lowest vertex (i.e. the descendant with the highest number) */
     theGraph->G[descendant].visited = 1;

     /* Mark all ancestors of the lowest vertex, and the edges used to reach
        them, up to the given ancestor vertex. */

     while (descendant != ancestor)
     {
          /* Get the parent vertex */

          parent = theGraph->V[descendant].DFSParent;

          /* If the descendant was a DFS tree root, then obviously
                we aren't going to find the ancestor, so something is wrong.*/

          if (parent == NIL || parent == descendant)
              return NOTOK;

          /* Find the edge from descendant that leads either to
                parent or to a root copy of the parent.
                When the edge is found, mark it and break the loop */

          J = gp_GetFirstArc(theGraph, descendant);
          while (gp_IsArc(theGraph, J))
          {
              Z = theGraph->G[J].v;
              if ((Z < N && Z == parent) ||
                  (Z >= N && theGraph->V[Z-N].DFSParent == parent))
              {
                  theGraph->G[J].visited = 1;
                  theGraph->G[gp_GetTwinArc(theGraph, J)].visited = 1;
                  break;
              }
              J = gp_GetNextArc(theGraph, J);
          }

          /* Mark the parent copy of the DFS parent */
          theGraph->G[parent].visited = 1;

          /* Hop to the parent */
          descendant = parent;
     }

     return OK;
}
void _MarkExternalFaceVertices(graphP theGraph, int startVertex)
{
    int nextVertex = startVertex;
    int e = gp_GetFirstArc(theGraph, nextVertex);
    int eTwin;

    // Handle the case of an isolated vertex
    if (gp_IsNotArc(e))
    {
    	gp_SetVertexVisited(theGraph, startVertex);
    	return;
    }

    // Process a non-trivial connected component
    do {
        gp_SetVertexVisited(theGraph, nextVertex);

        // The arc out of the vertex just visited points to the next vertex
        nextVertex = gp_GetNeighbor(theGraph, e);

        // Arc used to enter the next vertex is needed so we can get the
        // next edge in rotation order.
        // Note: for bicomps, first and last arcs of all external face vertices
        //       indicate the edges that hold them to the external face
        //       But _JoinBicomps() has already occurred, so cut vertices
        //       will have external face edges other than the first and last arcs
        //       Hence we need this more sophisticated traversal method
        eTwin = gp_GetTwinArc(theGraph, e);

        // Now we get the next arc in rotation order as the new arc out to the
        // vertex after nextVertex.  This sets us up for the next iteration.
        // Note: We cannot simply follow the chain of nextVertex first arcs
        //       as we started out doing at the top of this method.  This is
        //       because we are no longer dealing with bicomps only.
        //       Since _JoinBicomps() has already been invoked, there may now
        //       be cut vertices on the external face whose adjacency lists
        //       contain external face arcs in positions other than the first and
        //       and last arcs.  We will visit those vertices multiple times,
        //       which is OK (just that we have to explain why we're calculating
        //       jout in this way).
        e = gp_GetNextArcCircular(theGraph, eTwin);

        // Now things get really interesting.  The DFS root (startVertex) may
        // itself be a cut vertex to which multiple bicomps have been joined.
        // So we cannot simply stop when the external face walk gets back to
        // startVertex.  We must actually get back to startVertex using its
        // last arc.  This ensures that we've looped down into all the DFS
        // subtrees rooted at startVertex and walked their external faces.

        // Since we started the whole external face walk with the first arc
        // of startVertex, we need to proceed until we reenter startVertex
        // using its last arc.

    } while (eTwin != gp_GetLastArc(theGraph, startVertex));
}
Exemple #12
0
int _AssignColorToVertex(ColorVerticesContext *context, graphP theGraph, int v)
{
	int J, w, color;

	// Run the neighbor list of v and flag all the colors in use
    J = gp_GetFirstArc(theGraph, v);
    while (gp_IsArc(theGraph, J))
    {
         w = theGraph->G[J].v;
         context->colorDetector[context->color[w]] = 1;

         J = gp_GetNextArc(theGraph, J);
    }

    // Find the least numbered unused color and assign it to v
    // Note that this loop never runs more than deg(v) steps
    for (color = 0; color < theGraph->N; color++)
    {
        if (context->colorDetector[color] == 0)
        {
        	context->color[v] = color;
        	if (context->highestColorUsed < color)
        		context->highestColorUsed = color;
        	break;
        }
    }

    if (context->color[v] < 0)
    	return NOTOK;

    // Run the neighbor list of v and unflag all the colors in use
    J = gp_GetFirstArc(theGraph, v);
    while (gp_IsArc(theGraph, J))
    {
         w = theGraph->G[J].v;
         context->colorDetector[context->color[w]] = 0;

         J = gp_GetNextArc(theGraph, J);
    }

	return OK;
}
void _MarkPath(graphP theGraph, int e)
{
int  eTwin, nextVertex;

     nextVertex = gp_GetNeighbor(theGraph, e);
     // while nextVertex is strictly degree 2
     while (gp_IsArc(gp_GetFirstArc(theGraph, nextVertex)) &&
    		gp_IsArc(gp_GetLastArc(theGraph, nextVertex)) &&
    		gp_GetNextArc(theGraph, gp_GetFirstArc(theGraph, nextVertex)) == gp_GetLastArc(theGraph, nextVertex))
     {
         gp_SetVertexVisited(theGraph, nextVertex);

         eTwin = gp_GetTwinArc(theGraph, e);
         e = gp_GetFirstArc(theGraph, nextVertex);
         if (e == eTwin)
             e = gp_GetLastArc(theGraph, nextVertex);

         nextVertex = gp_GetNeighbor(theGraph, e);
     }
}
int  _TryPath(graphP theGraph, int e, int V)
{
int  eTwin, nextVertex;

     nextVertex = gp_GetNeighbor(theGraph, e);

     // while nextVertex is strictly degree 2
     while (gp_IsArc(gp_GetFirstArc(theGraph, nextVertex)) &&
    		gp_IsArc(gp_GetLastArc(theGraph, nextVertex)) &&
    		gp_GetNextArc(theGraph, gp_GetFirstArc(theGraph, nextVertex)) == gp_GetLastArc(theGraph, nextVertex))
     {
    	 eTwin = gp_GetTwinArc(theGraph, e);
         e = gp_GetFirstArc(theGraph, nextVertex);
         if (e == eTwin)
             e = gp_GetLastArc(theGraph, nextVertex);

         nextVertex = gp_GetNeighbor(theGraph, e);
     }

     return nextVertex == V ? TRUE : FALSE;
}
int  _TestPath(graphP theGraph, int U, int V)
{
	 int  e = gp_GetFirstArc(theGraph, U);

     while (gp_IsArc(e))
     {
         if (_TryPath(theGraph, e, V) == OK)
         {
             _MarkPath(theGraph, e);
             return TRUE;
         }

         e = gp_GetNextArc(theGraph, e);
     }

     return FALSE;
 }
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);
    }
}
Exemple #17
0
int  _WriteAdjMatrix(graphP theGraph, FILE *Outfile)
{
int  I, J, K;
char *Row = NULL;

     if (theGraph != NULL)
         Row = (char *) malloc((theGraph->N+1)*sizeof(char));

     if (Row==NULL || theGraph==NULL || Outfile==NULL)
     {
         if (Row != NULL) free(Row);
         return NOTOK;
     }

     fprintf(Outfile, "%d\n", theGraph->N);
     for (I = 0; I < theGraph->N; I++)
     {
          for (K = 0; K <= I; K++)
               Row[K] = ' ';
          for (K = I+1; K < theGraph->N; K++)
               Row[K] = '0';

          J = gp_GetFirstArc(theGraph, I);
          while (gp_IsArc(theGraph, J))
          {
        	  if (gp_GetDirection(theGraph, J, EDGEFLAG_DIRECTION_INONLY))
        		  return NOTOK;

              if (theGraph->G[J].v > I)
                  Row[theGraph->G[J].v] = '1';

              J = gp_GetNextArc(theGraph, J);
          }

          Row[theGraph->N] = '\0';
          fprintf(Outfile, "%s\n", Row);
     }

     free(Row);
     return OK;
}
Exemple #18
0
int _ComputeVertexRanges(DrawPlanarContext *context)
{
graphP theEmbedding = context->theGraph;
int I, J, min, max;

    for (I = 0; I < theEmbedding->N; I++)
    {
        min = theEmbedding->M + 1;
        max = -1;

        // Iterate the edges, except in the isolated vertex case we just
        // set the min and max to 1 since there no edges controlling where
        // it gets drawn.
        J = gp_GetFirstArc(theEmbedding, I);
        if (!gp_IsArc(theEmbedding, J))
        {
        	min = max = 0;
        }
        else
        {
            while (gp_IsArc(theEmbedding, J))
            {
                if (min > context->G[J].pos)
                    min = context->G[J].pos;

                if (max < context->G[J].pos)
                    max = context->G[J].pos;

                J = gp_GetNextArc(theEmbedding, J);
            }
        }

        context->G[I].start = min;
        context->G[I].end = max;
    }

    return OK;
}
Exemple #19
0
int  _DeleteUnmarkedVerticesAndEdges(graphP theGraph)
{
int  I, J, fwdArc, descendant;

     /* All of the forward and back arcs of all of the edge records
        were removed from the adjacency lists in the planarity algorithm
        preprocessing.  We now put them back into the adjacency lists
        (and we do not mark them), so they can be properly deleted below. */

     for (I = 0; I < theGraph->N; I++)
     {
         while (theGraph->V[I].fwdArcList != NIL)
         {
             fwdArc = theGraph->V[I].fwdArcList;
             descendant = theGraph->G[fwdArc].v;
             _AddBackEdge(theGraph, I, descendant);
         }
     }

     /* Now we delete all unmarked edges.  We don't delete vertices
        from the embedding, but the ones we should delete will become
        degree zero. */

     for (I = 0; I < theGraph->N; I++)
     {
          J = gp_GetFirstArc(theGraph, I);
          while (gp_IsArc(theGraph, J))
          {
                if (theGraph->G[J].visited)
                     J = gp_GetNextArc(theGraph, J);
                else J = gp_DeleteEdge(theGraph, J, 0);
          }
     }

     return OK;
}
Exemple #20
0
int  _WriteDebugInfo(graphP theGraph, FILE *Outfile)
{
int I, J, Gsize;

     if (theGraph==NULL || Outfile==NULL) return NOTOK;

     /* Print parent copy vertices and their adjacency lists */

     fprintf(Outfile, "DEBUG N=%d M=%d\n", theGraph->N, theGraph->M);
     for (I=0; I < theGraph->N; I++)
     {
          fprintf(Outfile, "%d(P=%d,lA=%d,LowPt=%d,v=%d):",
                             I, theGraph->V[I].DFSParent,
                                theGraph->V[I].leastAncestor,
                                theGraph->V[I].Lowpoint,
                                theGraph->G[I].v);

          J = gp_GetFirstArc(theGraph, I);
          while (gp_IsArc(theGraph, J))
          {
              fprintf(Outfile, " %d(J=%d)", theGraph->G[J].v, J);
              J = gp_GetNextArc(theGraph, J);
          }

          fprintf(Outfile, " %d\n", NIL);
     }

     /* Print any root copy vertices and their adjacency lists */

     for (I = theGraph->N; I < 2*theGraph->N; I++)
     {
          if (theGraph->G[I].v == NIL)
              continue;

          fprintf(Outfile, "%d(copy of=%d, DFS child=%d):",
                           I, theGraph->G[I].v, I-theGraph->N);

          J = gp_GetFirstArc(theGraph, I);
          while (gp_IsArc(theGraph, J))
          {
              fprintf(Outfile, " %d(J=%d)", theGraph->G[J].v, J);
              J = gp_GetNextArc(theGraph, J);
          }

          fprintf(Outfile, " %d\n", NIL);
     }

     /* Print information about vertices and root copy (virtual) vertices */
     fprintf(Outfile, "\nVERTEX INFORMATION\n");
     for (I=0; I < 2*theGraph->N; I++)
     {
         if (theGraph->G[I].v == NIL)
             continue;

         fprintf(Outfile, "V[%3d] v=%3d, type=%c, first arc=%3d, last arc=%3d\n",
                          I,
                          theGraph->G[I].v,
                          theGraph->G[I].type,
                          gp_GetFirstArc(theGraph, I),
                          gp_GetLastArc(theGraph, I));
     }

     /* Print information about edges */

     fprintf(Outfile, "\nEDGE INFORMATION\n");
     Gsize = theGraph->edgeOffset + theGraph->arcCapacity;
     for (J=theGraph->edgeOffset; J < Gsize; J++)
     {
          if (theGraph->G[J].v == NIL)
              continue;

          fprintf(Outfile, "E[%3d] v=%3d, type=%c, next arc=%3d, prev arc=%3d\n",
                           J,
                           theGraph->G[J].v,
                           theGraph->G[J].type,
                           gp_GetNextArc(theGraph, J),
                           gp_GetPrevArc(theGraph, J));
     }

     return OK;
}
Exemple #21
0
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 _TestForK23GraphObstruction(graphP theGraph, int *degrees, int *imageVerts)
{
int  v, e, imageVertPos;

     // This function operates over the imageVerts results produced by
     // getImageVertices, which only finds vertices of degree 3 or higher.
     // So, for a K2,3, there must be exactly two degree 3 vertices and
     // no degree 4 vertices.
     if (degrees[3] != 2)
         return FALSE;

     // For K_{2,3}, the three vertices of degree 2 were not
     // detected as image vertices because degree 2 vertices
     // are indistinguishable from the internal path vertices
     // between the image vertices.  So, here we acknowledge
     // that more image vertices need to be selected.
     imageVertPos = 2;

     // Assign the remaining three image vertices to be the
     // neighbors of the first degree 3 image vertex.
     // Ensure that each is distinct from the second
     // degree 3 image vertex. This must be the case because
     // the two degree 3 image vertices are in the same partition
     // and hence must not be adjacent.

     e = gp_GetFirstArc(theGraph, imageVerts[0]);
     while (gp_IsArc(e))
     {
         imageVerts[imageVertPos] = gp_GetNeighbor(theGraph, e);
         if (imageVerts[imageVertPos] == imageVerts[1])
             return FALSE;
         imageVertPos++;
         e = gp_GetNextArc(theGraph, e);
     }

     /* The paths from imageVerts[0] to each of the new degree 2
          image vertices are the edges we just traversed.
          Now test the paths between each of the degree 2 image
          vertices and imageVerts[1]. */

     _ClearVertexVisitedFlags(theGraph, FALSE);

     for (imageVertPos=2; imageVertPos<5; imageVertPos++)
     {
          if (_TestPath(theGraph, imageVerts[imageVertPos],
                                  imageVerts[1]) != TRUE)
              return FALSE;

          gp_SetVertexVisited(theGraph, imageVerts[imageVertPos]);
     }

     for (v = gp_GetFirstVertex(theGraph); gp_VertexInRange(theGraph, v); v++)
          if (gp_GetVertexVisited(theGraph, v))
              degrees[2]--;

     /* If every degree 2 vertex is used in a path between the
          two degree 3 image vertices, then there are no extra
          pieces of the graph in theGraph.  Specifically, the
          prior tests identify a K_{2,3} and ensure that nothing
          else could exist in the graph... except extra degree 2
          vertices joined in a cycle. We return NOTOK in that case. */

     return degrees[2] == 0 ? TRUE : FALSE;
}
int  _TestSubgraph(graphP theSubgraph, graphP theGraph)
{
int v, e, degreeCount;
int Result = TRUE;
int invokeSortOnGraph = FALSE;
int invokeSortOnSubgraph = FALSE;

    // If the graph is not sorted by DFI, but the alleged subgraph is,
    // then "unsort" the alleged subgraph so both have the same vertex order
    if (!(theGraph->internalFlags & FLAGS_SORTEDBYDFI) &&
         (theSubgraph->internalFlags & FLAGS_SORTEDBYDFI))
    {
        invokeSortOnSubgraph = TRUE;
        gp_SortVertices(theSubgraph);
    }

    // If the graph is not sorted by DFI, but the alleged subgraph is,
    // then "unsort" the alleged subgraph so both have the same vertex order
    if (!(theSubgraph->internalFlags & FLAGS_SORTEDBYDFI) &&
         (theGraph->internalFlags & FLAGS_SORTEDBYDFI))
    {
        invokeSortOnGraph = TRUE;
        gp_SortVertices(theGraph);
    }

/* We clear all visitation flags */

     _ClearVertexVisitedFlags(theGraph, FALSE);

/* For each vertex... */
     for (v = gp_GetFirstVertex(theSubgraph), degreeCount = 0; gp_VertexInRange(theSubgraph, v); v++)
     {
          /* For each neighbor w in the adjacency list of vertex v in the
                subgraph, set the visited flag in w in the graph */

          e = gp_GetFirstArc(theSubgraph, v);
          while (gp_IsArc(e))
          {
        	  if (gp_IsNotVertex(gp_GetNeighbor(theSubgraph, e)))
        	  {
        		  Result = FALSE;
        		  break;
        	  }
        	  degreeCount++;
        	  gp_SetVertexVisited(theGraph, gp_GetNeighbor(theSubgraph, e));
              e = gp_GetNextArc(theSubgraph, e);
          }

          if (Result != TRUE)
        	  break;

          /* For each neighbor w in the adjacency list of vertex v in the graph,
                clear the visited flag in w in the graph */

          e = gp_GetFirstArc(theGraph, v);
          while (gp_IsArc(e))
          {
        	  if (gp_IsNotVertex(gp_GetNeighbor(theGraph, e)))
        	  {
        		  Result = FALSE;
        		  break;
        	  }
        	  gp_ClearVertexVisited(theGraph, gp_GetNeighbor(theGraph, e));
              e = gp_GetNextArc(theGraph, e);
          }

          if (Result != TRUE)
        	  break;

          /* For each neighbor w in the adjacency list of vertex v in the subgraph,
             ensure that the visited flag in w was cleared (otherwise, the "subgraph"
             would incorrectly contain an adjacency not contained in the ("super") graph) */

          e = gp_GetFirstArc(theSubgraph, v);
          while (gp_IsArc(e))
          {
              if (gp_GetVertexVisited(theGraph, gp_GetNeighbor(theSubgraph, e)))
              {
            	  Result = FALSE;
            	  break;
              }
              e = gp_GetNextArc(theSubgraph, e);
          }

          if (Result != TRUE)
        	  break;
     }

    // Restore the DFI sort order of either graph if it had to be reordered at the start
    if (invokeSortOnSubgraph)
        gp_SortVertices(theSubgraph);
    if (invokeSortOnGraph)
        gp_SortVertices(theGraph);

    // Assuming theSubgraph is a subgraph, we also do an extra integrity check to ensure
    // proper edge array utilization
    if (Result == TRUE)
    {
    	// If the edge count is wrong, we fail the subgraph test in a way that invokes
    	// the name NOTOK so that in debug mode there is more trace on the failure.
    	if (degreeCount != 2*theSubgraph->M)
    		Result = NOTOK == FALSE ? NOTOK : FALSE;
    }

     return Result;
}
Exemple #24
0
int  _MarkZtoRPath(graphP theGraph)
{
int ZPrevArc, ZNextArc, Z, R, Px, Py;

/* Initialize */

    R = theGraph->IC.r;
    Px = theGraph->IC.px;
    Py = theGraph->IC.py;
    theGraph->IC.z = NIL;

/* Begin at Px and search its adjacency list for the edge leading to
   the first internal vertex of the X-Y path. */

    Z = Px;
    ZNextArc = gp_GetLastArc(theGraph, Z);
    while (ZNextArc != gp_GetFirstArc(theGraph, Z))
    {
       if (theGraph->G[ZNextArc].visited) break;

       ZNextArc = gp_GetPrevArc(theGraph, ZNextArc);
    }

    if (!theGraph->G[ZNextArc].visited)
        return NOTOK;

/* For each internal vertex Z, determine whether it has a path to root. */

    while (theGraph->G[ZNextArc].visited)
    {
        ZPrevArc = gp_GetTwinArc(theGraph, ZNextArc);
        ZNextArc = gp_GetPrevArcCircular(theGraph, ZPrevArc);
    }

    ZPrevArc = gp_GetTwinArc(theGraph, ZNextArc);
    Z = theGraph->G[ZPrevArc].v;

/* If there is no Z to R path, return */

    if (Z == Py) return OK;

/* Otherwise, store Z in the isolation context */

    theGraph->IC.z = Z;

/* Walk the proper face starting with (Z, ZNextArc) until we reach R, marking
        the vertices and edges encountered along the way, then Return OK. */

    while (Z != R)
    {
        /* If we ever encounter a non-internal vertex (other than the root R),
                then corruption has occured, so we return NOTOK */

        if (theGraph->G[Z].type != TYPE_UNKNOWN)
            return NOTOK;

        /* Go to the next vertex indicated by ZNextArc */

        Z = theGraph->G[ZNextArc].v;

        /* Mark the next vertex and the edge leading to it as visited. */

        theGraph->G[ZNextArc].visited = 1;
        theGraph->G[ZPrevArc].visited = 1;
        theGraph->G[Z].visited = 1;

        /* Go to the next edge in the proper face */

        ZNextArc = gp_GetPrevArcCircular(theGraph, ZPrevArc);
        ZPrevArc = gp_GetTwinArc(theGraph, ZNextArc);
    }

/* Found Z to R path, so indicate as much to caller */

    return OK;
}
Exemple #25
0
int _ComputeEdgePositions(DrawPlanarContext *context)
{
graphP theEmbedding = context->theGraph;
int *vertexOrder = NULL;
listCollectionP edgeList = NULL;
int edgeListHead, edgeListInsertPoint;
int I, J, Jcur, e, v, vpos;
int eIndex, JTwin;

	gp_LogLine("\ngraphDrawPlanar.c/_ComputeEdgePositions() start");

    // Sort the vertices by vertical position (in linear time)

    if ((vertexOrder = (int *) malloc(theEmbedding->N * sizeof(int))) == NULL)
        return NOTOK;

    for (I = 0; I < theEmbedding->N; I++)
        vertexOrder[context->G[I].pos] = I;

    // Allocate the edge list of size M.
    //    This is an array of (prev, next) pointers.
    //    An edge at position X corresponds to the edge
    //    at position X in the graph structure, which is
    //    represented by a pair of adjacent graph nodes
    //    starting at index 2N + 2X.

    if (theEmbedding->M > 0 && (edgeList = LCNew(theEmbedding->M)) == NULL)
    {
        free(vertexOrder);
        return NOTOK;
    }

    edgeListHead = NIL;

    // Each vertex starts out with a NIL generator edge.

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

    // Perform the vertical sweep of the combinatorial embedding, using
    // the vertex ordering to guide the sweep.
    // For each vertex, each edge leading to a vertex with a higher number in
    // the vertex order is recorded as the "generator edge", or the edge of
    // first discovery of that higher numbered vertex, unless the vertex already has
    // a recorded generator edge
    for (vpos=0; vpos < theEmbedding->N; vpos++)
    {
        // Get the vertex associated with the position
        v = vertexOrder[vpos];
        gp_LogLine(gp_MakeLogStr3("Processing vertex %d with DFI=%d at position=%d",
    				 theEmbedding->G[v].v, v, vpos));

        // The DFS tree root of a connected component is always the least
        // number vertex in the vertex ordering.  We have to give it a
        // false generator edge so that it is still "visited" and then
        // all of its edges are generators for its neighbor vertices because
        // they all have greater numbers in the vertex order.
        if (theEmbedding->V[v].DFSParent == NIL)
        {
            // False generator edge, so the vertex is distinguishable from
            // a vertex with no generator edge when its neighbors are visited
            // This way, an edge from a neighbor won't get recorded as the
            // generator edge of the DFS tree root.
            theEmbedding->G[v].visited = 1;

            // Now we traverse the adjacency list of the DFS tree root and
            // record each edge as the generator edge of the neighbors
            J = gp_GetFirstArc(theEmbedding, v);
            while (gp_IsArc(theGraph, J))
            {
                e = (J - theEmbedding->edgeOffset) / 2;

                edgeListHead = LCAppend(edgeList, edgeListHead, e);
                gp_LogLine(gp_MakeLogStr2("Append generator edge (%d, %d) to edgeList",
                		theEmbedding->G[v].v, theEmbedding->G[theEmbedding->G[J].v].v));

                // Set the generator edge for the root's neighbor
                theEmbedding->G[theEmbedding->G[J].v].visited = J;

                // Go to the next node of the root's adj list
                J = gp_GetNextArc(theEmbedding, J);
            }
        }

        // Else, if we are not on a DFS tree root...
        else
        {
            // Get the generator edge of the vertex
            if ((JTwin = theEmbedding->G[v].visited) == NIL)
                return NOTOK;
            J = gp_GetTwinArc(theEmbedding, JTwin);

            // Traverse the edges of the vertex, starting
            // from the generator edge and going counterclockwise...

            e = (J - theEmbedding->edgeOffset) / 2;
            edgeListInsertPoint = e;

            Jcur = gp_GetNextArcCircular(theEmbedding, J);

            while (Jcur != J)
            {
                // If the neighboring vertex's position is greater
                // than the current vertex (meaning it is lower in the
                // diagram), then add that edge to the edge order.

                if (context->G[theEmbedding->G[Jcur].v].pos > vpos)
                {
                    e = (Jcur - theEmbedding->edgeOffset) / 2;
                    LCInsertAfter(edgeList, edgeListInsertPoint, e);

                    gp_LogLine(gp_MakeLogStr4("Insert (%d, %d) after (%d, %d)",
                    		theEmbedding->G[v].v,
                    		theEmbedding->G[theEmbedding->G[Jcur].v].v,
                    		theEmbedding->G[theEmbedding->G[gp_GetTwinArc(theEmbedding, J)].v].v,
                    		theEmbedding->G[theEmbedding->G[J].v].v));

                    edgeListInsertPoint = e;

                    // If the vertex does not yet have a generator edge, then set it.
                    if (theEmbedding->G[theEmbedding->G[Jcur].v].visited == NIL)
                    {
                        theEmbedding->G[theEmbedding->G[Jcur].v].visited = Jcur;
                        gp_LogLine(gp_MakeLogStr2("Generator edge (%d, %d)",
                        		theEmbedding->G[theEmbedding->G[gp_GetTwinArc(theEmbedding, J)].v].v,
                        		theEmbedding->G[theEmbedding->G[Jcur].v].v));
                    }
                }

                // Go to the next node in v's adjacency list
                Jcur = gp_GetNextArcCircular(theEmbedding, Jcur);
            }
        }

#ifdef LOGGING
        _LogEdgeList(theEmbedding, edgeList, edgeListHead);
#endif
    }

    // Now iterate through the edgeList and assign positions to the edges.
    eIndex = 0;
    e = edgeListHead;
    while (e != NIL)
    {
        J = theEmbedding->edgeOffset + 2*e;
        JTwin = gp_GetTwinArc(theEmbedding, J);

        context->G[J].pos = context->G[JTwin].pos = eIndex;

        eIndex++;

        e = LCGetNext(edgeList, edgeListHead, e);
    }

    // Clean up and return
    LCFree(&edgeList);
    free(vertexOrder);

	gp_LogLine("graphDrawPlanar.c/_ComputeEdgePositions() end\n");

    return OK;
}
Exemple #26
0
int _ComputeVertexPositionsInComponent(DrawPlanarContext *context, int root, int *pIndex)
{
graphP theEmbedding = context->theGraph;
listCollectionP theOrder = LCNew(theEmbedding->N);
int W, P, C, V, J;

    if (theOrder == NULL)
        return NOTOK;

    // Determine the vertex order using a depth first search with
    // pre-order visitation.

    sp_ClearStack(theEmbedding->theStack);
    sp_Push(theEmbedding->theStack, root);
    while (!sp_IsEmpty(theEmbedding->theStack))
    {
        sp_Pop(theEmbedding->theStack, W);

        P = theEmbedding->V[W].DFSParent;
        V = context->V[W].ancestor;
        C = context->V[W].ancestorChild;

        // For the special case that we just popped the DFS tree root,
        // we simply add the root to its own position.
        if (P == NIL)
        {
            // Put the DFS root in the list by itself
            LCAppend(theOrder, NIL, W);
            // The children of the DFS root have the root as their
            // ancestorChild and 'beyond' as the drawingFlag, so this
            // causes the root's children to be placed below the root
            context->V[W].drawingFlag = DRAWINGFLAG_BELOW;
        }

        // Determine vertex W position relative to P
        else
        {
            // An unresolved tie is an error
            if (context->V[W].drawingFlag == DRAWINGFLAG_TIE)
                return NOTOK;

            // If C below V, then P below V, so interpret W between
            // P and V as W above P, and interpret W beyond P relative
            // to V as W below P.
            if (context->V[C].drawingFlag == DRAWINGFLAG_BELOW)
            {
                if (context->V[W].drawingFlag == DRAWINGFLAG_BETWEEN)
                    context->V[W].drawingFlag = DRAWINGFLAG_ABOVE;
                else
                    context->V[W].drawingFlag = DRAWINGFLAG_BELOW;
            }

            // If C above V, then P above V, so interpret W between
            // P and V as W below P, and interpret W beyond P relative
            // to V as W above P.
            else
            {
                if (context->V[W].drawingFlag == DRAWINGFLAG_BETWEEN)
                    context->V[W].drawingFlag = DRAWINGFLAG_BELOW;
                else
                    context->V[W].drawingFlag = DRAWINGFLAG_ABOVE;
            }

            if (context->V[W].drawingFlag == DRAWINGFLAG_BELOW)
                LCInsertAfter(theOrder, P, W);
            else
                LCInsertBefore(theOrder, P, W);
        }

        // Push DFS children
        J = gp_GetFirstArc(theEmbedding, W);
        while (gp_IsArc(theEmbedding, J))
        {
            if (theEmbedding->G[J].type == EDGE_DFSCHILD)
                sp_Push(theEmbedding->theStack, theEmbedding->G[J].v);

            J = gp_GetNextArc(theEmbedding, J);
        }
    }

    // Use the order to assign vertical positions
    V = root;
    while (V != NIL)
    {
        context->G[V].pos = *pIndex;
        (*pIndex)++;
        V = LCGetNext(theOrder, root, V);
    }

    // Clean up and return

    LCFree(&theOrder);
    return OK;
}
Exemple #27
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;
}
Exemple #28
0
int  gp_LowpointAndLeastAncestor(graphP theGraph)
{
stackP theStack = theGraph->theStack;
int I, u, uneighbor, J, L, leastAncestor;
int totalVisited = 0;

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

     sp_ClearStack(theStack);

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

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

     for (I=0; I < theGraph->N && totalVisited < theGraph->N; I++)
     {
          if (theGraph->G[I].visited)
              continue;

          sp_Push(theStack, I);
          while (sp_NonEmpty(theStack))
          {
              sp_Pop(theStack, u);
              if (!theGraph->G[u].visited)
              {
                  /* Mark u as visited, then push it back on the stack */
                  theGraph->G[u].visited = 1;
                  totalVisited++;
                  sp_Push(theStack, u);

                  /* Push DFS children */
                  J = gp_GetFirstArc(theGraph, u);
                  while (gp_IsArc(theGraph, J))
                  {
                      if (theGraph->G[J].type == EDGE_DFSCHILD)
                      {
                          sp_Push(theStack, theGraph->G[J].v);
                      }
                      else break;

                      J = gp_GetNextArc(theGraph, J);
                  }
              }
              else
              {
                  /* Start with high values because we are doing a min function */
                  L = leastAncestor = u;

                  /* Compute L and leastAncestor */
                  J = gp_GetFirstArc(theGraph, u);
                  while (gp_IsArc(theGraph, J))
                  {
                      uneighbor = theGraph->G[J].v;
                      if (theGraph->G[J].type == EDGE_DFSCHILD)
                      {
                          if (L > theGraph->V[uneighbor].Lowpoint)
                              L = theGraph->V[uneighbor].Lowpoint;
                      }
                      else if (theGraph->G[J].type == EDGE_BACK)
                      {
                          if (leastAncestor > uneighbor)
                              leastAncestor = uneighbor;
                      }
                      else if (theGraph->G[J].type == EDGE_FORWARD)
                          break;

                      J = gp_GetNextArc(theGraph, J);
                  }

                  /* Assign leastAncestor and Lowpoint to the vertex */
                  theGraph->V[u].leastAncestor = leastAncestor;
                  theGraph->V[u].Lowpoint = leastAncestor < L ? leastAncestor : L;
              }
         }
     }

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

     return OK;
}
int  _K33Search_MarkDFSPath(graphP theGraph, int ancestor, int descendant)
{
int  J, parent, N;

     N = theGraph->N;

     /* If we are marking from a root vertex upward, then go up to the parent
        copy before starting the loop */

     if (descendant >= N)
         descendant = theGraph->V[descendant-N].DFSParent;

     /* Mark the lowest vertex (the one with the highest number). */

     theGraph->G[descendant].visited = 1;

     /* Mark all ancestors of the lowest vertex, and the edges used to reach
        them, up to the given ancestor vertex. */

     while (descendant != ancestor)
     {
          if (descendant == NIL)
              return NOTOK;

          /* If we are at a bicomp root, then ascend to its parent copy and
                mark it as visited. */

          if (descendant >= N)
          {
              parent = theGraph->V[descendant-N].DFSParent;
          }

          /* If we are on a regular, non-virtual vertex then get the edge to
                the parent, mark the edge, then fall through to the code
                that marks the parent vertex. */
          else
          {

              /* Scan the edges for the one marked as the DFS parent */

              parent = NIL;
              J = gp_GetFirstArc(theGraph, descendant);
              while (gp_IsArc(theGraph, J))
              {
                  if (theGraph->G[J].type == EDGE_DFSPARENT)
                  {
                      parent = theGraph->G[J].v;
                      break;
                  }
                  J = gp_GetNextArc(theGraph, J);
              }

              /* If the desired edge was not found, then the data structure is
                    corrupt, so bail out. */

              if (parent == NIL)
                  return NOTOK;

              /* Mark the edge */

              theGraph->G[J].visited = 1;
              theGraph->G[gp_GetTwinArc(theGraph, J)].visited = 1;
          }

          /* Mark the parent, then hop to the parent and reiterate */

          theGraph->G[parent].visited = 1;
          descendant = parent;
     }

     return OK;
}