CFugue
dimacs.h
1 #ifndef _DIMACS__9FD17A0C_743B_4438_B8D7_9CD297CED5D3_
2 #define _DIMACS__9FD17A0C_743B_4438_B8D7_9CD297CED5D3_
3 
4 #include "_TChar.h"
5 #include <stdlib.h>
6 #include <stdio.h>
7 #include <string.h>
8 
10 {
11  inline static void OnProblemInformationRead(int nVertices, int nEdges) { }
12  inline static void OnFoundEdge(int nVert1, int nVert2) { }
13  inline static void OnLoadComplete() { }
14 };
15 
16 /// Gets Nr_vert and Nr_edge from the preamble string
17 /// containing Dimacs format "p ??? num num"
18 int get_params(int& Nr_vert, int& Nr_edges, const char* Preamble)
19 {
20  char c, *tmp;
21  const char * pp = Preamble;
22  int stop = 0;
23  tmp = (char *)calloc(100, sizeof(char));
24 
25  Nr_vert = Nr_edges = 0;
26 
27  while (!stop && (c = *pp++) != '\0'){
28  switch (c)
29  {
30  case 'c':
31  while ((c = *pp++) != '\n' && c != '\0');
32  break;
33 
34  case 'p':
35  sscanf(pp, "%s %d %d\n", tmp, &Nr_vert, &Nr_edges);
36  stop = 1;
37  break;
38 
39  default:
40  break;
41  }
42  }
43 
44  free(tmp);
45 
46  if (Nr_vert == 0 || Nr_edges == 0)
47  return 0; /* error */
48  else
49  return 1;
50 
51 }
52 
53 ///////////////////////////////////////////////////////////
54 ///
55 #define MAX_NR_VERTICES 10000
56 #define MAX_NR_VERTICESdiv8 (MAX_NR_VERTICES/8)
57 #define MAX_PREAMBLE 10000
58 ///
59 ///////////////////////////////////////////////////////////
60 // Retruns if there is edge in the binary bitmap loaded from binary input file
61 bool get_edge(int i, int j, char Bitmap[MAX_NR_VERTICES][MAX_NR_VERTICESdiv8])
62 {
63  static const unsigned char masks[ 8 ] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
64 
65  int byte, bit;
66  unsigned char mask;
67 
68  bit = 7-(j & 0x00000007);
69  byte = j >> 3;
70 
71  mask = masks[bit];
72  return( (Bitmap[i][byte] & mask)==mask );
73 }
74 
75 // Loads a binary input file and reports the found edges
76 template<class _listener>
77 bool read_graph_DIMACS_bin(const char* lpszFile)
78 {
79  char Preamble[MAX_PREAMBLE];
80  char Bitmap[MAX_NR_VERTICES][MAX_NR_VERTICESdiv8];
81 
82  int i, j, length = 0;
83 
84  FILE *fp = fopen(lpszFile, "r");
85  if(fp == NULL) { fprintf(stderr, "\nERROR: Unable to open %s \n", lpszFile); return false; }
86 
87  // Try reading the length of the Preamble
88  if (!fscanf(fp, "%d\n", &length))
89  { fprintf(stderr,"\nERROR: Corrupted preamble in %s \n", lpszFile); return false; }
90 
91  if(length >= MAX_PREAMBLE)
92  { fprintf(stderr,"\nERROR: Too long preamble in %s \n", lpszFile); return false; }
93 
94  // Read the Preamble itself
95  fread(Preamble, 1, length, fp);
96  Preamble[length] = '\0';
97 
98  // Get the Edge and Vertex Information
99  int Nr_vert, Nr_edges;
100  if (!get_params(Nr_vert, Nr_edges, Preamble))
101  { fprintf(stderr,"\nERROR: Corrupted preamble in %s \n", lpszFile); return false; }
102 
103  // Report the Edge and Vertex information to the App
104  _listener::OnProblemInformationRead(Nr_vert, Nr_edges);
105 
106  // Read the Adjacency into a binary bitmap
107  for ( i = 0
108  ; i < Nr_vert && fread(Bitmap[i], 1, (int)((i + 8)/8), fp)
109  ; i++ );
110 
111  fclose(fp);
112 
113  // Now report the Edges found in the bitmap
114  for ( i = 0; i<Nr_vert; i++ )
115  for ( j=0; j<=i; j++ )
116  if ( get_edge(i,j,Bitmap) )
117  _listener::OnFoundEdge(i+1, j+1); // Report the Edge to the App for processing
118 
119  _listener::OnLoadComplete(); // Report the completion of loading the graph
120 
121  return true;
122 }
123 
124 // Loads an Ascii input file and reports the found edges
125 template<class _listener>
126 bool read_graph_DIMACS_ascii(const char* lpszFile)
127 {
128  char Preamble[MAX_PREAMBLE];
129 
130  int c, oc;
131  char * pp = Preamble;
132  int i,j;
133  int Nr_vert, Nr_edges;
134 
135  FILE *fp = fopen(lpszFile, "r");
136  if(fp == NULL) { fprintf(stderr, "\nERROR: Unable to open %s \n", lpszFile); return false; }
137 
138  // Read past the Comments and Preamble section
139  for(oc = '\0' ;(c = fgetc(fp)) != EOF && (oc != '\n' || c != 'e')
140  ; oc = *pp++ = c);
141 
142  ungetc(c, fp);
143  *pp = '\0';
144  if(!get_params(Nr_vert, Nr_edges, Preamble)) // Get the Edge and Vertex Information
145  { fprintf(stderr,"\nERROR: Corrupted preamble in %s \n", lpszFile); return false; }
146 
147  // Report the Edge and Vertex information to the App
148  _listener::OnProblemInformationRead(Nr_vert, Nr_edges);
149 
150  // Read the Edge Adjacency Information
151  while ((c = fgetc(fp)) != EOF)
152  {
153  switch (c)
154  {
155  case 'e':
156  {
157  if (!fscanf(fp, "%d %d", &i, &j))
158  { fprintf(stderr, "\nERROR: corrupted inputfile %s \n", lpszFile); return false; }
159 
160  _listener::OnFoundEdge(i, j); // Report the Found Edge to the App
161  break;
162  }
163  case '\n':
164  default: break;
165  }
166  }
167 
168  fclose(fp);
169 
170  _listener::OnLoadComplete(); // Report the completion of loading the graph
171 
172  return true;
173 }
174 
175 // loads the given DIMACS graph file (binary / ascii)
176 template<class _listener>
177 bool load_DIMACS_graphfile(const char* lpszFile)
178 {
179  if(strstr(lpszFile, ".b")) // if the input file is Binary
180  return read_graph_DIMACS_bin<_listener>(lpszFile);
181 
182  // else consider it as an Ascii
183  return read_graph_DIMACS_ascii<_listener>(lpszFile);
184 }
185 
186 #endif // _DIMACS__9FD17A0C_743B_4438_B8D7_9CD297CED5D3_

CFugue, the C++ Music Programming Library © Copyright 2009 Cenacle Research India Private Limited Gopalakrishna Palem