/* This software was developed by Bruce Hendrickson and Robert Leland * * at Sandia National Laboratories under US Department of Energy * * contract DE-AC04-76DP00789 and is copyrighted by Sandia Corporation. */ #include #include #include "defs.h" int input_graph(fin, inname, start, adjacency, nvtxs, vweights, eweights) FILE *fin; /* input file */ char *inname; /* name of input file */ int **start; /* start of edge list for each vertex */ int **adjacency; /* edge list data */ int *nvtxs; /* number of vertices in graph */ int **vweights; /* vertex weight list data */ float **eweights; /* edge weight list data */ { extern FILE *Output_File; /* output file or null */ extern int CHECK_INPUT; /* print warnings or not? */ extern int DEBUG_INPUT; /* echo that input file read successful? */ extern int DEBUG_TRACE; /* trace main execution path */ int *adjptr; /* loops through adjacency data */ float *ewptr; /* loops through edge weight data */ int narcs; /* number of edges expected in graph */ int nedges; /* twice number of edges really in graph */ int nedge; /* loops through edges for each vertex */ int flag; /* condition indicator */ int found_flag; /* is vertex found in adjacency list? */ int skip_flag; /* should this edge be ignored? */ int end_flag; /* indicates end of line or file */ int vtx; /* vertex in graph */ int line_num; /* line number in input file */ int sum_edges; /* total number of edges read so far */ int option; /* input option */ int using_ewgts; /* are edge weights in input file? */ int using_vwgts; /* are vertex weights in input file? */ int vtxnums; /* are vertex numbers in input file? */ int vertex; /* current vertex being read */ int new_vertex; /* new vertex being read */ int weight; /* weight being read */ float eweight; /* edge weight being read */ int neighbor; /* neighbor of current vertex */ int self_edge; /* is a self edge encountered? */ int ignore_me; /* is this edge being ignored? */ int ignored; /* how many edges are ignored? */ int error_flag; /* error reading input? */ int j; /* loop counters */ int sfree(), read_int(); double *smalloc(), read_val(); if (DEBUG_TRACE > 0) { printf("\n"); } /* Read first line of input (= nvtxs, narcs, option). */ /* The (decimal) digits of the option variable mean: 1's digit not zero => input edge weights 10's digit not zero => input vertex weights 100's digit not zero => include vertex numbers */ *start = NULL; *adjacency = NULL; *vweights = NULL; *eweights = NULL; error_flag = 0; line_num = 0; /* Read any leading comment lines */ end_flag = 1; while (end_flag == 1) { *nvtxs = read_int(fin, &end_flag); ++line_num; } if (*nvtxs <= 0) { printf("ERROR in graph file `%s':", inname); printf(" Invalid number of vertices (%d).\n", *nvtxs); if (Output_File != NULL) { fprintf(Output_File, "ERROR in graph file `%s':", inname); fprintf(Output_File, " Invalid number of vertices (%d).\n", *nvtxs); } fclose(fin); return(1); } narcs = read_int(fin, &end_flag); if (narcs < 0) { printf("ERROR in graph file `%s':", inname); printf(" Invalid number of expected edges (%d).\n", narcs); if (Output_File != NULL) { fprintf(Output_File, "ERROR in graph file `%s':", inname); fprintf(Output_File, " Invalid number of expected edges (%d).\n", narcs); } fclose(fin); return(1); } if (!end_flag) { option = read_int(fin, &end_flag); } while (!end_flag) j = read_int(fin, &end_flag); using_ewgts = option - 10 * (option / 10); option /= 10; using_vwgts = option - 10 * (option / 10); option /= 10; vtxnums = option - 10 * (option / 10); /* Allocate space for rows and columns. */ *start = (int *) smalloc((unsigned) (*nvtxs + 1) * sizeof(int)); if (narcs != 0) *adjacency = (int *) smalloc((unsigned) (2 * narcs + 1) * sizeof(int)); else *adjacency = NULL; if (using_vwgts) *vweights = (int *) smalloc((unsigned) (*nvtxs) * sizeof(int)); else *vweights = NULL; if (using_ewgts && narcs != 0) *eweights = (float *) smalloc((unsigned) (2 * narcs + 1) * sizeof(float)); else *eweights = NULL; adjptr = *adjacency; ewptr = *eweights; self_edge = 0; ignored = 0; sum_edges = 0; nedges = 0; (*start)[0] = 0; vertex = 0; vtx = 0; new_vertex = TRUE; while ((narcs || using_vwgts || vtxnums) && end_flag != -1) { ++line_num; /* If multiple input lines per vertex, read vertex number. */ if (vtxnums) { j = read_int(fin, &end_flag); if (end_flag) { if (vertex == *nvtxs) break; printf("ERROR in graph file `%s':", inname); printf(" no vertex number in line %d.\n", line_num); if (Output_File != NULL) { fprintf(Output_File, "ERROR in graph file `%s':", inname); fprintf(Output_File, " no vertex number in line %d.\n", line_num); } fclose(fin); return (1); } if (j != vertex && j != vertex + 1) { printf("ERROR in graph file `%s':", inname); printf(" out-of-order vertex number in line %d.\n", line_num); if (Output_File != NULL) { fprintf(Output_File, "ERROR in graph file `%s':", inname); fprintf(Output_File, " out-of-order vertex number in line %d.\n", line_num); } fclose(fin); return (1); } if (j != vertex) { new_vertex = TRUE; vertex = j; } else new_vertex = FALSE; } else vertex = ++vtx; if (vertex > *nvtxs) break; /* If vertices are weighted, read vertex weight. */ if (using_vwgts && new_vertex) { weight = read_int(fin, &end_flag); if (end_flag) { printf("ERROR in graph file `%s':", inname); printf(" no weight for vertex %d.\n", vertex); if (Output_File != NULL) { fprintf(Output_File, "ERROR in graph file `%s':", inname); fprintf(Output_File, " no weight for vertex %d.\n", vertex); } fclose(fin); return (1); } if (weight <= 0) { printf("ERROR in graph file `%s':", inname); printf(" zero or negative weight entered for vertex %d.\n", vertex); if (Output_File != NULL) { fprintf(Output_File, "ERROR in graph file `%s':", inname); fprintf(Output_File, " zero or negative weight entered for vertex %d.\n", vertex); } fclose(fin); return (1); } (*vweights)[vertex-1] = weight; } nedge = 0; /* Read number of adjacent vertex. */ neighbor = read_int(fin, &end_flag); while (!end_flag) { skip_flag = FALSE; ignore_me = FALSE; if (neighbor > *nvtxs) { printf("ERROR in graph file `%s':", inname); printf(" nvtxs=%d, but edge (%d,%d) was input.\n", *nvtxs, vertex, neighbor); if (Output_File != NULL) { fprintf(Output_File, "ERROR in graph file `%s':", inname); fprintf(Output_File, " nvtxs=%d, but edge (%d,%d) was input.\n", *nvtxs, vertex, neighbor); } fclose(fin); return (1); } if (neighbor <= 0) { printf("ERROR in graph file `%s':", inname); printf(" zero or negative vertex in edge (%d,%d).\n", vertex, neighbor); if (Output_File != NULL) { fprintf(Output_File, "ERROR in graph file `%s':", inname); fprintf(Output_File, " zero or negative vertex in edge (%d,%d).\n", vertex, neighbor); } fclose(fin); return (1); } if (neighbor == vertex) { if (!self_edge && CHECK_INPUT) { printf("WARNING: Self edge (%d, %d) being ignored.\n", vertex, vertex); if (Output_File != NULL) { fprintf(Output_File, "WARNING: Self edge (%d, %d) being ignored.\n", vertex, vertex); } } skip_flag = TRUE; ++self_edge; } /* Check if adjacency is repeated. */ if (!skip_flag) { found_flag = FALSE; for (j = (*start)[vertex - 1]; !found_flag && j < sum_edges + nedge; j++) { if ((*adjacency)[j] == neighbor) found_flag = TRUE; } if (found_flag) { printf("WARNING: Multiple occurences of edge (%d,%d) ignored\n", vertex, neighbor); if (Output_File != NULL) { fprintf(Output_File, "WARNING: Multiple occurences of edge (%d,%d) ignored\n", vertex, neighbor); } skip_flag = TRUE; if (!ignore_me) { ignore_me = TRUE; ++ignored; } } } if (using_ewgts) { /* Read edge weight if it's being input. */ eweight = read_val(fin, &end_flag); if (end_flag) { printf("ERROR in graph file `%s':", inname); printf(" no weight for edge (%d,%d).\n", vertex, neighbor); if (Output_File != NULL) { fprintf(Output_File, "ERROR in graph file `%s':", inname); fprintf(Output_File, " no weight for edge (%d,%d).\n", vertex, neighbor); } fclose(fin); return (1); } if (eweight <= 0 && CHECK_INPUT) { printf("WARNING: Bad weight entered for edge (%d,%d). Edge ignored.\n", vertex, neighbor); if (Output_File != NULL) { fprintf(Output_File, "WARNING: Bad weight entered for edge (%d,%d). Edge ignored.\n", vertex, neighbor); } skip_flag = TRUE; if (!ignore_me) { ignore_me = TRUE; ++ignored; } } else { *ewptr++ = eweight; } } /* Check for edge only entered once. */ if (neighbor < vertex && !skip_flag) { found_flag = FALSE; for (j = (*start)[neighbor - 1]; !found_flag && j < (*start)[neighbor]; j++) { if ((*adjacency)[j] == vertex) found_flag = TRUE; } if (!found_flag) { printf("ERROR in graph file `%s':", inname); printf(" Edge (%d, %d) entered but not (%d, %d)\n", vertex, neighbor, neighbor, vertex); if (Output_File != NULL) { fprintf(Output_File, "ERROR in graph file `%s':", inname); fprintf(Output_File, " Edge (%d, %d) entered but not (%d, %d)\n", vertex, neighbor, neighbor, vertex); } error_flag = 1; } } /* Add edge to data structure. */ if (!skip_flag) { if (++nedges > 2*narcs) { printf("ERROR in graph file `%s':", inname); printf(" at least %d adjacencies entered, but nedges = %d\n", nedges, narcs); if (Output_File != NULL) { fprintf(Output_File, "ERROR in graph file `%s':", inname); fprintf(Output_File, " at least %d adjacencies entered, but nedges = %d\n", nedges, narcs); } fclose(fin); return (1); } *adjptr++ = neighbor; nedge++; } /* Read number of next adjacent vertex. */ neighbor = read_int(fin, &end_flag); } sum_edges += nedge; (*start)[vertex] = sum_edges; } /* Make sure there's nothing else in file. */ flag = FALSE; while (!flag && end_flag != -1) { read_int(fin, &end_flag); if (!end_flag) flag = TRUE; } if (flag && CHECK_INPUT) { printf("WARNING: Possible error in graph file `%s'\n", inname); printf(" Data found after expected end of file\n"); if (Output_File != NULL) { fprintf(Output_File, "WARNING: Possible error in graph file `%s'\n", inname); fprintf(Output_File, " Data found after expected end of file\n"); } } (*start)[*nvtxs] = sum_edges; if (self_edge > 1 && CHECK_INPUT) { printf("WARNING: %d self edges were read and ignored.\n", self_edge); if (Output_File != NULL) { fprintf(Output_File, "WARNING: %d self edges were read and ignored.\n", self_edge); } } if (vertex != 0) { /* Normal file was read. */ /* Make sure narcs was reasonable. */ if (nedges + 2 * self_edge != 2 * narcs && nedges + 2 * self_edge + ignored != 2 * narcs && nedges + self_edge != 2 * narcs && nedges + self_edge + ignored != 2 * narcs && nedges != 2 * narcs && nedges + ignored != 2 * narcs && CHECK_INPUT) { printf("WARNING: I expected %d edges entered twice, but I only count %d.\n", narcs, nedges); if (Output_File != NULL) { fprintf(Output_File, "WARNING: I expected %d edges entered twice, but I only count %d.\n", narcs, nedges); } } } else { /* Graph was empty => must be using inertial method. */ sfree((char *) *start); if (*adjacency != NULL) sfree((char *) *adjacency); if (*eweights != NULL) sfree((char *) *eweights); *start = NULL; *adjacency = NULL; } fclose(fin); if (DEBUG_INPUT > 0) { printf("Done reading graph file `%s'.\n", inname); } return (error_flag); }