Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/elmergrid/src/metis-5.1.0/libmetis/checkgraph.c
3206 views
1
/*
2
* Copyright 1997, Regents of the University of Minnesota
3
*
4
* checkgraph.c
5
*
6
* This file contains routines related to I/O
7
*
8
* Started 8/28/94
9
* George
10
*
11
*/
12
13
#include "metislib.h"
14
15
16
17
/*************************************************************************/
18
/*! This function checks if a graph is valid. A valid graph must satisfy
19
the following constraints:
20
- It should contain no self-edges.
21
- It should be undirected; i.e., (u,v) and (v,u) should be present.
22
- The adjacency list should not contain multiple edges to the same
23
other vertex.
24
25
\param graph is the graph to be checked, whose numbering starts from 0.
26
\param numflag is 0 if error reporting will be done using 0 as the
27
numbering, or 1 if the reporting should be done using 1.
28
\param verbose is 1 the identified errors will be displayed, or 0, if
29
it should run silently.
30
*/
31
/*************************************************************************/
32
int CheckGraph(graph_t *graph, int numflag, int verbose)
33
{
34
idx_t i, j, k, l;
35
idx_t nvtxs, err=0;
36
idx_t minedge, maxedge, minewgt, maxewgt;
37
idx_t *xadj, *adjncy, *adjwgt, *htable;
38
39
numflag = (numflag == 0 ? 0 : 1); /* make sure that numflag is 0 or 1 */
40
41
nvtxs = graph->nvtxs;
42
xadj = graph->xadj;
43
adjncy = graph->adjncy;
44
adjwgt = graph->adjwgt;
45
46
ASSERT(adjwgt != NULL);
47
48
htable = ismalloc(nvtxs, 0, "htable");
49
50
minedge = maxedge = adjncy[0];
51
minewgt = maxewgt = adjwgt[0];
52
53
for (i=0; i<nvtxs; i++) {
54
for (j=xadj[i]; j<xadj[i+1]; j++) {
55
k = adjncy[j];
56
57
minedge = (k < minedge) ? k : minedge;
58
maxedge = (k > maxedge) ? k : maxedge;
59
minewgt = (adjwgt[j] < minewgt) ? adjwgt[j] : minewgt;
60
maxewgt = (adjwgt[j] > maxewgt) ? adjwgt[j] : maxewgt;
61
62
if (i == k) {
63
if (verbose)
64
printf("Vertex %"PRIDX" contains a self-loop "
65
"(i.e., diagonal entry in the matrix)!\n", i+numflag);
66
err++;
67
}
68
else {
69
for (l=xadj[k]; l<xadj[k+1]; l++) {
70
if (adjncy[l] == i) {
71
if (adjwgt[l] != adjwgt[j]) {
72
if (verbose)
73
printf("Edges (u:%"PRIDX" v:%"PRIDX" wgt:%"PRIDX") and "
74
"(v:%"PRIDX" u:%"PRIDX" wgt:%"PRIDX") "
75
"do not have the same weight!\n",
76
i+numflag, k+numflag, adjwgt[j],
77
k+numflag, i+numflag, adjwgt[l]);
78
err++;
79
}
80
break;
81
}
82
}
83
if (l == xadj[k+1]) {
84
if (verbose)
85
printf("Missing edge: (%"PRIDX" %"PRIDX")!\n", k+numflag, i+numflag);
86
err++;
87
}
88
}
89
90
if (htable[k] == 0) {
91
htable[k]++;
92
}
93
else {
94
if (verbose)
95
printf("Edge %"PRIDX" from vertex %"PRIDX" is repeated %"PRIDX" times\n",
96
k+numflag, i+numflag, htable[k]++);
97
err++;
98
}
99
}
100
101
for (j=xadj[i]; j<xadj[i+1]; j++)
102
htable[adjncy[j]] = 0;
103
}
104
105
106
if (err > 0 && verbose) {
107
printf("A total of %"PRIDX" errors exist in the input file. "
108
"Correct them, and run again!\n", err);
109
}
110
111
gk_free((void **)&htable, LTERM);
112
113
return (err == 0 ? 1 : 0);
114
}
115
116
117
/*************************************************************************/
118
/*! This function performs a quick check of the weights of the graph */
119
/*************************************************************************/
120
int CheckInputGraphWeights(idx_t nvtxs, idx_t ncon, idx_t *xadj, idx_t *adjncy,
121
idx_t *vwgt, idx_t *vsize, idx_t *adjwgt)
122
{
123
idx_t i;
124
125
if (ncon <= 0) {
126
printf("Input Error: ncon must be >= 1.\n");
127
return 0;
128
}
129
130
if (vwgt) {
131
for (i=ncon*nvtxs; i>=0; i--) {
132
if (vwgt[i] < 0) {
133
printf("Input Error: negative vertex weight(s).\n");
134
return 0;
135
}
136
}
137
}
138
if (vsize) {
139
for (i=nvtxs; i>=0; i--) {
140
if (vsize[i] < 0) {
141
printf("Input Error: negative vertex sizes(s).\n");
142
return 0;
143
}
144
}
145
}
146
if (adjwgt) {
147
for (i=xadj[nvtxs]-1; i>=0; i--) {
148
if (adjwgt[i] < 0) {
149
printf("Input Error: non-positive edge weight(s).\n");
150
return 0;
151
}
152
}
153
}
154
155
return 1;
156
}
157
158
159
/*************************************************************************/
160
/*! This function creates a graph whose topology is consistent with
161
Metis' requirements that:
162
- There are no self-edges.
163
- It is undirected; i.e., (u,v) and (v,u) should be present and of the
164
same weight.
165
- The adjacency list should not contain multiple edges to the same
166
other vertex.
167
168
Any of the above errors are fixed by performing the following operations:
169
- Self-edges are removed.
170
- The undirected graph is formed by the union of edges.
171
- One of the duplicate edges is selected.
172
173
The routine does not change the provided vertex weights.
174
*/
175
/*************************************************************************/
176
graph_t *FixGraph(graph_t *graph)
177
{
178
idx_t i, j, k, l, nvtxs, nedges;
179
idx_t *xadj, *adjncy, *adjwgt;
180
idx_t *nxadj, *nadjncy, *nadjwgt;
181
graph_t *ngraph;
182
uvw_t *edges;
183
184
185
nvtxs = graph->nvtxs;
186
xadj = graph->xadj;
187
adjncy = graph->adjncy;
188
adjwgt = graph->adjwgt;
189
ASSERT(adjwgt != NULL);
190
191
ngraph = CreateGraph();
192
193
ngraph->nvtxs = nvtxs;
194
195
/* deal with vertex weights/sizes */
196
ngraph->ncon = graph->ncon;
197
ngraph->vwgt = icopy(nvtxs*graph->ncon, graph->vwgt,
198
imalloc(nvtxs*graph->ncon, "FixGraph: vwgt"));
199
200
ngraph->vsize = ismalloc(nvtxs, 1, "FixGraph: vsize");
201
if (graph->vsize)
202
icopy(nvtxs, graph->vsize, ngraph->vsize);
203
204
/* fix graph by sorting the "superset" of edges */
205
edges = (uvw_t *)gk_malloc(sizeof(uvw_t)*2*xadj[nvtxs], "FixGraph: edges");
206
207
for (nedges=0, i=0; i<nvtxs; i++) {
208
for (j=xadj[i]; j<xadj[i+1]; j++) {
209
/* keep only the upper-trianglular part of the adjacency matrix */
210
if (i < adjncy[j]) {
211
edges[nedges].u = i;
212
edges[nedges].v = adjncy[j];
213
edges[nedges].w = adjwgt[j];
214
nedges++;
215
}
216
else if (i > adjncy[j]) {
217
edges[nedges].u = adjncy[j];
218
edges[nedges].v = i;
219
edges[nedges].w = adjwgt[j];
220
nedges++;
221
}
222
}
223
}
224
225
uvwsorti(nedges, edges);
226
227
228
/* keep the unique subset */
229
for (k=0, i=1; i<nedges; i++) {
230
if (edges[k].v != edges[i].v || edges[k].u != edges[i].u) {
231
edges[++k] = edges[i];
232
}
233
}
234
nedges = k+1;
235
236
/* allocate memory for the fixed graph */
237
nxadj = ngraph->xadj = ismalloc(nvtxs+1, 0, "FixGraph: nxadj");
238
nadjncy = ngraph->adjncy = imalloc(2*nedges, "FixGraph: nadjncy");
239
nadjwgt = ngraph->adjwgt = imalloc(2*nedges, "FixGraph: nadjwgt");
240
241
/* create the adjacency list of the fixed graph from the upper-triangular
242
part of the adjacency matrix */
243
for (k=0; k<nedges; k++) {
244
nxadj[edges[k].u]++;
245
nxadj[edges[k].v]++;
246
}
247
MAKECSR(i, nvtxs, nxadj);
248
249
for (k=0; k<nedges; k++) {
250
nadjncy[nxadj[edges[k].u]] = edges[k].v;
251
nadjncy[nxadj[edges[k].v]] = edges[k].u;
252
nadjwgt[nxadj[edges[k].u]] = edges[k].w;
253
nadjwgt[nxadj[edges[k].v]] = edges[k].w;
254
nxadj[edges[k].u]++;
255
nxadj[edges[k].v]++;
256
}
257
SHIFTCSR(i, nvtxs, nxadj);
258
259
gk_free((void **)&edges, LTERM);
260
261
return ngraph;
262
}
263
264
265