Main Page   Class Hierarchy   Compound List   File List   Contact   Download   Symbolic Constraints   Examples  

ghc_tree_main.c

00001 #include <stdlib.h>
00002 #include <stdio.h>
00003 #include "graph.h"
00004 
00005 
00006 #define NO_MEM  fprintf(stderr,"Unable to allocate memory\n")
00007 #define LEPS 1e-8
00008 
00009       /* protoype definitions */
00010 
00011 float user_time (); 
00012 BOOL ghc_tree (graph *);                  
00013 
00014 
00015 void print_time (float t)
00016 {
00017   long t_sec, t_hun; 
00018   float t1;
00019 
00020   if (t < 1.0)
00021     printf ("0'%d [s'10ms]\n", (long) (t * 100.0));
00022   else
00023    { t1 = t * 100.0;
00024      t_sec = (long) t;
00025      t_hun = (long) t1 - (long) 100 * t_sec;
00026      printf ("%d'%d [s'10ms]\n", t_sec, t_hun);
00027    }
00028 }
00029 
00030 
00031 BOOL alloc_graph (long n, long m, graph **gr)
00032 {
00033   if ((*gr = (graph *) malloc (sizeof (graph))) == (graph *) 0)
00034     return (FALSE);
00035   if (((*gr)->nodes = (node *) malloc (n * sizeof (node))) 
00036       == (node *) 0)
00037    { free (*gr);
00038      return (FALSE);
00039    }
00040   if (((*gr)->edges = (edge *) malloc (2L * m * sizeof (edge)))
00041       == (edge *) 0)
00042    { free (*gr);
00043      free ((*gr)->nodes);
00044      return (FALSE);
00045    }
00046   return (TRUE);
00047 }
00048 
00049 
00050 void dealloc_graph (graph *gr)
00051 {
00052   free (gr->nodes);
00053   free (gr->edges);
00054   free (gr);
00055 }
00056 
00057 
00058 char skip_comment (FILE *fd)
00059 { 
00060   char any;
00061   char *c;
00062   static char buf[256];
00063 
00064   do { c = fgets (buf, 256, fd);
00065        fscanf (fd, "%c", &any);
00066      } 
00067   while (any == 'c');
00068   return (any);
00069 }
00070 
00071 
00072 graph *get_graph (FILE *fd) 
00073 {
00074   long n, m, m0, i, j, nod1, nod2;
00075   double cap;
00076   node *nptr, *nptr1, *nptr2;
00077   edge *eptr1, *eptr2;
00078   graph *gr;
00079   char inp[4], any;
00080 
00081   /* Scans input file and constructs internal representation
00082      of graph.
00083 
00084      Undirected edges are represented by pairs of edge desrip-
00085      tors associated to incident nodes, the incidence list of 
00086      a node is represented as a one way linked list of edge de-
00087      scriptors each of which contains a pointer to an adjacent
00088      node and a "back" pointer to the descriptor of the other
00089      edge in the pair contained in the incidence list of the
00090      adjacent node. 
00091   */
00092 
00093   fscanf (fd, "%c", &any);
00094   if (any == 'c')
00095     any = skip_comment (fd);
00096   if (any != 'p')
00097    { fprintf (stderr, "Problem line missing in input file\n");
00098      exit (1);
00099    }
00100   fscanf (fd, "%s", inp);  
00101   if (inp[0] != 'g' || inp[1] != 'h' ||
00102       inp[2] != 'c' || inp[3] != 't' )
00103    { fprintf (stderr,
00104               "problem in input file is not Gomory/Gu cut tree\n");
00105      return ((graph *) 0);
00106    }
00107 
00108   fscanf (fd, "%ld", &n);
00109   fscanf (fd, "%ld", &m);
00110 
00111   if (! alloc_graph (n, m, &gr))
00112    { NO_MEM;
00113      return ((graph *) 0);
00114    }
00115 
00116   gr->n_nodes = n;
00117   gr->n_edges0 = m;
00118   m0 = 0;
00119 
00120   //printf ("Number of nodes and edges: %d, %d\n", n, m);
00121 
00122   for (i = n, nptr = &(gr->nodes[n-1]); i > 0L; --nptr, --i)
00123     { nptr->id = i;
00124       nptr->first_edge = NILE;
00125     }
00126 
00127   eptr1 = &(gr->edges[0L]);
00128   eptr2 = &(gr->edges[m]);
00129   for (j = 0L; j < m; j++)
00130     { if (fscanf (fd, "%s %ld %ld %lg", inp, &nod1, &nod2, &cap)
00131           == EOF)
00132        { fprintf (stderr,
00133                   "EOF reached in input file, %d edges read\n", j);
00134          dealloc_graph (gr);
00135          return ((graph *) 0);
00136        }
00137       if (inp[0] != 'e')
00138        { printf ("syntax error - edge descriptor line expected\n");
00139          dealloc_graph (gr);
00140          return ((graph *) 0);
00141        }
00142       if (nod1 < 1 || nod1 > n)
00143        { fprintf (stderr,
00144                   "invalid node id %d in input graph\n", nod1);
00145          dealloc_graph (gr);
00146          return ((graph *) 0);
00147        }
00148       if (nod2 < 1 || nod2 > n)
00149        { fprintf (stderr, 
00150                   "invalid node id %d in input graph\n", nod2);
00151          dealloc_graph (gr);
00152          return ((graph *) 0);
00153        }
00154       if (nod1 == nod2)
00155        { fprintf (stderr,
00156                   "loop on node %d in input graph\n", nod1);
00157          dealloc_graph (gr);
00158          return ((graph *) 0);
00159        }
00160       if (cap > EPS)
00161        { /* put edge into internal graph representation */
00162          --nod1;
00163          --nod2;
00164          nptr1 = &(gr->nodes[nod1]);
00165          nptr2 = &(gr->nodes[nod2]);
00166          eptr1->adjac = nptr2;
00167          eptr2->adjac = nptr1;
00168          eptr1->cap = cap;
00169          eptr2->cap = cap;
00170          eptr1->back = eptr2;
00171          eptr2->back = eptr1;
00172          if (nptr1->first_edge == NILE)
00173           { nptr1->first_edge = eptr1;
00174             eptr1->next = NILE;
00175           }
00176          else
00177           { eptr1->next = nptr1->first_edge;
00178             nptr1->first_edge = eptr1;
00179           }
00180          if (nptr2->first_edge == NILE)
00181           { nptr2->first_edge = eptr2;
00182             eptr2->next = NILE;
00183           }
00184          else
00185           { eptr2->next = nptr2->first_edge;
00186             nptr2->first_edge = eptr2;
00187           }
00188          ++eptr1;
00189          ++eptr2;
00190        }
00191       else
00192        { /* zero capacity edge not put into edge lists 
00193             of its incident nodes, just counted        */
00194          m0++; 
00195        }
00196       gr->n_edges = m - m0;
00197     }
00198   return (gr);
00199 }
00200 
00201 /*
00202 void updateCapacities(graph* gr; double* cap)
00203 {
00204    edge *eptr1, *eptr2;
00205    eptr1 = &(gr->edges[0L]);
00206    eptr2 = &(gr->edges[m]);
00207 
00208    for (int j = 0; j < G.number_of_edges(); j++) {
00209       eptr1->cap = cap[j];
00210       eptr2->cap = cap[j];
00211       ++eptr1;
00212       ++eptr2;
00213    }
00214 
00215    return;
00216 }  
00217 */
00218 
00219 void print_tree (graph *gr)
00220 {
00221   node *nptr; 
00222 
00223   printf ("Gomory/Hu cut tree:\n");
00224   printf ("root  1\n");
00225   for (nptr = &(gr->nodes[gr->n_nodes-1L]);
00226                   nptr >= &(gr->nodes[1L]); nptr--)
00227      printf ("e  %d  %d    %e\n",
00228              nptr->id, nptr->parent->id, nptr->mincap);
00229 }  
00230 
00231 void compute_tree (int n, int m, int* os, int* ot, double* oc, int* cts, int* ctt, double* ctc)
00232 {
00233   long m0, i, j, nod1, nod2;
00234   double cap;
00235   node *nptr, *nptr1, *nptr2;
00236   edge *eptr1, *eptr2;
00237   graph *gr;
00238 
00239   /* Scans input data and constructs internal representation
00240      of graph.
00241 
00242      Undirected edges are represented by pairs of edge desrip-
00243      tors associated to incident nodes, the incidence list of 
00244      a node is represented as a one way linked list of edge de-
00245      scriptors each of which contains a pointer to an adjacent
00246      node and a "back" pointer to the descriptor of the other
00247      edge in the pair contained in the incidence list of the
00248      adjacent node. 
00249   */
00250 
00251   if (! alloc_graph (n, m, &gr))
00252    { NO_MEM;
00253      exit(1);
00254    }
00255 
00256   gr->n_nodes = n;
00257   gr->n_edges0 = m;
00258   m0 = 0;
00259 
00260   //printf ("CUT_TREE:\nNumber of nodes and edges: %d, %d\n", n, m);
00261 
00262   for (i = n, nptr = &(gr->nodes[n-1]); i > 0; --nptr, --i)
00263     { nptr->id = i;
00264       nptr->first_edge = NILE;
00265     }
00266 
00267   eptr1 = &(gr->edges[0L]);
00268   eptr2 = &(gr->edges[m]);
00269   /* insert the edges into the graph 
00270    * node numbering is expected to start with 1! */
00271   for (j = 0; j < m; j++)
00272     { 
00273        nod1 = os[j];
00274        nod2 = ot[j];
00275        cap = oc[j];
00276       if (nod1 == nod2)
00277        { fprintf (stderr,
00278                   "loop on node %d in input graph\n", nod1);
00279          dealloc_graph (gr);
00280          exit(1);
00281        }
00282       if (cap > EPS)
00283        { /* put edge into internal graph representation */
00284          --nod1;
00285          --nod2;
00286          nptr1 = &(gr->nodes[nod1]);
00287          nptr2 = &(gr->nodes[nod2]);
00288          eptr1->adjac = nptr2;
00289          eptr2->adjac = nptr1;
00290          eptr1->cap = cap;
00291          eptr2->cap = cap;
00292          eptr1->back = eptr2;
00293          eptr2->back = eptr1;
00294          if (nptr1->first_edge == NILE)
00295           { nptr1->first_edge = eptr1;
00296             eptr1->next = NILE;
00297           }
00298          else
00299           { eptr1->next = nptr1->first_edge;
00300             nptr1->first_edge = eptr1;
00301           }
00302          if (nptr2->first_edge == NILE)
00303           { nptr2->first_edge = eptr2;
00304             eptr2->next = NILE;
00305           }
00306          else
00307           { eptr2->next = nptr2->first_edge;
00308             nptr2->first_edge = eptr2;
00309           }
00310          ++eptr1;
00311          ++eptr2;
00312        }
00313       else
00314        { /* zero capacity edge not put into edge lists 
00315             of its incident nodes, just counted        */
00316          m0++; 
00317        }
00318       gr->n_edges = m - m0;
00319     }
00320 
00321   /* compute the cut tree */
00322   ghc_tree (gr);
00323 
00324   /* initialize the return data */
00325   int oi = 0;
00326 
00327   for (nptr = &(gr->nodes[gr->n_nodes-1L]);
00328                   nptr >= &(gr->nodes[1L]); nptr--) {
00329              cts[oi] = nptr->id;
00330              ctt[oi] = nptr->parent->id;
00331              ctc[oi] =  nptr->mincap;
00332              oi++;
00333   }
00334   dealloc_graph(gr);
00335 
00336   if( oi != n-1 ) {
00337      printf("Wrong number of edges in cut tree!\n");
00338      exit(1);
00339   }
00340 
00341   return;
00342 }  
00343 
00344 
00345 #ifdef GCT_MAIN
00346 void main (argc, argv)
00347   int argc;
00348   char **argv;
00349 {
00350   FILE *fd;
00351   graph *gr;
00352   long n1, n2;
00353   float t0, t1, t2;
00354 
00355   /* Main programm for Gomory/Hu cut tree function   
00356      
00357      Input format is compatible to DIMACS, nodes and arcs
00358      are asssumed to be numbered 1 to n and m respectively. 
00359   */
00360                     
00361   if  (argc != 2)
00362    { fprintf (stderr, "ghc_tree: call parameter missing\n");
00363      fprintf (stderr,
00364               "usage:  ghc_tree <input filename>\n");
00365      exit (1);
00366    }
00367   t0 = user_time (); 
00368   if ((fd = fopen (argv[1], "r")) == NULL)
00369    { fprintf(stderr, "Unable to open %s\n", argv[1]);
00370      exit (1);
00371    }
00372 
00373   gr = get_graph (fd);
00374   if (gr == (graph *) 0)
00375    { close (fd); 
00376      exit (1);
00377    }
00378   close (fd);  
00379 
00380   t1 = user_time ();
00381 
00382   if (ghc_tree (gr))
00383    { t2 = user_time (); 
00384      print_tree (gr);
00385      printf ("File input and initialization time: ");
00386      print_time (t1 - t0);
00387      printf ("Total execution time: ");
00388      print_time (t2 - t0);
00389    }
00390   dealloc_graph (gr);
00391 }
00392 #endif 
Generated on Mon Mar 28 22:03:48 2011 for SCIL by  doxygen 1.6.3