You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
420 lines
14 KiB
420 lines
14 KiB
/*
|
|
* Copyright(C) 1999-2020, 2023 National Technology & Engineering Solutions
|
|
* of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with
|
|
* NTESS, the U.S. Government retains certain rights in this software.
|
|
*
|
|
* See packages/seacas/LICENSE for details
|
|
*/
|
|
|
|
#include "defs.h" // for TRUE, FALSE
|
|
#include "smalloc.h" // for smalloc, sfree
|
|
|
|
#include <stdio.h> // for printf, fprintf, NULL, etc
|
|
|
|
int input_graph(FILE *fin, char *inname, int **start, int **adjacency, int *nvtxs, int **vweights,
|
|
float **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 = 0; /* 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 */
|
|
|
|
if (DEBUG_TRACE > 0) {
|
|
printf("<Entering input_graph>\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) {
|
|
(void)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 = smalloc((*nvtxs + 1) * sizeof(int));
|
|
if (narcs != 0) {
|
|
*adjacency = smalloc((2 * narcs + 1) * sizeof(int));
|
|
}
|
|
else {
|
|
*adjacency = NULL;
|
|
}
|
|
|
|
if (using_vwgts) {
|
|
*vweights = smalloc((*nvtxs) * sizeof(int));
|
|
}
|
|
else {
|
|
*vweights = NULL;
|
|
}
|
|
|
|
if (using_ewgts && narcs != 0) {
|
|
*eweights = smalloc((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 occurrences of edge (%d,%d) ignored\n", vertex, neighbor);
|
|
if (Output_File != NULL) {
|
|
fprintf(Output_File, "WARNING: Multiple occurrences 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) {
|
|
++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(*start);
|
|
if (*adjacency != NULL) {
|
|
sfree(*adjacency);
|
|
}
|
|
if (*eweights != NULL) {
|
|
sfree(*eweights);
|
|
}
|
|
*start = NULL;
|
|
*adjacency = NULL;
|
|
}
|
|
|
|
fclose(fin);
|
|
|
|
if (DEBUG_INPUT > 0) {
|
|
printf("Done reading graph file `%s'.\n", inname);
|
|
}
|
|
return (error_flag);
|
|
}
|
|
|