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.
537 lines
16 KiB
537 lines
16 KiB
/**
|
|
@file
|
|
|
|
@ingroup cudd
|
|
|
|
@brief Functions to read in a matrix
|
|
|
|
@see cudd_addHarwell.c
|
|
|
|
@author Fabio Somenzi
|
|
|
|
@copyright@parblock
|
|
Copyright (c) 1995-2015, Regents of the University of Colorado
|
|
|
|
All rights reserved.
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
modification, are permitted provided that the following conditions
|
|
are met:
|
|
|
|
Redistributions of source code must retain the above copyright
|
|
notice, this list of conditions and the following disclaimer.
|
|
|
|
Redistributions in binary form must reproduce the above copyright
|
|
notice, this list of conditions and the following disclaimer in the
|
|
documentation and/or other materials provided with the distribution.
|
|
|
|
Neither the name of the University of Colorado nor the names of its
|
|
contributors may be used to endorse or promote products derived from
|
|
this software without specific prior written permission.
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
POSSIBILITY OF SUCH DAMAGE.
|
|
@endparblock
|
|
|
|
*/
|
|
|
|
#include "util.h"
|
|
#include "cuddInt.h"
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* Constant declarations */
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* Stucture declarations */
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* Type declarations */
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* Variable declarations */
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* Macro declarations */
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
/** \cond */
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* Static function prototypes */
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
/** \endcond */
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* Definition of exported functions */
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
|
|
/**
|
|
@brief Reads in a sparse matrix.
|
|
|
|
@details Reads in a sparse matrix specified in a simple format.
|
|
The first line of the input contains the numbers of rows and columns.
|
|
The remaining lines contain the elements of the matrix, one per line.
|
|
Given a background value
|
|
(specified by the background field of the manager), only the values
|
|
different from it are explicitly listed. Each foreground element is
|
|
described by two integers, i.e., the row and column number, and a
|
|
real number, i.e., the value.<p>
|
|
Cudd_addRead produces an %ADD that depends on two sets of variables: x
|
|
and y. The x variables (x\[0\] ... x\[nx-1\]) encode the row index and
|
|
the y variables (y\[0\] ... y\[ny-1\]) encode the column index.
|
|
x\[0\] and y\[0\] are the most significant bits in the indices.
|
|
The variables may already exist or may be created by the function.
|
|
The index of x\[i\] is bx+i*sx, and the index of y\[i\] is by+i*sy.<p>
|
|
On input, nx and ny hold the numbers
|
|
of row and column variables already in existence. On output, they
|
|
hold the numbers of row and column variables actually used by the
|
|
matrix. When Cudd_addRead creates the variable arrays,
|
|
the index of x\[i\] is bx+i*sx, and the index of y\[i\] is by+i*sy.
|
|
When some variables already exist Cudd_addRead expects the indices
|
|
of the existing x variables to be bx+i*sx, and the indices of the
|
|
existing y variables to be by+i*sy.<p>
|
|
m and n are set to the numbers of rows and columns of the
|
|
matrix. Their values on input are immaterial.
|
|
The %ADD for the sparse matrix is returned in E, and its reference
|
|
count is > 0.
|
|
|
|
@return 1 in case of success; 0 otherwise.
|
|
|
|
@sideeffect nx and ny are set to the numbers of row and column
|
|
variables. m and n are set to the numbers of rows and columns. x and y
|
|
are possibly extended to represent the array of row and column
|
|
variables. Similarly for xn and yn_, which hold on return from
|
|
Cudd_addRead the complements of the row and column variables.
|
|
|
|
@see Cudd_addHarwell Cudd_bddRead
|
|
|
|
*/
|
|
int
|
|
Cudd_addRead(
|
|
FILE * fp /**< input file pointer */,
|
|
DdManager * dd /**< %DD manager */,
|
|
DdNode ** E /**< characteristic function of the graph */,
|
|
DdNode *** x /**< array of row variables */,
|
|
DdNode *** y /**< array of column variables */,
|
|
DdNode *** xn /**< array of complemented row variables */,
|
|
DdNode *** yn_ /**< array of complemented column variables */,
|
|
int * nx /**< number or row variables */,
|
|
int * ny /**< number or column variables */,
|
|
int * m /**< number of rows */,
|
|
int * n /**< number of columns */,
|
|
int bx /**< first index of row variables */,
|
|
int sx /**< step of row variables */,
|
|
int by /**< first index of column variables */,
|
|
int sy /**< step of column variables */)
|
|
{
|
|
DdNode *one, *zero;
|
|
DdNode *w, *neW;
|
|
DdNode *minterm1;
|
|
int u, v, err, i, nv;
|
|
int lnx, lny;
|
|
CUDD_VALUE_TYPE val;
|
|
DdNode **lx, **ly, **lxn, **lyn;
|
|
|
|
one = DD_ONE(dd);
|
|
zero = DD_ZERO(dd);
|
|
|
|
err = fscanf(fp, "%d %d", &u, &v);
|
|
if (err == EOF) {
|
|
return(0);
|
|
} else if (err != 2) {
|
|
return(0);
|
|
}
|
|
|
|
*m = u;
|
|
/* Compute the number of x variables. */
|
|
lx = *x; lxn = *xn;
|
|
u--; /* row and column numbers start from 0 */
|
|
for (lnx=0; u > 0; lnx++) {
|
|
u >>= 1;
|
|
}
|
|
/* Here we rely on the fact that REALLOC of a null pointer is
|
|
** translates to an ALLOC.
|
|
*/
|
|
if (lnx > *nx) {
|
|
*x = lx = REALLOC(DdNode *, *x, lnx);
|
|
if (lx == NULL) {
|
|
dd->errorCode = CUDD_MEMORY_OUT;
|
|
return(0);
|
|
}
|
|
*xn = lxn = REALLOC(DdNode *, *xn, lnx);
|
|
if (lxn == NULL) {
|
|
dd->errorCode = CUDD_MEMORY_OUT;
|
|
return(0);
|
|
}
|
|
}
|
|
|
|
*n = v;
|
|
/* Compute the number of y variables. */
|
|
ly = *y; lyn = *yn_;
|
|
v--; /* row and column numbers start from 0 */
|
|
for (lny=0; v > 0; lny++) {
|
|
v >>= 1;
|
|
}
|
|
/* Here we rely on the fact that REALLOC of a null pointer is
|
|
** translates to an ALLOC.
|
|
*/
|
|
if (lny > *ny) {
|
|
*y = ly = REALLOC(DdNode *, *y, lny);
|
|
if (ly == NULL) {
|
|
dd->errorCode = CUDD_MEMORY_OUT;
|
|
return(0);
|
|
}
|
|
*yn_ = lyn = REALLOC(DdNode *, *yn_, lny);
|
|
if (lyn == NULL) {
|
|
dd->errorCode = CUDD_MEMORY_OUT;
|
|
return(0);
|
|
}
|
|
}
|
|
|
|
/* Create all new variables. */
|
|
for (i = *nx, nv = bx + (*nx) * sx; i < lnx; i++, nv += sx) {
|
|
do {
|
|
dd->reordered = 0;
|
|
lx[i] = cuddUniqueInter(dd, nv, one, zero);
|
|
} while (dd->reordered == 1);
|
|
if (lx[i] == NULL) {
|
|
if (dd->errorCode == CUDD_TIMEOUT_EXPIRED && dd->timeoutHandler) {
|
|
dd->timeoutHandler(dd, dd->tohArg);
|
|
}
|
|
return(0);
|
|
}
|
|
cuddRef(lx[i]);
|
|
do {
|
|
dd->reordered = 0;
|
|
lxn[i] = cuddUniqueInter(dd, nv, zero, one);
|
|
} while (dd->reordered == 1);
|
|
if (lxn[i] == NULL) {
|
|
if (dd->errorCode == CUDD_TIMEOUT_EXPIRED && dd->timeoutHandler) {
|
|
dd->timeoutHandler(dd, dd->tohArg);
|
|
}
|
|
return(0);
|
|
}
|
|
cuddRef(lxn[i]);
|
|
}
|
|
for (i = *ny, nv = by + (*ny) * sy; i < lny; i++, nv += sy) {
|
|
do {
|
|
dd->reordered = 0;
|
|
ly[i] = cuddUniqueInter(dd, nv, one, zero);
|
|
} while (dd->reordered == 1);
|
|
if (ly[i] == NULL) {
|
|
if (dd->errorCode == CUDD_TIMEOUT_EXPIRED && dd->timeoutHandler) {
|
|
dd->timeoutHandler(dd, dd->tohArg);
|
|
}
|
|
return(0);
|
|
}
|
|
cuddRef(ly[i]);
|
|
do {
|
|
dd->reordered = 0;
|
|
lyn[i] = cuddUniqueInter(dd, nv, zero, one);
|
|
} while (dd->reordered == 1);
|
|
if (lyn[i] == NULL) {
|
|
if (dd->errorCode == CUDD_TIMEOUT_EXPIRED && dd->timeoutHandler) {
|
|
dd->timeoutHandler(dd, dd->tohArg);
|
|
}
|
|
return(0);
|
|
}
|
|
cuddRef(lyn[i]);
|
|
}
|
|
*nx = lnx;
|
|
*ny = lny;
|
|
|
|
*E = dd->background; /* this call will never cause reordering */
|
|
cuddRef(*E);
|
|
|
|
while (! feof(fp)) {
|
|
err = fscanf(fp, "%d %d %lf", &u, &v, &val);
|
|
if (err == EOF) {
|
|
break;
|
|
} else if (err != 3) {
|
|
return(0);
|
|
} else if (u >= *m || v >= *n || u < 0 || v < 0) {
|
|
return(0);
|
|
}
|
|
|
|
minterm1 = one; cuddRef(minterm1);
|
|
|
|
/* Build minterm1 corresponding to this arc */
|
|
for (i = lnx - 1; i>=0; i--) {
|
|
if (u & 1) {
|
|
w = Cudd_addApply(dd, Cudd_addTimes, minterm1, lx[i]);
|
|
} else {
|
|
w = Cudd_addApply(dd, Cudd_addTimes, minterm1, lxn[i]);
|
|
}
|
|
if (w == NULL) {
|
|
Cudd_RecursiveDeref(dd, minterm1);
|
|
return(0);
|
|
}
|
|
cuddRef(w);
|
|
Cudd_RecursiveDeref(dd, minterm1);
|
|
minterm1 = w;
|
|
u >>= 1;
|
|
}
|
|
for (i = lny - 1; i>=0; i--) {
|
|
if (v & 1) {
|
|
w = Cudd_addApply(dd, Cudd_addTimes, minterm1, ly[i]);
|
|
} else {
|
|
w = Cudd_addApply(dd, Cudd_addTimes, minterm1, lyn[i]);
|
|
}
|
|
if (w == NULL) {
|
|
Cudd_RecursiveDeref(dd, minterm1);
|
|
return(0);
|
|
}
|
|
cuddRef(w);
|
|
Cudd_RecursiveDeref(dd, minterm1);
|
|
minterm1 = w;
|
|
v >>= 1;
|
|
}
|
|
/* Create new constant node if necessary.
|
|
** This call will never cause reordering.
|
|
*/
|
|
neW = cuddUniqueConst(dd, val);
|
|
if (neW == NULL) {
|
|
Cudd_RecursiveDeref(dd, minterm1);
|
|
return(0);
|
|
}
|
|
cuddRef(neW);
|
|
|
|
w = Cudd_addIte(dd, minterm1, neW, *E);
|
|
if (w == NULL) {
|
|
Cudd_RecursiveDeref(dd, minterm1);
|
|
Cudd_RecursiveDeref(dd, neW);
|
|
return(0);
|
|
}
|
|
cuddRef(w);
|
|
Cudd_RecursiveDeref(dd, minterm1);
|
|
Cudd_RecursiveDeref(dd, neW);
|
|
Cudd_RecursiveDeref(dd, *E);
|
|
*E = w;
|
|
}
|
|
return(1);
|
|
|
|
} /* end of Cudd_addRead */
|
|
|
|
|
|
/**
|
|
@brief Reads in a graph (without labels) given as a list of arcs.
|
|
|
|
@details Reads in a graph (without labels) given as an adjacency
|
|
matrix. The first line of the input contains the numbers of rows and
|
|
columns of the adjacency matrix. The remaining lines contain the arcs
|
|
of the graph, one per line. Each arc is described by two integers,
|
|
i.e., the row and column number, or the indices of the two endpoints.
|
|
Cudd_bddRead produces a %BDD that depends on two sets of variables: x
|
|
and y. The x variables (x\[0\] ... x\[nx-1\]) encode
|
|
the row index and the y variables (y\[0\] ... y\[ny-1\]) encode the
|
|
column index. x\[0\] and y\[0\] are the most significant bits in the
|
|
indices.
|
|
The variables may already exist or may be created by the function.
|
|
The index of x\[i\] is bx+i*sx, and the index of y\[i\] is by+i*sy.<p>
|
|
On input, nx and ny hold the numbers of row and column variables already
|
|
in existence. On output, they hold the numbers of row and column
|
|
variables actually used by the matrix. When Cudd_bddRead creates the
|
|
variable arrays, the index of x\[i\] is bx+i*sx, and the index of
|
|
y\[i\] is by+i*sy. When some variables already exist, Cudd_bddRead
|
|
expects the indices of the existing x variables to be bx+i*sx, and the
|
|
indices of the existing y variables to be by+i*sy.<p>
|
|
m and n are set to the numbers of rows and columns of the
|
|
matrix. Their values on input are immaterial. The %BDD for the graph
|
|
is returned in E, and its reference count is > 0.
|
|
|
|
@return 1 in case of success; 0 otherwise.
|
|
|
|
@sideeffect nx and ny are set to the numbers of row and column
|
|
variables. m and n are set to the numbers of rows and columns. x and y
|
|
are possibly extended to represent the array of row and column
|
|
variables.
|
|
|
|
@see Cudd_addHarwell Cudd_addRead
|
|
|
|
*/
|
|
int
|
|
Cudd_bddRead(
|
|
FILE * fp /**< input file pointer */,
|
|
DdManager * dd /**< DD manager */,
|
|
DdNode ** E /**< characteristic function of the graph */,
|
|
DdNode *** x /**< array of row variables */,
|
|
DdNode *** y /**< array of column variables */,
|
|
int * nx /**< number or row variables */,
|
|
int * ny /**< number or column variables */,
|
|
int * m /**< number of rows */,
|
|
int * n /**< number of columns */,
|
|
int bx /**< first index of row variables */,
|
|
int sx /**< step of row variables */,
|
|
int by /**< first index of column variables */,
|
|
int sy /**< step of column variables */)
|
|
{
|
|
DdNode *one, *zero;
|
|
DdNode *w;
|
|
DdNode *minterm1;
|
|
int u, v, err, i, nv;
|
|
int lnx, lny;
|
|
DdNode **lx, **ly;
|
|
|
|
one = DD_ONE(dd);
|
|
zero = Cudd_Not(one);
|
|
|
|
err = fscanf(fp, "%d %d", &u, &v);
|
|
if (err == EOF) {
|
|
return(0);
|
|
} else if (err != 2) {
|
|
return(0);
|
|
}
|
|
|
|
*m = u;
|
|
/* Compute the number of x variables. */
|
|
lx = *x;
|
|
u--; /* row and column numbers start from 0 */
|
|
for (lnx=0; u > 0; lnx++) {
|
|
u >>= 1;
|
|
}
|
|
if (lnx > *nx) {
|
|
*x = lx = REALLOC(DdNode *, *x, lnx);
|
|
if (lx == NULL) {
|
|
dd->errorCode = CUDD_MEMORY_OUT;
|
|
return(0);
|
|
}
|
|
}
|
|
|
|
*n = v;
|
|
/* Compute the number of y variables. */
|
|
ly = *y;
|
|
v--; /* row and column numbers start from 0 */
|
|
for (lny=0; v > 0; lny++) {
|
|
v >>= 1;
|
|
}
|
|
if (lny > *ny) {
|
|
*y = ly = REALLOC(DdNode *, *y, lny);
|
|
if (ly == NULL) {
|
|
dd->errorCode = CUDD_MEMORY_OUT;
|
|
return(0);
|
|
}
|
|
}
|
|
|
|
/* Create all new variables. */
|
|
for (i = *nx, nv = bx + (*nx) * sx; i < lnx; i++, nv += sx) {
|
|
do {
|
|
dd->reordered = 0;
|
|
lx[i] = cuddUniqueInter(dd, nv, one, zero);
|
|
} while (dd->reordered == 1);
|
|
if (lx[i] == NULL) {
|
|
if (dd->errorCode == CUDD_TIMEOUT_EXPIRED && dd->timeoutHandler) {
|
|
dd->timeoutHandler(dd, dd->tohArg);
|
|
}
|
|
return(0);
|
|
}
|
|
cuddRef(lx[i]);
|
|
}
|
|
for (i = *ny, nv = by + (*ny) * sy; i < lny; i++, nv += sy) {
|
|
do {
|
|
dd->reordered = 0;
|
|
ly[i] = cuddUniqueInter(dd, nv, one, zero);
|
|
} while (dd->reordered == 1);
|
|
if (ly[i] == NULL) {
|
|
if (dd->errorCode == CUDD_TIMEOUT_EXPIRED && dd->timeoutHandler) {
|
|
dd->timeoutHandler(dd, dd->tohArg);
|
|
}
|
|
return(0);
|
|
}
|
|
cuddRef(ly[i]);
|
|
}
|
|
*nx = lnx;
|
|
*ny = lny;
|
|
|
|
*E = zero; /* this call will never cause reordering */
|
|
cuddRef(*E);
|
|
|
|
while (! feof(fp)) {
|
|
err = fscanf(fp, "%d %d", &u, &v);
|
|
if (err == EOF) {
|
|
break;
|
|
} else if (err != 2) {
|
|
return(0);
|
|
} else if (u >= *m || v >= *n || u < 0 || v < 0) {
|
|
return(0);
|
|
}
|
|
|
|
minterm1 = one; cuddRef(minterm1);
|
|
|
|
/* Build minterm1 corresponding to this arc. */
|
|
for (i = lnx - 1; i>=0; i--) {
|
|
if (u & 1) {
|
|
w = Cudd_bddAnd(dd, minterm1, lx[i]);
|
|
} else {
|
|
w = Cudd_bddAnd(dd, minterm1, Cudd_Not(lx[i]));
|
|
}
|
|
if (w == NULL) {
|
|
Cudd_RecursiveDeref(dd, minterm1);
|
|
return(0);
|
|
}
|
|
cuddRef(w);
|
|
Cudd_RecursiveDeref(dd,minterm1);
|
|
minterm1 = w;
|
|
u >>= 1;
|
|
}
|
|
for (i = lny - 1; i>=0; i--) {
|
|
if (v & 1) {
|
|
w = Cudd_bddAnd(dd, minterm1, ly[i]);
|
|
} else {
|
|
w = Cudd_bddAnd(dd, minterm1, Cudd_Not(ly[i]));
|
|
}
|
|
if (w == NULL) {
|
|
Cudd_RecursiveDeref(dd, minterm1);
|
|
return(0);
|
|
}
|
|
cuddRef(w);
|
|
Cudd_RecursiveDeref(dd, minterm1);
|
|
minterm1 = w;
|
|
v >>= 1;
|
|
}
|
|
|
|
w = Cudd_bddAnd(dd, Cudd_Not(minterm1), Cudd_Not(*E));
|
|
if (w == NULL) {
|
|
Cudd_RecursiveDeref(dd, minterm1);
|
|
return(0);
|
|
}
|
|
w = Cudd_Not(w);
|
|
cuddRef(w);
|
|
Cudd_RecursiveDeref(dd, minterm1);
|
|
Cudd_RecursiveDeref(dd, *E);
|
|
*E = w;
|
|
}
|
|
return(1);
|
|
|
|
} /* end of Cudd_bddRead */
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* Definition of internal functions */
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* Definition of static functions */
|
|
/*---------------------------------------------------------------------------*/
|
|
|