emergency commit
[cl-cudd.git] / distr / cudd / cuddHarwell.c
blob57ed7579b77ce81c14ed4a6da1b29199497f5538
1 /**CFile***********************************************************************
3 FileName [cuddHarwell.c]
5 PackageName [cudd]
7 Synopsis [Function to read a matrix in Harwell format.]
9 Description [External procedures included in this module:
10 <ul>
11 <li> Cudd_addHarwell()
12 </ul>
15 Author [Fabio Somenzi]
17 Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado
19 All rights reserved.
21 Redistribution and use in source and binary forms, with or without
22 modification, are permitted provided that the following conditions
23 are met:
25 Redistributions of source code must retain the above copyright
26 notice, this list of conditions and the following disclaimer.
28 Redistributions in binary form must reproduce the above copyright
29 notice, this list of conditions and the following disclaimer in the
30 documentation and/or other materials provided with the distribution.
32 Neither the name of the University of Colorado nor the names of its
33 contributors may be used to endorse or promote products derived from
34 this software without specific prior written permission.
36 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
37 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
38 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
39 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
40 COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
41 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
42 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
43 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
44 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
45 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
46 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
47 POSSIBILITY OF SUCH DAMAGE.]
49 ******************************************************************************/
51 #include "util.h"
52 #include "cuddInt.h"
54 /*---------------------------------------------------------------------------*/
55 /* Constant declarations */
56 /*---------------------------------------------------------------------------*/
59 /*---------------------------------------------------------------------------*/
60 /* Stucture declarations */
61 /*---------------------------------------------------------------------------*/
64 /*---------------------------------------------------------------------------*/
65 /* Type declarations */
66 /*---------------------------------------------------------------------------*/
69 /*---------------------------------------------------------------------------*/
70 /* Variable declarations */
71 /*---------------------------------------------------------------------------*/
73 #ifndef lint
74 static char rcsid[] DD_UNUSED = "$Id: cuddHarwell.c,v 1.9 2004/08/13 18:04:49 fabio Exp $";
75 #endif
77 /*---------------------------------------------------------------------------*/
78 /* Macro declarations */
79 /*---------------------------------------------------------------------------*/
82 /**AutomaticStart*************************************************************/
84 /*---------------------------------------------------------------------------*/
85 /* Static function prototypes */
86 /*---------------------------------------------------------------------------*/
89 /**AutomaticEnd***************************************************************/
92 /*---------------------------------------------------------------------------*/
93 /* Definition of exported functions */
94 /*---------------------------------------------------------------------------*/
96 /**Function********************************************************************
98 Synopsis [Reads in a matrix in the format of the Harwell-Boeing
99 benchmark suite.]
101 Description [Reads in a matrix in the format of the Harwell-Boeing
102 benchmark suite. The variables are ordered as follows:
103 <blockquote>
104 x\[0\] y\[0\] x\[1\] y\[1\] ...
105 </blockquote>
106 0 is the most significant bit. On input, nx and ny hold the numbers
107 of row and column variables already in existence. On output, they
108 hold the numbers of row and column variables actually used by the
109 matrix. m and n are set to the numbers of rows and columns of the
110 matrix. Their values on input are immaterial. Returns 1 on
111 success; 0 otherwise. The ADD for the sparse matrix is returned in
112 E, and its reference count is > 0.]
114 SideEffects [None]
116 SeeAlso [Cudd_addRead Cudd_bddRead]
118 ******************************************************************************/
120 Cudd_addHarwell(
121 FILE * fp /* pointer to the input file */,
122 DdManager * dd /* DD manager */,
123 DdNode ** E /* characteristic function of the graph */,
124 DdNode *** x /* array of row variables */,
125 DdNode *** y /* array of column variables */,
126 DdNode *** xn /* array of complemented row variables */,
127 DdNode *** yn_ /* array of complemented column variables */,
128 int * nx /* number or row variables */,
129 int * ny /* number or column variables */,
130 int * m /* number of rows */,
131 int * n /* number of columns */,
132 int bx /* first index of row variables */,
133 int sx /* step of row variables */,
134 int by /* first index of column variables */,
135 int sy /* step of column variables */,
136 int pr /* verbosity level */)
138 DdNode *one, *zero;
139 DdNode *w;
140 DdNode *cubex, *cubey, *minterm1;
141 int u, v, err, i, j, nv;
142 double val;
143 DdNode **lx, **ly, **lxn, **lyn; /* local copies of x, y, xn, yn_ */
144 int lnx, lny; /* local copies of nx and ny */
145 char title[73], key[9], mxtype[4], rhstyp[4];
146 int totcrd, ptrcrd, indcrd, valcrd, rhscrd,
147 nrow, ncol, nnzero, neltvl,
148 nrhs, nrhsix;
149 int *colptr, *rowind;
150 #if 0
151 int nguess, nexact;
152 int *rhsptr, *rhsind;
153 #endif
155 if (*nx < 0 || *ny < 0) return(0);
157 one = DD_ONE(dd);
158 zero = DD_ZERO(dd);
160 /* Read the header */
161 err = fscanf(fp, "%72c %8c", title, key);
162 if (err == EOF) {
163 return(0);
164 } else if (err != 2) {
165 return(0);
167 title[72] = (char) 0;
168 key[8] = (char) 0;
170 err = fscanf(fp, "%d %d %d %d %d", &totcrd, &ptrcrd, &indcrd,
171 &valcrd, &rhscrd);
172 if (err == EOF) {
173 return(0);
174 } else if (err != 5) {
175 return(0);
178 err = fscanf(fp, "%3s %d %d %d %d", mxtype, &nrow, &ncol,
179 &nnzero, &neltvl);
180 if (err == EOF) {
181 return(0);
182 } else if (err != 5) {
183 return(0);
186 /* Skip FORTRAN formats */
187 if (rhscrd == 0) {
188 err = fscanf(fp, "%*s %*s %*s \n");
189 } else {
190 err = fscanf(fp, "%*s %*s %*s %*s \n");
192 if (err == EOF) {
193 return(0);
194 } else if (err != 0) {
195 return(0);
198 /* Print out some stuff if requested to be verbose */
199 if (pr>0) {
200 (void) fprintf(dd->out,"%s: type %s, %d rows, %d columns, %d entries\n", key,
201 mxtype, nrow, ncol, nnzero);
202 if (pr>1) (void) fprintf(dd->out,"%s\n", title);
205 /* Check matrix type */
206 if (mxtype[0] != 'R' || mxtype[1] != 'U' || mxtype[2] != 'A') {
207 (void) fprintf(dd->err,"%s: Illegal matrix type: %s\n",
208 key, mxtype);
209 return(0);
211 if (neltvl != 0) return(0);
213 /* Read optional 5-th line */
214 if (rhscrd != 0) {
215 err = fscanf(fp, "%3c %d %d", rhstyp, &nrhs, &nrhsix);
216 if (err == EOF) {
217 return(0);
218 } else if (err != 3) {
219 return(0);
221 rhstyp[3] = (char) 0;
222 if (rhstyp[0] != 'F') {
223 (void) fprintf(dd->err,
224 "%s: Sparse right-hand side not yet supported\n", key);
225 return(0);
227 if (pr>0) (void) fprintf(dd->out,"%d right-hand side(s)\n", nrhs);
228 } else {
229 nrhs = 0;
232 /* Compute the number of variables */
234 /* row and column numbers start from 0 */
235 u = nrow - 1;
236 for (i=0; u > 0; i++) {
237 u >>= 1;
239 lnx = i;
240 if (nrhs == 0) {
241 v = ncol - 1;
242 } else {
243 v = 2* (ddMax(ncol, nrhs) - 1);
245 for (i=0; v > 0; i++) {
246 v >>= 1;
248 lny = i;
250 /* Allocate or reallocate arrays for variables as needed */
251 if (*nx == 0) {
252 if (lnx > 0) {
253 *x = lx = ALLOC(DdNode *,lnx);
254 if (lx == NULL) {
255 dd->errorCode = CUDD_MEMORY_OUT;
256 return(0);
258 *xn = lxn = ALLOC(DdNode *,lnx);
259 if (lxn == NULL) {
260 dd->errorCode = CUDD_MEMORY_OUT;
261 return(0);
263 } else {
264 *x = *xn = NULL;
266 } else if (lnx > *nx) {
267 *x = lx = REALLOC(DdNode *, *x, lnx);
268 if (lx == NULL) {
269 dd->errorCode = CUDD_MEMORY_OUT;
270 return(0);
272 *xn = lxn = REALLOC(DdNode *, *xn, lnx);
273 if (lxn == NULL) {
274 dd->errorCode = CUDD_MEMORY_OUT;
275 return(0);
277 } else {
278 lx = *x;
279 lxn = *xn;
281 if (*ny == 0) {
282 if (lny >0) {
283 *y = ly = ALLOC(DdNode *,lny);
284 if (ly == NULL) {
285 dd->errorCode = CUDD_MEMORY_OUT;
286 return(0);
288 *yn_ = lyn = ALLOC(DdNode *,lny);
289 if (lyn == NULL) {
290 dd->errorCode = CUDD_MEMORY_OUT;
291 return(0);
293 } else {
294 *y = *yn_ = NULL;
296 } else if (lny > *ny) {
297 *y = ly = REALLOC(DdNode *, *y, lny);
298 if (ly == NULL) {
299 dd->errorCode = CUDD_MEMORY_OUT;
300 return(0);
302 *yn_ = lyn = REALLOC(DdNode *, *yn_, lny);
303 if (lyn == NULL) {
304 dd->errorCode = CUDD_MEMORY_OUT;
305 return(0);
307 } else {
308 ly = *y;
309 lyn = *yn_;
312 /* Create new variables as needed */
313 for (i= *nx,nv=bx+(*nx)*sx; i < lnx; i++,nv+=sx) {
314 do {
315 dd->reordered = 0;
316 lx[i] = cuddUniqueInter(dd, nv, one, zero);
317 } while (dd->reordered == 1);
318 if (lx[i] == NULL) return(0);
319 cuddRef(lx[i]);
320 do {
321 dd->reordered = 0;
322 lxn[i] = cuddUniqueInter(dd, nv, zero, one);
323 } while (dd->reordered == 1);
324 if (lxn[i] == NULL) return(0);
325 cuddRef(lxn[i]);
327 for (i= *ny,nv=by+(*ny)*sy; i < lny; i++,nv+=sy) {
328 do {
329 dd->reordered = 0;
330 ly[i] = cuddUniqueInter(dd, nv, one, zero);
331 } while (dd->reordered == 1);
332 if (ly[i] == NULL) return(0);
333 cuddRef(ly[i]);
334 do {
335 dd->reordered = 0;
336 lyn[i] = cuddUniqueInter(dd, nv, zero, one);
337 } while (dd->reordered == 1);
338 if (lyn[i] == NULL) return(0);
339 cuddRef(lyn[i]);
342 /* Update matrix parameters */
343 *nx = lnx;
344 *ny = lny;
345 *m = nrow;
346 if (nrhs == 0) {
347 *n = ncol;
348 } else {
349 *n = (1 << (lny - 1)) + nrhs;
352 /* Read structure data */
353 colptr = ALLOC(int, ncol+1);
354 if (colptr == NULL) {
355 dd->errorCode = CUDD_MEMORY_OUT;
356 return(0);
358 rowind = ALLOC(int, nnzero);
359 if (rowind == NULL) {
360 dd->errorCode = CUDD_MEMORY_OUT;
361 return(0);
364 for (i=0; i<ncol+1; i++) {
365 err = fscanf(fp, " %d ", &u);
366 if (err == EOF){
367 FREE(colptr);
368 FREE(rowind);
369 return(0);
370 } else if (err != 1) {
371 FREE(colptr);
372 FREE(rowind);
373 return(0);
375 colptr[i] = u - 1;
377 if (colptr[0] != 0) {
378 (void) fprintf(dd->err,"%s: Unexpected colptr[0] (%d)\n",
379 key,colptr[0]);
380 FREE(colptr);
381 FREE(rowind);
382 return(0);
384 for (i=0; i<nnzero; i++) {
385 err = fscanf(fp, " %d ", &u);
386 if (err == EOF){
387 FREE(colptr);
388 FREE(rowind);
389 return(0);
390 } else if (err != 1) {
391 FREE(colptr);
392 FREE(rowind);
393 return(0);
395 rowind[i] = u - 1;
398 *E = zero; cuddRef(*E);
400 for (j=0; j<ncol; j++) {
401 v = j;
402 cubey = one; cuddRef(cubey);
403 for (nv = lny - 1; nv>=0; nv--) {
404 if (v & 1) {
405 w = Cudd_addApply(dd, Cudd_addTimes, cubey, ly[nv]);
406 } else {
407 w = Cudd_addApply(dd, Cudd_addTimes, cubey, lyn[nv]);
409 if (w == NULL) {
410 Cudd_RecursiveDeref(dd, cubey);
411 FREE(colptr);
412 FREE(rowind);
413 return(0);
415 cuddRef(w);
416 Cudd_RecursiveDeref(dd, cubey);
417 cubey = w;
418 v >>= 1;
420 for (i=colptr[j]; i<colptr[j+1]; i++) {
421 u = rowind[i];
422 err = fscanf(fp, " %lf ", &val);
423 if (err == EOF || err != 1){
424 Cudd_RecursiveDeref(dd, cubey);
425 FREE(colptr);
426 FREE(rowind);
427 return(0);
429 /* Create new Constant node if necessary */
430 cubex = cuddUniqueConst(dd, (CUDD_VALUE_TYPE) val);
431 if (cubex == NULL) {
432 Cudd_RecursiveDeref(dd, cubey);
433 FREE(colptr);
434 FREE(rowind);
435 return(0);
437 cuddRef(cubex);
439 for (nv = lnx - 1; nv>=0; nv--) {
440 if (u & 1) {
441 w = Cudd_addApply(dd, Cudd_addTimes, cubex, lx[nv]);
442 } else {
443 w = Cudd_addApply(dd, Cudd_addTimes, cubex, lxn[nv]);
445 if (w == NULL) {
446 Cudd_RecursiveDeref(dd, cubey);
447 Cudd_RecursiveDeref(dd, cubex);
448 FREE(colptr);
449 FREE(rowind);
450 return(0);
452 cuddRef(w);
453 Cudd_RecursiveDeref(dd, cubex);
454 cubex = w;
455 u >>= 1;
457 minterm1 = Cudd_addApply(dd, Cudd_addTimes, cubey, cubex);
458 if (minterm1 == NULL) {
459 Cudd_RecursiveDeref(dd, cubey);
460 Cudd_RecursiveDeref(dd, cubex);
461 FREE(colptr);
462 FREE(rowind);
463 return(0);
465 cuddRef(minterm1);
466 Cudd_RecursiveDeref(dd, cubex);
467 w = Cudd_addApply(dd, Cudd_addPlus, *E, minterm1);
468 if (w == NULL) {
469 Cudd_RecursiveDeref(dd, cubey);
470 FREE(colptr);
471 FREE(rowind);
472 return(0);
474 cuddRef(w);
475 Cudd_RecursiveDeref(dd, minterm1);
476 Cudd_RecursiveDeref(dd, *E);
477 *E = w;
479 Cudd_RecursiveDeref(dd, cubey);
481 FREE(colptr);
482 FREE(rowind);
484 /* Read right-hand sides */
485 for (j=0; j<nrhs; j++) {
486 v = j + (1<< (lny-1));
487 cubey = one; cuddRef(cubey);
488 for (nv = lny - 1; nv>=0; nv--) {
489 if (v & 1) {
490 w = Cudd_addApply(dd, Cudd_addTimes, cubey, ly[nv]);
491 } else {
492 w = Cudd_addApply(dd, Cudd_addTimes, cubey, lyn[nv]);
494 if (w == NULL) {
495 Cudd_RecursiveDeref(dd, cubey);
496 return(0);
498 cuddRef(w);
499 Cudd_RecursiveDeref(dd, cubey);
500 cubey = w;
501 v >>= 1;
503 for (i=0; i<nrow; i++) {
504 u = i;
505 err = fscanf(fp, " %lf ", &val);
506 if (err == EOF || err != 1){
507 Cudd_RecursiveDeref(dd, cubey);
508 return(0);
510 /* Create new Constant node if necessary */
511 if (val == (double) 0.0) continue;
512 cubex = cuddUniqueConst(dd, (CUDD_VALUE_TYPE) val);
513 if (cubex == NULL) {
514 Cudd_RecursiveDeref(dd, cubey);
515 return(0);
517 cuddRef(cubex);
519 for (nv = lnx - 1; nv>=0; nv--) {
520 if (u & 1) {
521 w = Cudd_addApply(dd, Cudd_addTimes, cubex, lx[nv]);
522 } else {
523 w = Cudd_addApply(dd, Cudd_addTimes, cubex, lxn[nv]);
525 if (w == NULL) {
526 Cudd_RecursiveDeref(dd, cubey);
527 Cudd_RecursiveDeref(dd, cubex);
528 return(0);
530 cuddRef(w);
531 Cudd_RecursiveDeref(dd, cubex);
532 cubex = w;
533 u >>= 1;
535 minterm1 = Cudd_addApply(dd, Cudd_addTimes, cubey, cubex);
536 if (minterm1 == NULL) {
537 Cudd_RecursiveDeref(dd, cubey);
538 Cudd_RecursiveDeref(dd, cubex);
539 return(0);
541 cuddRef(minterm1);
542 Cudd_RecursiveDeref(dd, cubex);
543 w = Cudd_addApply(dd, Cudd_addPlus, *E, minterm1);
544 if (w == NULL) {
545 Cudd_RecursiveDeref(dd, cubey);
546 return(0);
548 cuddRef(w);
549 Cudd_RecursiveDeref(dd, minterm1);
550 Cudd_RecursiveDeref(dd, *E);
551 *E = w;
553 Cudd_RecursiveDeref(dd, cubey);
556 return(1);
558 } /* end of Cudd_addHarwell */
561 /*---------------------------------------------------------------------------*/
562 /* Definition of internal functions */
563 /*---------------------------------------------------------------------------*/
565 /*---------------------------------------------------------------------------*/
566 /* Definition of static functions */
567 /*---------------------------------------------------------------------------*/