graphIO.c

Go to the documentation of this file.
00001 /* Copyright (c) 2005 by John M. Boyer, All Rights Reserved.  Please see
00002  * License.txt for use and redistribution license. */
00003 /* Copyright (c) 1997-2003 by John M. Boyer, All Rights Reserved.
00004         This code may not be reproduced or disseminated in whole or in part 
00005         without the written permission of the author. */
00006 
00007 #define GRAPHIO_C
00008 
00009 #include <stdlib.h>
00010 #include <string.h>
00011 
00012 #include "graph_boyer.h"
00013 
00014 /* Private functions (exported to system) */
00015 int _ReadAdjMatrix (graphP theGraph,
00016                     FILE * Infile);
00017 int _ReadAdjList (graphP theGraph,
00018                   FILE * Infile);
00019 int _WriteAdjList (graphP theGraph,
00020                    FILE * Outfile);
00021 int _WriteAdjMatrix (graphP theGraph,
00022                      FILE * Outfile);
00023 int _WriteDebugInfo (graphP theGraph,
00024                      FILE * Outfile);
00025 
00026 /********************************************************************
00027  _ReadAdjMatrix()
00028  This function reads the undirected graph in upper triangular matrix format.
00029  Though O(N^2) time is required, this routine is useful during
00030  reliability testing due to the wealth of graph generating software
00031  that uses this format for output.
00032  Returns: OK, NOTOK on internal error, NONPLANAR if too many edges
00033  ********************************************************************/
00034 int _ReadAdjMatrix (graphP theGraph,
00035                     FILE * Infile)
00036 {
00037   int N,
00038     I,
00039     J,
00040     Flag,
00041     ErrorCode;
00042   if (Infile == NULL)
00043     return NOTOK;
00044   fscanf (Infile, " %d ", &N);
00045   if (gp_InitGraph (theGraph, N) != OK)
00046     return NOTOK;
00047   for (I = 0, ErrorCode = OK; I < N - 1 && ErrorCode == OK; I++)
00048 
00049   {
00050     theGraph->G[I].v = I;
00051     for (J = I + 1; J < N; J++)
00052 
00053     {
00054       fscanf (Infile, " %1d", &Flag);
00055       if (Flag)
00056 
00057       {
00058         ErrorCode = gp_AddEdge (theGraph, I, 0, J, 0);
00059         if (ErrorCode != OK)
00060           break;
00061       }
00062     }
00063   }
00064   return ErrorCode;
00065 }
00066 
00067 
00068 /********************************************************************
00069  _ReadAdjList()
00070  This function reads the graph in adjacency list format.
00071 
00072  The file format is
00073  On the first line    : N= number of vertices
00074  On N subsequent lines: #: a b c ... -1
00075  where # is a vertex number and a, b, c, ... are its neighbors.
00076 
00077  NOTE:  The vertex number is skipped; the vertices are expected to be
00078         in sorted order in the file.  The vertex number is for file
00079         documentation only.
00080 
00081  NOTE:  This reader will not read all edges in the same order as
00082         they exist in your input file.  When a low numbered vertex u
00083         is being read, an edge to a higher numbered vertex v causes
00084         this reader to add both (u,v) and (v,u) to the graph.  When
00085         v is processed, the edge to u is simply ignored.  This ensures
00086         that the graph from this reader is undirected, but it is an
00087         error to try feeding a digraph to this reader because arcs
00088         from high to low numbered vertices are ignored even if the
00089         arc from low to high numbered vertex was absent.
00090 
00091  Returns: OK, NOTOK on internal error, NONPLANAR if too many edges
00092  ********************************************************************/
00093 int _ReadAdjList (graphP theGraph,
00094                   FILE * Infile)
00095 {
00096   int N,
00097     I,
00098     J,
00099     ErrorCode;
00100   if (Infile == NULL)
00101     return NOTOK;
00102   fgetc (Infile);               /* Skip the N= */
00103   fgetc (Infile);
00104   fscanf (Infile, " %d ", &N);  /* Read N */
00105   if (gp_InitGraph (theGraph, N) != OK)
00106     return NOTOK;
00107   for (I = 0, ErrorCode = OK; I < N && ErrorCode == OK; I++)
00108 
00109   {
00110     theGraph->G[I].v = I;
00111     fscanf (Infile, "%*d");     /* Skip vertex # and colon */
00112     fgetc (Infile);
00113     while (1)                   /* Read Adj List */
00114 
00115     {
00116       fscanf (Infile, " %d ", &J);
00117       if (J < 0)
00118         break;                  /* If NIL, then we are done */
00119       if (J >= N)
00120         ErrorCode = NOTOK;
00121 
00122       else if (I > J)
00123         ErrorCode = OK;
00124 
00125       else
00126         ErrorCode = gp_AddEdge (theGraph, I, 1, J, 1);
00127       if (ErrorCode != OK)
00128         break;
00129     }
00130   }
00131   return ErrorCode;
00132 }
00133 
00134 
00135 /********************************************************************
00136  _ReadLEDAGraph()
00137  Reads the edge list from a LEDA file containing a simple undirected graph.
00138  ********************************************************************/
00139 int _ReadLEDAGraph (graphP theGraph,
00140                     FILE * Infile)
00141 {
00142   char Line[256];
00143   int N,
00144     I,
00145     M,
00146     J,
00147     u,
00148     v;
00149 
00150   /* Skip the lines that say LEDA.GRAPH and give the node and edge types */
00151   fgets (Line, 255, Infile);
00152   fgets (Line, 255, Infile);
00153   fgets (Line, 255, Infile);
00154 
00155   /* Read the number of vertices, then skip that many more lines. */
00156   fgets (Line, 255, Infile);
00157   sscanf (Line, " %d", &N);
00158   for (I = 0; I < N; I++)
00159     fgets (Line, 255, Infile);
00160 
00161   /* Initialize the graph */
00162   if (gp_InitGraph (theGraph, N) != OK)
00163     return NOTOK;
00164 
00165   /* Read the number of edges */
00166   fgets (Line, 255, Infile);
00167   sscanf (Line, " %d", &M);
00168 
00169   /* Read and add each edge, omitting duplicates */
00170   for (J = 0; J < M; J++)
00171 
00172   {
00173     fgets (Line, 255, Infile);
00174     sscanf (Line, " %d %d", &u, &v);
00175     if (u != v && !gp_IsNeighbor (theGraph, u - 1, v - 1))
00176 
00177     {
00178       if (gp_AddEdge (theGraph, u - 1, 0, v - 1, 0) != OK)
00179         return NOTOK;
00180     }
00181   }
00182   return OK;
00183 }
00184 
00185 
00186 /********************************************************************
00187  gp_Read()
00188  Opens the given file, determines whether it is in adjacency list or
00189  matrix format based on whether the file start with N or just a number,
00190  calls the appropriate read function, then closes the file and returns
00191  the graph.
00192  Pass "stdin" for the FileName to read from the stdin stream
00193  Returns: OK, NOTOK on internal error, NONPLANAR if too many edges
00194  ********************************************************************/
00195 int gp_Read (graphP theGraph,
00196              char *FileName)
00197 {
00198   FILE *Infile;
00199   char Ch;
00200   int RetVal = NOTOK;
00201   if (strcmp (FileName, "stdin") == OK)
00202     Infile = stdin;
00203 
00204   else if ((Infile = fopen (FileName, READTEXT)) == NULL)
00205     return RetVal;
00206   Ch = (char) fgetc (Infile);
00207   ungetc (Ch, Infile);
00208   if (Ch == 'N')
00209     RetVal = _ReadAdjList (theGraph, Infile);
00210 
00211   else if (Ch == 'L')
00212     RetVal = _ReadLEDAGraph (theGraph, Infile);
00213 
00214   else
00215     RetVal = _ReadAdjMatrix (theGraph, Infile);
00216   if (strcmp (FileName, "stdin") != OK)
00217     fclose (Infile);
00218   return RetVal;
00219 }
00220 
00221 
00222 /********************************************************************
00223  _WriteAdjList()
00224  For each vertex, we write its number, a colon, the list of adjacent vertices,
00225  then a NIL.  The vertices occupy the first N positions of theGraph.  Each
00226  vertex is also the head of a circular list kept by link[0] and link[1].
00227  Aside from the vertex itself, the other elements in the list represent
00228  the edges between the vertex and its neighbors, and these edge records
00229  reside at or above position 2N in theGraph.
00230 
00231  Returns: NOTOK if either param is NULL; OK otherwise (after printing
00232                 adjacency list representation to Outfile).
00233  ********************************************************************/
00234 int _WriteAdjList (graphP theGraph,
00235                    FILE * Outfile)
00236 {
00237   int I,
00238     J;
00239   if (theGraph == NULL || Outfile == NULL)
00240     return NOTOK;
00241   fprintf (Outfile, "N=%d\n", theGraph->N);
00242   for (I = 0; I < theGraph->N; I++)
00243 
00244   {
00245     fprintf (Outfile, "%d:", I);
00246     J = theGraph->G[I].link[1];
00247     while (J >= theGraph->N)
00248 
00249     {
00250       fprintf (Outfile, " %d", theGraph->G[J].v);
00251       J = theGraph->G[J].link[1];
00252     }
00253     fprintf (Outfile, " %d\n", NIL);
00254   }
00255   return OK;
00256 }
00257 
00258 
00259 /********************************************************************
00260  _WriteAdjMatrix()
00261  Outputs upper triangular matrix representation capable of being
00262  read by _ReadAdjMatrix()
00263  ********************************************************************/
00264 int _WriteAdjMatrix (graphP theGraph,
00265                      FILE * Outfile)
00266 {
00267   int I,
00268     J,
00269     K;
00270   char *Row = NULL;
00271   if (theGraph != NULL)
00272     Row = (char *) malloc ((theGraph->N + 1) * sizeof (char));
00273   if (Row == NULL || theGraph == NULL || Outfile == NULL)
00274 
00275   {
00276     if (Row != NULL)
00277       free (Row);
00278     return NOTOK;
00279   }
00280   fprintf (Outfile, "%d\n", theGraph->N);
00281   for (I = 0; I < theGraph->N; I++)
00282 
00283   {
00284     for (K = 0; K <= I; K++)
00285       Row[K] = ' ';
00286     for (K = I + 1; K < theGraph->N; K++)
00287       Row[K] = '0';
00288     J = theGraph->G[I].link[0];
00289     while (J >= theGraph->N)
00290 
00291     {
00292       if (theGraph->G[J].v > I)
00293         Row[theGraph->G[J].v] = '1';
00294       J = theGraph->G[J].link[0];
00295     }
00296     Row[theGraph->N] = '\0';
00297     fprintf (Outfile, "%s\n", Row);
00298   }
00299   free (Row);
00300   return OK;
00301 }
00302 
00303 
00304 /********************************************************************
00305  _WriteDebugInfo()
00306  Writes adjacency list, but also includes the type value of each
00307  edge (e.g. is it DFS child  arc, forward arc or back arc?), and
00308  the L, A and DFSParent of each vertex.
00309  ********************************************************************/
00310 int _WriteDebugInfo (graphP theGraph,
00311                      FILE * Outfile)
00312 {
00313   int I,
00314     J;
00315   if (theGraph == NULL || Outfile == NULL)
00316     return NOTOK;
00317 
00318   /* Print parent copy vertices and their adjacency lists */
00319   fprintf (Outfile, "DEBUG N=%d M=%d\n", theGraph->N, theGraph->M);
00320   for (I = 0; I < theGraph->N; I++)
00321 
00322   {
00323     fprintf (Outfile, "%d(P=%d,lA=%d,LowPt=%d,v=%d):", I,
00324              theGraph->V[I].DFSParent, theGraph->V[I].leastAncestor,
00325              theGraph->V[I].Lowpoint, theGraph->G[I].v);
00326     J = theGraph->G[I].link[0];
00327     while (J >= theGraph->N)
00328 
00329     {
00330       fprintf (Outfile, " %d(J=%d)", theGraph->G[J].v, J);
00331       J = theGraph->G[J].link[0];
00332     }
00333     fprintf (Outfile, " %d\n", NIL);
00334   }
00335 
00336   /* Print any root copy vertices and their adjacency lists */
00337   for (I = theGraph->N; I < 2 * theGraph->N; I++)
00338 
00339   {
00340     if (theGraph->G[I].v == NIL)
00341       continue;
00342     fprintf (Outfile, "%d(copy of=%d, DFS child=%d):", I, theGraph->G[I].v,
00343              I - theGraph->N);
00344     J = theGraph->G[I].link[0];
00345     while (J >= 2 * theGraph->N)
00346 
00347     {
00348       fprintf (Outfile, " %d(J=%d)", theGraph->G[J].v, J);
00349       J = theGraph->G[J].link[0];
00350     }
00351     fprintf (Outfile, " %d\n", NIL);
00352   }
00353 
00354   /* Print all graph node information for vertices (0 to N-1),
00355    * root copy vertices (N to 2N-1), and edges (2N to 8N-1) */
00356   fprintf (Outfile, "\nGRAPH NODES\n");
00357   for (I = 0; I < 8 * theGraph->N; I++)
00358 
00359   {
00360     if (theGraph->G[I].v == NIL)
00361       continue;
00362     fprintf (Outfile, "G[%3d] v=%3d, type=%c, link[0]=%3d, link[1]=%3d\n", I,
00363              theGraph->G[I].v, theGraph->G[I].type, theGraph->G[I].link[0],
00364              theGraph->G[I].link[1]);
00365   }
00366   return OK;
00367 }
00368 
00369 
00370 /********************************************************************
00371  gp_Write()
00372  Writes theGraph into the file.
00373  Pass "stdout" or "stderr" to FileName to write to the corresponding stream
00374  Pass WRITE_ADJLIST, WRITE_ADJMATRIX or WRITE_DEBUGINFO for the Mode
00375  Returns NOTOK on parameter error, OK on success.
00376  ********************************************************************/
00377 int gp_Write (graphP theGraph,
00378               char *FileName,
00379               int Mode)
00380 {
00381   FILE *Outfile;
00382   int RetVal = NOTOK;
00383   if (theGraph == NULL || FileName == NULL)
00384     return NOTOK;
00385   if (strcmp (FileName, "stdout") == OK)
00386     Outfile = stdout;
00387 
00388   else if (strcmp (FileName, "stderr") == OK)
00389     Outfile = stderr;
00390 
00391   else if ((Outfile = fopen (FileName, WRITETEXT)) == NULL)
00392     return NOTOK;
00393   switch (Mode)
00394 
00395   {
00396   case WRITE_ADJLIST:
00397     RetVal = _WriteAdjList (theGraph, Outfile);
00398     break;
00399   case WRITE_ADJMATRIX:
00400     RetVal = _WriteAdjMatrix (theGraph, Outfile);
00401     break;
00402   case WRITE_DEBUGINFO:
00403     RetVal = _WriteDebugInfo (theGraph, Outfile);
00404     break;
00405   }
00406   if (strcmp (FileName, "stdout") == OK || strcmp (FileName, "stderr") == OK)
00407     fflush (Outfile);
00408 
00409   else if (fclose (Outfile) != OK)
00410     RetVal = NOTOK;
00411   return RetVal;
00412 }

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