2 * Copyright 1997, Regents of the University of Minnesota
6 * This file contains routines related to I/O
11 * $Id: io.c 11932 2012-05-10 18:18:23Z dominique $
19 /*************************************************************************/
20 /*! This function reads in a sparse graph */
21 /*************************************************************************/
22 graph_t
*ReadGraph(params_t
*params
)
24 idx_t i
, j
, k
, l
, fmt
, ncon
, nfields
, readew
, readvw
, readvs
, edge
, ewgt
;
25 idx_t
*xadj
, *adjncy
, *vwgt
, *adjwgt
, *vsize
;
26 char *line
=NULL
, fmtstr
[256], *curstr
, *newstr
;
31 if (!gk_fexists(params
->filename
))
32 errexit("File %s does not exist!\n", params
->filename
);
34 graph
= CreateGraph();
36 fpin
= gk_fopen(params
->filename
, "r", "ReadGRaph: Graph");
38 /* Skip comment lines until you get to the first valid line */
40 if (gk_getline(&line
, &lnlen
, fpin
) == -1)
41 errexit("Premature end of input file: file: %s\n", params
->filename
);
42 } while (line
[0] == '%');
46 nfields
= sscanf(line
, "%"SCIDX
" %"SCIDX
" %"SCIDX
" %"SCIDX
,
47 &(graph
->nvtxs
), &(graph
->nedges
), &fmt
, &ncon
);
50 errexit("The input file does not specify the number of vertices and edges.\n");
52 if (graph
->nvtxs
<= 0 || graph
->nedges
<= 0)
53 errexit("The supplied nvtxs:%"PRIDX
" and nedges:%"PRIDX
" must be positive.\n",
54 graph
->nvtxs
, graph
->nedges
);
57 errexit("Cannot read this type of file format [fmt=%"PRIDX
"]!\n", fmt
);
59 sprintf(fmtstr
, "%03"PRIDX
, fmt
%1000);
60 readvs
= (fmtstr
[0] == '1');
61 readvw
= (fmtstr
[1] == '1');
62 readew
= (fmtstr
[2] == '1');
64 /*printf("%s %"PRIDX" %"PRIDX" %"PRIDX"\n", fmtstr, readvs, readvw, readew); */
67 if (ncon
> 0 && !readvw
)
69 "------------------------------------------------------------------------------\n"
70 "*** I detected an error in your input file ***\n\n"
71 "You specified ncon=%"PRIDX
", but the fmt parameter does not specify vertex weights\n"
72 "Make sure that the fmt parameter is set to either 10 or 11.\n"
73 "------------------------------------------------------------------------------\n", ncon
);
76 ncon
= graph
->ncon
= (ncon
== 0 ? 1 : ncon
);
78 xadj
= graph
->xadj
= ismalloc(graph
->nvtxs
+1, 0, "ReadGraph: xadj");
79 adjncy
= graph
->adjncy
= imalloc(graph
->nedges
, "ReadGraph: adjncy");
80 vwgt
= graph
->vwgt
= ismalloc(ncon
*graph
->nvtxs
, 1, "ReadGraph: vwgt");
81 adjwgt
= graph
->adjwgt
= ismalloc(graph
->nedges
, 1, "ReadGraph: adjwgt");
82 vsize
= graph
->vsize
= ismalloc(graph
->nvtxs
, 1, "ReadGraph: vsize");
85 /*----------------------------------------------------------------------
86 * Read the sparse graph file
87 *---------------------------------------------------------------------*/
88 for (xadj
[0]=0, k
=0, i
=0; i
<graph
->nvtxs
; i
++) {
90 if (gk_getline(&line
, &lnlen
, fpin
) == -1)
91 errexit("Premature end of input file while reading vertex %"PRIDX
".\n", i
+1);
92 } while (line
[0] == '%');
97 /* Read vertex sizes */
99 vsize
[i
] = strtoidx(curstr
, &newstr
, 10);
100 if (newstr
== curstr
)
101 errexit("The line for vertex %"PRIDX
" does not have vsize information\n", i
+1);
103 errexit("The size for vertex %"PRIDX
" must be >= 0\n", i
+1);
108 /* Read vertex weights */
110 for (l
=0; l
<ncon
; l
++) {
111 vwgt
[i
*ncon
+l
] = strtoidx(curstr
, &newstr
, 10);
112 if (newstr
== curstr
)
113 errexit("The line for vertex %"PRIDX
" does not have enough weights "
114 "for the %"PRIDX
" constraints.\n", i
+1, ncon
);
115 if (vwgt
[i
*ncon
+l
] < 0)
116 errexit("The weight vertex %"PRIDX
" and constraint %"PRIDX
" must be >= 0\n", i
+1, l
);
122 edge
= strtoidx(curstr
, &newstr
, 10);
123 if (newstr
== curstr
)
124 break; /* End of line */
127 if (edge
< 1 || edge
> graph
->nvtxs
)
128 errexit("Edge %"PRIDX
" for vertex %"PRIDX
" is out of bounds\n", edge
, i
+1);
132 ewgt
= strtoidx(curstr
, &newstr
, 10);
133 if (newstr
== curstr
)
134 errexit("Premature end of line for vertex %"PRIDX
"\n", i
+1);
136 errexit("The weight (%"PRIDX
") for edge (%"PRIDX
", %"PRIDX
") must be positive.\n",
141 if (k
== graph
->nedges
)
142 errexit("There are more edges in the file than the %"PRIDX
" specified.\n",
153 if (k
!= graph
->nedges
) {
154 printf("------------------------------------------------------------------------------\n");
155 printf("*** I detected an error in your input file ***\n\n");
156 printf("In the first line of the file, you specified that the graph contained\n"
157 "%"PRIDX
" edges. However, I only found %"PRIDX
" edges in the file.\n",
158 graph
->nedges
/2, k
/2);
159 if (2*k
== graph
->nedges
) {
160 printf("\n *> I detected that you specified twice the number of edges that you have in\n");
161 printf(" the file. Remember that the number of edges specified in the first line\n");
162 printf(" counts each edge between vertices v and u only once.\n\n");
164 printf("Please specify the correct number of edges in the first line of the file.\n");
165 printf("------------------------------------------------------------------------------\n");
169 gk_free((void *)&line
, LTERM
);
175 /*************************************************************************/
176 /*! This function reads in a mesh */
177 /*************************************************************************/
178 mesh_t
*ReadMesh(params_t
*params
)
180 idx_t i
, j
, k
, l
, nfields
, ncon
, node
;
181 idx_t
*eptr
, *eind
, *ewgt
;
182 size_t nlines
, ntokens
;
183 char *line
=NULL
, *curstr
, *newstr
;
188 if (!gk_fexists(params
->filename
))
189 errexit("File %s does not exist!\n", params
->filename
);
193 /* get some file stats */
194 gk_getfilestats(params
->filename
, &nlines
, &ntokens
, NULL
, NULL
);
196 fpin
= gk_fopen(params
->filename
, "r", __func__
);
198 /* Skip comment lines until you get to the first valid line */
200 if (gk_getline(&line
, &lnlen
, fpin
) == -1)
201 errexit("Premature end of input file: file: %s\n", params
->filename
);
202 } while (line
[0] == '%');
206 nfields
= sscanf(line
, "%"SCIDX
" %"SCIDX
, &(mesh
->ne
), &(mesh
->ncon
));
209 errexit("The input file does not specify the number of elements.\n");
212 errexit("The supplied number of elements:%"PRIDX
" must be positive.\n", mesh
->ne
);
214 if (mesh
->ne
> nlines
)
215 errexit("The file has %zu lines which smaller than the number of "
216 "elements of %"PRIDX
" specified in the header line.\n", nlines
, mesh
->ne
);
219 eptr
= mesh
->eptr
= ismalloc(mesh
->ne
+1, 0, "ReadMesh: eptr");
220 eind
= mesh
->eind
= imalloc(ntokens
, "ReadMesh: eind");
221 ewgt
= mesh
->ewgt
= ismalloc((ncon
== 0 ? 1 : ncon
)*mesh
->ne
, 1, "ReadMesh: ewgt");
224 /*----------------------------------------------------------------------
226 *---------------------------------------------------------------------*/
227 for (eptr
[0]=0, k
=0, i
=0; i
<mesh
->ne
; i
++) {
229 if (gk_getline(&line
, &lnlen
, fpin
) == -1)
230 errexit("Premature end of input file while reading element %"PRIDX
".\n", i
+1);
231 } while (line
[0] == '%');
236 /* Read element weights */
237 for (l
=0; l
<ncon
; l
++) {
238 ewgt
[i
*ncon
+l
] = strtoidx(curstr
, &newstr
, 10);
239 if (newstr
== curstr
)
240 errexit("The line for vertex %"PRIDX
" does not have enough weights "
241 "for the %"PRIDX
" constraints.\n", i
+1, ncon
);
242 if (ewgt
[i
*ncon
+l
] < 0)
243 errexit("The weight for element %"PRIDX
" and constraint %"PRIDX
" must be >= 0\n", i
+1, l
);
248 node
= strtoidx(curstr
, &newstr
, 10);
249 if (newstr
== curstr
)
250 break; /* End of line */
254 errexit("Node %"PRIDX
" for element %"PRIDX
" is out of bounds\n", node
, i
+1);
262 mesh
->ncon
= (ncon
== 0 ? 1 : ncon
);
263 mesh
->nn
= imax(eptr
[mesh
->ne
], eind
)+1;
265 gk_free((void *)&line
, LTERM
);
271 /*************************************************************************/
272 /*! This function reads in the target partition weights. If no file is
273 specified the weights are set to 1/nparts */
274 /*************************************************************************/
275 void ReadTPwgts(params_t
*params
, idx_t ncon
)
277 idx_t i
, j
, from
, to
, fromcnum
, tocnum
, nleft
;
278 real_t awgt
=0.0, twgt
;
279 char *line
=NULL
, *curstr
, *newstr
;
283 params
->tpwgts
= rsmalloc(params
->nparts
*ncon
, -1.0, "ReadTPwgts: tpwgts");
285 if (params
->tpwgtsfile
== NULL
) {
286 for (i
=0; i
<params
->nparts
; i
++) {
287 for (j
=0; j
<ncon
; j
++)
288 params
->tpwgts
[i
*ncon
+j
] = 1.0/params
->nparts
;
293 if (!gk_fexists(params
->tpwgtsfile
))
294 errexit("Graph file %s does not exist!\n", params
->tpwgtsfile
);
296 fpin
= gk_fopen(params
->tpwgtsfile
, "r", "ReadTPwgts: tpwgtsfile");
298 while (gk_getline(&line
, &lnlen
, fpin
) != -1) {
299 gk_strchr_replace(line
, " ", "");
300 /* start extracting the fields */
305 from
= strtoidx(curstr
, &newstr
, 10);
306 if (newstr
== curstr
)
307 errexit("The 'from' component of line <%s> in the tpwgts file is incorrect.\n", line
);
310 if (curstr
[0] == '-') {
311 to
= strtoidx(curstr
+1, &newstr
, 10);
312 if (newstr
== curstr
)
313 errexit("The 'to' component of line <%s> in the tpwgts file is incorrect.\n", line
);
320 if (curstr
[0] == ':') {
321 fromcnum
= strtoidx(curstr
+1, &newstr
, 10);
322 if (newstr
== curstr
)
323 errexit("The 'fromcnum' component of line <%s> in the tpwgts file is incorrect.\n", line
);
326 if (curstr
[0] == '-') {
327 tocnum
= strtoidx(curstr
+1, &newstr
, 10);
328 if (newstr
== curstr
)
329 errexit("The 'tocnum' component of line <%s> in the tpwgts file is incorrect.\n", line
);
341 if (curstr
[0] == '=') {
342 awgt
= strtoreal(curstr
+1, &newstr
);
343 if (newstr
== curstr
)
344 errexit("The 'wgt' component of line <%s> in the tpwgts file is incorrect.\n", line
);
348 errexit("The 'wgt' component of line <%s> in the tpwgts file is missing.\n", line
);
351 /*printf("Read: %"PRIDX"-%"PRIDX":%"PRIDX"-%"PRIDX"=%"PRREAL"\n",
352 from, to, fromcnum, tocnum, awgt);*/
354 if (from
< 0 || to
< 0 || from
>= params
->nparts
|| to
>= params
->nparts
)
355 errexit("Invalid partition range for %"PRIDX
":%"PRIDX
"\n", from
, to
);
356 if (fromcnum
< 0 || tocnum
< 0 || fromcnum
>= ncon
|| tocnum
>= ncon
)
357 errexit("Invalid constraint number range for %"PRIDX
":%"PRIDX
"\n",
359 if (awgt
<= 0.0 || awgt
>= 1.0)
360 errexit("Invalid partition weight of %"PRREAL
"\n", awgt
);
361 for (i
=from
; i
<=to
; i
++) {
362 for (j
=fromcnum
; j
<=tocnum
; j
++)
363 params
->tpwgts
[i
*ncon
+j
] = awgt
;
369 /* Assign weight to the unspecified constraints x partitions */
370 for (j
=0; j
<ncon
; j
++) {
371 /* Sum up the specified weights for the jth constraint */
372 for (twgt
=0.0, nleft
=params
->nparts
, i
=0; i
<params
->nparts
; i
++) {
373 if (params
->tpwgts
[i
*ncon
+j
] > 0) {
374 twgt
+= params
->tpwgts
[i
*ncon
+j
];
379 /* Rescale the weights to be on the safe side */
381 rscale(params
->nparts
, 1.0/twgt
, params
->tpwgts
+j
, ncon
);
383 /* Assign the left-over weight to the remaining partitions */
386 errexit("The total specified target partition weights for constraint #%"PRIDX
387 " of %"PRREAL
" exceeds 1.0.\n", j
, twgt
);
389 awgt
= (1.0 - twgt
)/nleft
;
390 for (i
=0; i
<params
->nparts
; i
++)
391 params
->tpwgts
[i
*ncon
+j
] =
392 (params
->tpwgts
[i
*ncon
+j
] < 0 ? awgt
: params
->tpwgts
[i
*ncon
+j
]);
397 line
= NULL
; /* set to null to match behavior of gk_free() */
399 gk_free((void *)&line
, LTERM
);
404 /*************************************************************************/
405 /*! This function reads in a partition/ordering vector */
406 /**************************************************************************/
407 void ReadPOVector(graph_t
*graph
, char *filename
, idx_t
*vector
)
412 fpin
= gk_fopen(filename
, "r", __func__
);
413 for (i
=0; i
<graph
->nvtxs
; i
++) {
414 if (fscanf(fpin
, "%"SCIDX
"\n", vector
+i
) != 1)
415 errexit("[%s] Premature end of file %s at line %d [nvtxs: %d]\n",
416 __func__
, filename
, i
, graph
->nvtxs
);
422 /*************************************************************************/
423 /*! This function writes out the partition vector */
424 /*************************************************************************/
425 void WritePartition(char *fname
, idx_t
*part
, idx_t n
, idx_t nparts
)
429 char filename
[MAXLINE
];
431 sprintf(filename
, "%s.part.%"PRIDX
, fname
, nparts
);
433 fpout
= gk_fopen(filename
, "w", __func__
);
436 fprintf(fpout
,"%" PRIDX
"\n", part
[i
]);
442 /*************************************************************************/
443 /*! This function writes out the partition vectors for a mesh */
444 /*************************************************************************/
445 void WriteMeshPartition(char *fname
, idx_t nparts
, idx_t ne
, idx_t
*epart
,
446 idx_t nn
, idx_t
*npart
)
452 sprintf(filename
,"%s.epart.%"PRIDX
,fname
, nparts
);
454 fpout
= gk_fopen(filename
, "w", __func__
);
457 fprintf(fpout
,"%" PRIDX
"\n", epart
[i
]);
462 sprintf(filename
,"%s.npart.%"PRIDX
,fname
, nparts
);
464 fpout
= gk_fopen(filename
, "w", __func__
);
467 fprintf(fpout
, "%" PRIDX
"\n", npart
[i
]);
474 /*************************************************************************/
475 /*! This function writes out the permutation vector */
476 /*************************************************************************/
477 void WritePermutation(char *fname
, idx_t
*iperm
, idx_t n
)
481 char filename
[MAXLINE
];
483 sprintf(filename
, "%s.iperm", fname
);
485 fpout
= gk_fopen(filename
, "w", __func__
);
488 fprintf(fpout
, "%" PRIDX
"\n", iperm
[i
]);
494 /*************************************************************************/
495 /*! This function writes a graph into a file */
496 /*************************************************************************/
497 void WriteGraph(graph_t
*graph
, char *filename
)
499 idx_t i
, j
, nvtxs
, ncon
;
500 idx_t
*xadj
, *adjncy
, *adjwgt
, *vwgt
, *vsize
;
501 int hasvwgt
=0, hasewgt
=0, hasvsize
=0;
504 nvtxs
= graph
->nvtxs
;
507 adjncy
= graph
->adjncy
;
509 vsize
= graph
->vsize
;
510 adjwgt
= graph
->adjwgt
;
512 /* determine if the graph has non-unity vwgt, vsize, or adjwgt */
514 for (i
=0; i
<nvtxs
*ncon
; i
++) {
522 for (i
=0; i
<nvtxs
; i
++) {
530 for (i
=0; i
<xadj
[nvtxs
]; i
++) {
531 if (adjwgt
[i
] != 1) {
538 fpout
= gk_fopen(filename
, "w", __func__
);
540 /* write the header line */
541 fprintf(fpout
, "%"PRIDX
" %"PRIDX
, nvtxs
, xadj
[nvtxs
]/2);
542 if (hasvwgt
|| hasvsize
|| hasewgt
) {
543 fprintf(fpout
, " %d%d%d", hasvsize
, hasvwgt
, hasewgt
);
545 fprintf(fpout
, " %d", (int)graph
->ncon
);
549 /* write the rest of the graph */
550 for (i
=0; i
<nvtxs
; i
++) {
551 fprintf(fpout
, "\n");
553 fprintf(fpout
, " %"PRIDX
, vsize
[i
]);
556 for (j
=0; j
<ncon
; j
++)
557 fprintf(fpout
, " %"PRIDX
, vwgt
[i
*ncon
+j
]);
560 for (j
=xadj
[i
]; j
<xadj
[i
+1]; j
++) {
561 fprintf(fpout
, " %"PRIDX
, adjncy
[j
]+1);
563 fprintf(fpout
, " %"PRIDX
, adjwgt
[j
]);