1 /**CFile***********************************************************************
3 FileName [cuddZddUtil.c]
7 Synopsis [Utility functions for ZDDs.]
9 Description [External procedures included in this module:
11 <li> Cudd_zddPrintMinterm()
12 <li> Cudd_zddPrintCover()
13 <li> Cudd_zddPrintDebug()
14 <li> Cudd_zddFirstPath()
15 <li> Cudd_zddNextPath()
16 <li> Cudd_zddCoverPathToString()
17 <li> Cudd_zddDumpDot()
19 Internal procedures included in this module:
23 Static procedures included in this module:
26 <li> zdd_print_minterm_aux()
27 <li> zddPrintCoverAux()
33 Author [Hyong-Kyoon Shin, In-Ho Moon, Fabio Somenzi]
35 Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado
39 Redistribution and use in source and binary forms, with or without
40 modification, are permitted provided that the following conditions
43 Redistributions of source code must retain the above copyright
44 notice, this list of conditions and the following disclaimer.
46 Redistributions in binary form must reproduce the above copyright
47 notice, this list of conditions and the following disclaimer in the
48 documentation and/or other materials provided with the distribution.
50 Neither the name of the University of Colorado nor the names of its
51 contributors may be used to endorse or promote products derived from
52 this software without specific prior written permission.
54 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
55 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
56 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
57 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
58 COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
59 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
60 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
61 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
62 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
63 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
64 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
65 POSSIBILITY OF SUCH DAMAGE.]
67 ******************************************************************************/
72 /*---------------------------------------------------------------------------*/
73 /* Constant declarations */
74 /*---------------------------------------------------------------------------*/
77 /*---------------------------------------------------------------------------*/
78 /* Stucture declarations */
79 /*---------------------------------------------------------------------------*/
82 /*---------------------------------------------------------------------------*/
83 /* Type declarations */
84 /*---------------------------------------------------------------------------*/
87 /*---------------------------------------------------------------------------*/
88 /* Variable declarations */
89 /*---------------------------------------------------------------------------*/
92 static char rcsid
[] DD_UNUSED
= "$Id: cuddZddUtil.c,v 1.27 2009/03/08 02:49:02 fabio Exp $";
95 /*---------------------------------------------------------------------------*/
96 /* Macro declarations */
97 /*---------------------------------------------------------------------------*/
100 /**AutomaticStart*************************************************************/
102 /*---------------------------------------------------------------------------*/
103 /* Static function prototypes */
104 /*---------------------------------------------------------------------------*/
106 static int zp2 (DdManager
*zdd
, DdNode
*f
, st_table
*t
);
107 static void zdd_print_minterm_aux (DdManager
*zdd
, DdNode
*node
, int level
, int *list
);
108 static void zddPrintCoverAux (DdManager
*zdd
, DdNode
*node
, int level
, int *list
);
110 /**AutomaticEnd***************************************************************/
113 /*---------------------------------------------------------------------------*/
114 /* Definition of exported functions */
115 /*---------------------------------------------------------------------------*/
118 /**Function********************************************************************
120 Synopsis [Prints a disjoint sum of product form for a ZDD.]
122 Description [Prints a disjoint sum of product form for a ZDD. Returns 1
123 if successful; 0 otherwise.]
127 SeeAlso [Cudd_zddPrintDebug Cudd_zddPrintCover]
129 ******************************************************************************/
131 Cudd_zddPrintMinterm(
138 size
= (int)zdd
->sizeZ
;
139 list
= ALLOC(int, size
);
141 zdd
->errorCode
= CUDD_MEMORY_OUT
;
144 for (i
= 0; i
< size
; i
++) list
[i
] = 3; /* bogus value should disappear */
145 zdd_print_minterm_aux(zdd
, node
, 0, list
);
149 } /* end of Cudd_zddPrintMinterm */
152 /**Function********************************************************************
154 Synopsis [Prints a sum of products from a ZDD representing a cover.]
156 Description [Prints a sum of products from a ZDD representing a cover.
157 Returns 1 if successful; 0 otherwise.]
161 SeeAlso [Cudd_zddPrintMinterm]
163 ******************************************************************************/
172 size
= (int)zdd
->sizeZ
;
173 if (size
% 2 != 0) return(0); /* number of variables should be even */
174 list
= ALLOC(int, size
);
176 zdd
->errorCode
= CUDD_MEMORY_OUT
;
179 for (i
= 0; i
< size
; i
++) list
[i
] = 3; /* bogus value should disappear */
180 zddPrintCoverAux(zdd
, node
, 0, list
);
184 } /* end of Cudd_zddPrintCover */
187 /**Function********************************************************************
189 Synopsis [Prints to the standard output a ZDD and its statistics.]
191 Description [Prints to the standard output a DD and its statistics.
192 The statistics include the number of nodes and the number of minterms.
193 (The number of minterms is also the number of combinations in the set.)
194 The statistics are printed if pr > 0. Specifically:
196 <li> pr = 0 : prints nothing
197 <li> pr = 1 : prints counts of nodes and minterms
198 <li> pr = 2 : prints counts + disjoint sum of products
199 <li> pr = 3 : prints counts + list of nodes
200 <li> pr > 3 : prints counts + disjoint sum of products + list of nodes
202 Returns 1 if successful; 0 otherwise.
209 ******************************************************************************/
217 DdNode
*empty
= DD_ZERO(zdd
);
222 if (f
== empty
&& pr
> 0) {
223 (void) fprintf(zdd
->out
,": is the empty ZDD\n");
224 (void) fflush(zdd
->out
);
229 nodes
= Cudd_zddDagSize(f
);
230 if (nodes
== CUDD_OUT_OF_MEM
) retval
= 0;
231 minterms
= Cudd_zddCountMinterm(zdd
, f
, n
);
232 if (minterms
== (double)CUDD_OUT_OF_MEM
) retval
= 0;
233 (void) fprintf(zdd
->out
,": %d nodes %g minterms\n",
236 if (!cuddZddP(zdd
, f
)) retval
= 0;
237 if (pr
== 2 || pr
> 3) {
238 if (!Cudd_zddPrintMinterm(zdd
, f
)) retval
= 0;
239 (void) fprintf(zdd
->out
,"\n");
241 (void) fflush(zdd
->out
);
245 } /* end of Cudd_zddPrintDebug */
249 /**Function********************************************************************
251 Synopsis [Finds the first path of a ZDD.]
253 Description [Defines an iterator on the paths of a ZDD
254 and finds its first path. Returns a generator that contains the
255 information necessary to continue the enumeration if successful; NULL
257 A path is represented as an array of literals, which are integers in
258 {0, 1, 2}; 0 represents an else arc out of a node, 1 represents a then arc
259 out of a node, and 2 stands for the absence of a node.
260 The size of the array equals the number of variables in the manager at
261 the time Cudd_zddFirstCube is called.<p>
262 The paths that end in the empty terminal are not enumerated.]
264 SideEffects [The first path is returned as a side effect.]
266 SeeAlso [Cudd_zddForeachPath Cudd_zddNextPath Cudd_GenFree
269 ******************************************************************************/
277 DdNode
*top
, *next
, *prev
;
282 if (zdd
== NULL
|| f
== NULL
) return(NULL
);
284 /* Allocate generator an initialize it. */
285 gen
= ALLOC(DdGen
,1);
287 zdd
->errorCode
= CUDD_MEMORY_OUT
;
292 gen
->type
= CUDD_GEN_ZDD_PATHS
;
293 gen
->status
= CUDD_GEN_EMPTY
;
294 gen
->gen
.cubes
.cube
= NULL
;
295 gen
->gen
.cubes
.value
= DD_ZERO_VAL
;
297 gen
->stack
.stack
= NULL
;
301 gen
->gen
.cubes
.cube
= ALLOC(int,nvars
);
302 if (gen
->gen
.cubes
.cube
== NULL
) {
303 zdd
->errorCode
= CUDD_MEMORY_OUT
;
307 for (i
= 0; i
< nvars
; i
++) gen
->gen
.cubes
.cube
[i
] = 2;
309 /* The maximum stack depth is one plus the number of variables.
310 ** because a path may have nodes at all levels, including the
313 gen
->stack
.stack
= ALLOC(DdNodePtr
, nvars
+1);
314 if (gen
->stack
.stack
== NULL
) {
315 zdd
->errorCode
= CUDD_MEMORY_OUT
;
316 FREE(gen
->gen
.cubes
.cube
);
320 for (i
= 0; i
<= nvars
; i
++) gen
->stack
.stack
[i
] = NULL
;
322 /* Find the first path of the ZDD. */
323 gen
->stack
.stack
[gen
->stack
.sp
] = f
; gen
->stack
.sp
++;
326 top
= gen
->stack
.stack
[gen
->stack
.sp
-1];
327 if (!cuddIsConstant(Cudd_Regular(top
))) {
328 /* Take the else branch first. */
329 gen
->gen
.cubes
.cube
[Cudd_Regular(top
)->index
] = 0;
330 next
= cuddE(Cudd_Regular(top
));
331 gen
->stack
.stack
[gen
->stack
.sp
] = Cudd_Not(next
); gen
->stack
.sp
++;
332 } else if (Cudd_Regular(top
) == DD_ZERO(zdd
)) {
335 if (gen
->stack
.sp
== 1) {
336 /* The current node has no predecessor. */
337 gen
->status
= CUDD_GEN_EMPTY
;
341 prev
= Cudd_Regular(gen
->stack
.stack
[gen
->stack
.sp
-2]);
343 if (next
!= top
) { /* follow the then branch next */
344 gen
->gen
.cubes
.cube
[prev
->index
] = 1;
345 gen
->stack
.stack
[gen
->stack
.sp
-1] = next
;
348 /* Pop the stack and try again. */
349 gen
->gen
.cubes
.cube
[prev
->index
] = 2;
351 top
= gen
->stack
.stack
[gen
->stack
.sp
-1];
354 gen
->status
= CUDD_GEN_NONEMPTY
;
355 gen
->gen
.cubes
.value
= cuddV(Cudd_Regular(top
));
361 *path
= gen
->gen
.cubes
.cube
;
364 } /* end of Cudd_zddFirstPath */
367 /**Function********************************************************************
369 Synopsis [Generates the next path of a ZDD.]
371 Description [Generates the next path of a ZDD onset,
372 using generator gen. Returns 0 if the enumeration is completed; 1
375 SideEffects [The path is returned as a side effect. The
376 generator is modified.]
378 SeeAlso [Cudd_zddForeachPath Cudd_zddFirstPath Cudd_GenFree
381 ******************************************************************************/
387 DdNode
*top
, *next
, *prev
;
388 DdManager
*zdd
= gen
->manager
;
390 /* Backtrack from previously reached terminal node. */
392 if (gen
->stack
.sp
== 1) {
393 /* The current node has no predecessor. */
394 gen
->status
= CUDD_GEN_EMPTY
;
398 top
= gen
->stack
.stack
[gen
->stack
.sp
-1];
399 prev
= Cudd_Regular(gen
->stack
.stack
[gen
->stack
.sp
-2]);
401 if (next
!= top
) { /* follow the then branch next */
402 gen
->gen
.cubes
.cube
[prev
->index
] = 1;
403 gen
->stack
.stack
[gen
->stack
.sp
-1] = next
;
406 /* Pop the stack and try again. */
407 gen
->gen
.cubes
.cube
[prev
->index
] = 2;
412 top
= gen
->stack
.stack
[gen
->stack
.sp
-1];
413 if (!cuddIsConstant(Cudd_Regular(top
))) {
414 /* Take the else branch first. */
415 gen
->gen
.cubes
.cube
[Cudd_Regular(top
)->index
] = 0;
416 next
= cuddE(Cudd_Regular(top
));
417 gen
->stack
.stack
[gen
->stack
.sp
] = Cudd_Not(next
); gen
->stack
.sp
++;
418 } else if (Cudd_Regular(top
) == DD_ZERO(zdd
)) {
421 if (gen
->stack
.sp
== 1) {
422 /* The current node has no predecessor. */
423 gen
->status
= CUDD_GEN_EMPTY
;
427 prev
= Cudd_Regular(gen
->stack
.stack
[gen
->stack
.sp
-2]);
429 if (next
!= top
) { /* follow the then branch next */
430 gen
->gen
.cubes
.cube
[prev
->index
] = 1;
431 gen
->stack
.stack
[gen
->stack
.sp
-1] = next
;
434 /* Pop the stack and try again. */
435 gen
->gen
.cubes
.cube
[prev
->index
] = 2;
437 top
= gen
->stack
.stack
[gen
->stack
.sp
-1];
440 gen
->status
= CUDD_GEN_NONEMPTY
;
441 gen
->gen
.cubes
.value
= cuddV(Cudd_Regular(top
));
447 if (gen
->status
== CUDD_GEN_EMPTY
) return(0);
448 *path
= gen
->gen
.cubes
.cube
;
451 } /* end of Cudd_zddNextPath */
454 /**Function********************************************************************
456 Synopsis [Converts a path of a ZDD representing a cover to a string.]
458 Description [Converts a path of a ZDD representing a cover to a
459 string. The string represents an implicant of the cover. The path
460 is typically produced by Cudd_zddForeachPath. Returns a pointer to
461 the string if successful; NULL otherwise. If the str input is NULL,
462 it allocates a new string. The string passed to this function must
463 have enough room for all variables and for the terminator.]
467 SeeAlso [Cudd_zddForeachPath]
469 ******************************************************************************/
471 Cudd_zddCoverPathToString(
472 DdManager
*zdd
/* DD manager */,
473 int *path
/* path of ZDD representing a cover */,
474 char *str
/* pointer to string to use if != NULL */
477 int nvars
= zdd
->sizeZ
;
481 if (nvars
& 1) return(NULL
);
484 res
= ALLOC(char, nvars
+1);
485 if (res
== NULL
) return(NULL
);
489 for (i
= 0; i
< nvars
; i
++) {
490 int v
= (path
[2*i
] << 2) | path
[2*i
+1];
514 } /* end of Cudd_zddCoverPathToString */
517 /**Function********************************************************************
519 Synopsis [Writes a dot file representing the argument ZDDs.]
521 Description [Writes a file representing the argument ZDDs in a format
522 suitable for the graph drawing program dot.
523 It returns 1 in case of success; 0 otherwise (e.g., out-of-memory,
525 Cudd_zddDumpDot does not close the file: This is the caller
526 responsibility. Cudd_zddDumpDot uses a minimal unique subset of the
527 hexadecimal address of a node as name for it.
528 If the argument inames is non-null, it is assumed to hold the pointers
529 to the names of the inputs. Similarly for onames.
530 Cudd_zddDumpDot uses the following convention to draw arcs:
532 <li> solid line: THEN arcs;
533 <li> dashed line: ELSE arcs.
535 The dot options are chosen so that the drawing fits on a letter-size
541 SeeAlso [Cudd_DumpDot Cudd_zddPrintDebug]
543 ******************************************************************************/
546 DdManager
* dd
/* manager */,
547 int n
/* number of output nodes to be dumped */,
548 DdNode
** f
/* array of output nodes to be dumped */,
549 char ** inames
/* array of input names (or NULL) */,
550 char ** onames
/* array of output names (or NULL) */,
551 FILE * fp
/* pointer to the dump file */)
553 DdNode
*support
= NULL
;
556 int nvars
= dd
->sizeZ
;
557 st_table
*visited
= NULL
;
563 long refAddr
, diff
, mask
;
565 /* Build a bit array with the support of f. */
566 sorted
= ALLOC(int,nvars
);
567 if (sorted
== NULL
) {
568 dd
->errorCode
= CUDD_MEMORY_OUT
;
571 for (i
= 0; i
< nvars
; i
++) sorted
[i
] = 0;
573 /* Take the union of the supports of each output function. */
574 for (i
= 0; i
< n
; i
++) {
575 support
= Cudd_Support(dd
,f
[i
]);
576 if (support
== NULL
) goto failure
;
579 while (!cuddIsConstant(scan
)) {
580 sorted
[scan
->index
] = 1;
583 Cudd_RecursiveDeref(dd
,support
);
585 support
= NULL
; /* so that we do not try to free it in case of failure */
587 /* Initialize symbol table for visited nodes. */
588 visited
= st_init_table(st_ptrcmp
, st_ptrhash
);
589 if (visited
== NULL
) goto failure
;
591 /* Collect all the nodes of this DD in the symbol table. */
592 for (i
= 0; i
< n
; i
++) {
593 retval
= cuddCollectNodes(f
[i
],visited
);
594 if (retval
== 0) goto failure
;
597 /* Find how many most significant hex digits are identical
598 ** in the addresses of all the nodes. Build a mask based
599 ** on this knowledge, so that digits that carry no information
600 ** will not be printed. This is done in two steps.
601 ** 1. We scan the symbol table to find the bits that differ
602 ** in at least 2 addresses.
603 ** 2. We choose one of the possible masks. There are 8 possible
604 ** masks for 32-bit integer, and 16 possible masks for 64-bit
608 /* Find the bits that are different. */
609 refAddr
= (long) f
[0];
611 gen
= st_init_gen(visited
);
612 while (st_gen(gen
, &scan
, NULL
)) {
613 diff
|= refAddr
^ (long) scan
;
617 /* Choose the mask. */
618 for (i
= 0; (unsigned) i
< 8 * sizeof(long); i
+= 4) {
620 if (diff
<= mask
) break;
623 /* Write the header and the global attributes. */
624 retval
= fprintf(fp
,"digraph \"ZDD\" {\n");
625 if (retval
== EOF
) return(0);
627 "size = \"7.5,10\"\ncenter = true;\nedge [dir = none];\n");
628 if (retval
== EOF
) return(0);
630 /* Write the input name subgraph by scanning the support array. */
631 retval
= fprintf(fp
,"{ node [shape = plaintext];\n");
632 if (retval
== EOF
) goto failure
;
633 retval
= fprintf(fp
," edge [style = invis];\n");
634 if (retval
== EOF
) goto failure
;
635 /* We use a name ("CONST NODES") with an embedded blank, because
636 ** it is unlikely to appear as an input name.
638 retval
= fprintf(fp
," \"CONST NODES\" [style = invis];\n");
639 if (retval
== EOF
) goto failure
;
640 for (i
= 0; i
< nvars
; i
++) {
641 if (sorted
[dd
->invpermZ
[i
]]) {
642 if (inames
== NULL
) {
643 retval
= fprintf(fp
,"\" %d \" -> ", dd
->invpermZ
[i
]);
645 retval
= fprintf(fp
,"\" %s \" -> ", inames
[dd
->invpermZ
[i
]]);
647 if (retval
== EOF
) goto failure
;
650 retval
= fprintf(fp
,"\"CONST NODES\"; \n}\n");
651 if (retval
== EOF
) goto failure
;
653 /* Write the output node subgraph. */
654 retval
= fprintf(fp
,"{ rank = same; node [shape = box]; edge [style = invis];\n");
655 if (retval
== EOF
) goto failure
;
656 for (i
= 0; i
< n
; i
++) {
657 if (onames
== NULL
) {
658 retval
= fprintf(fp
,"\"F%d\"", i
);
660 retval
= fprintf(fp
,"\" %s \"", onames
[i
]);
662 if (retval
== EOF
) goto failure
;
664 retval
= fprintf(fp
,"; }\n");
666 retval
= fprintf(fp
," -> ");
668 if (retval
== EOF
) goto failure
;
671 /* Write rank info: All nodes with the same index have the same rank. */
672 for (i
= 0; i
< nvars
; i
++) {
673 if (sorted
[dd
->invpermZ
[i
]]) {
674 retval
= fprintf(fp
,"{ rank = same; ");
675 if (retval
== EOF
) goto failure
;
676 if (inames
== NULL
) {
677 retval
= fprintf(fp
,"\" %d \";\n", dd
->invpermZ
[i
]);
679 retval
= fprintf(fp
,"\" %s \";\n", inames
[dd
->invpermZ
[i
]]);
681 if (retval
== EOF
) goto failure
;
682 nodelist
= dd
->subtableZ
[i
].nodelist
;
683 slots
= dd
->subtableZ
[i
].slots
;
684 for (j
= 0; j
< slots
; j
++) {
686 while (scan
!= NULL
) {
687 if (st_is_member(visited
,(char *) scan
)) {
688 retval
= fprintf(fp
,"\"%p\";\n", (void *)
689 ((mask
& (ptrint
) scan
) /
691 if (retval
== EOF
) goto failure
;
696 retval
= fprintf(fp
,"}\n");
697 if (retval
== EOF
) goto failure
;
701 /* All constants have the same rank. */
703 "{ rank = same; \"CONST NODES\";\n{ node [shape = box]; ");
704 if (retval
== EOF
) goto failure
;
705 nodelist
= dd
->constants
.nodelist
;
706 slots
= dd
->constants
.slots
;
707 for (j
= 0; j
< slots
; j
++) {
709 while (scan
!= NULL
) {
710 if (st_is_member(visited
,(char *) scan
)) {
711 retval
= fprintf(fp
,"\"%p\";\n", (void *)
712 ((mask
& (ptrint
) scan
) / sizeof(DdNode
)));
713 if (retval
== EOF
) goto failure
;
718 retval
= fprintf(fp
,"}\n}\n");
719 if (retval
== EOF
) goto failure
;
721 /* Write edge info. */
722 /* Edges from the output nodes. */
723 for (i
= 0; i
< n
; i
++) {
724 if (onames
== NULL
) {
725 retval
= fprintf(fp
,"\"F%d\"", i
);
727 retval
= fprintf(fp
,"\" %s \"", onames
[i
]);
729 if (retval
== EOF
) goto failure
;
730 retval
= fprintf(fp
," -> \"%p\" [style = solid];\n",
731 (void *) ((mask
& (ptrint
) f
[i
]) /
733 if (retval
== EOF
) goto failure
;
736 /* Edges from internal nodes. */
737 for (i
= 0; i
< nvars
; i
++) {
738 if (sorted
[dd
->invpermZ
[i
]]) {
739 nodelist
= dd
->subtableZ
[i
].nodelist
;
740 slots
= dd
->subtableZ
[i
].slots
;
741 for (j
= 0; j
< slots
; j
++) {
743 while (scan
!= NULL
) {
744 if (st_is_member(visited
,(char *) scan
)) {
746 "\"%p\" -> \"%p\";\n",
747 (void *) ((mask
& (ptrint
) scan
) / sizeof(DdNode
)),
748 (void *) ((mask
& (ptrint
) cuddT(scan
)) /
750 if (retval
== EOF
) goto failure
;
752 "\"%p\" -> \"%p\" [style = dashed];\n",
753 (void *) ((mask
& (ptrint
) scan
)
755 (void *) ((mask
& (ptrint
)
758 if (retval
== EOF
) goto failure
;
766 /* Write constant labels. */
767 nodelist
= dd
->constants
.nodelist
;
768 slots
= dd
->constants
.slots
;
769 for (j
= 0; j
< slots
; j
++) {
771 while (scan
!= NULL
) {
772 if (st_is_member(visited
,(char *) scan
)) {
773 retval
= fprintf(fp
,"\"%p\" [label = \"%g\"];\n",
774 (void *) ((mask
& (ptrint
) scan
) /
777 if (retval
== EOF
) goto failure
;
783 /* Write trailer and return. */
784 retval
= fprintf(fp
,"}\n");
785 if (retval
== EOF
) goto failure
;
787 st_free_table(visited
);
792 if (sorted
!= NULL
) FREE(sorted
);
793 if (visited
!= NULL
) st_free_table(visited
);
796 } /* end of Cudd_zddDumpBlif */
799 /*---------------------------------------------------------------------------*/
800 /* Definition of internal functions */
801 /*---------------------------------------------------------------------------*/
804 /**Function********************************************************************
806 Synopsis [Prints a ZDD to the standard output. One line per node is
809 Description [Prints a ZDD to the standard output. One line per node is
810 printed. Returns 1 if successful; 0 otherwise.]
814 SeeAlso [Cudd_zddPrintDebug]
816 ******************************************************************************/
823 st_table
*table
= st_init_table(st_ptrcmp
, st_ptrhash
);
825 if (table
== NULL
) return(0);
827 retval
= zp2(zdd
, f
, table
);
828 st_free_table(table
);
829 (void) fputc('\n', zdd
->out
);
832 } /* end of cuddZddP */
835 /*---------------------------------------------------------------------------*/
836 /* Definition of static functions */
837 /*---------------------------------------------------------------------------*/
840 /**Function********************************************************************
842 Synopsis [Performs the recursive step of cuddZddP.]
844 Description [Performs the recursive step of cuddZddP. Returns 1 in
845 case of success; 0 otherwise.]
851 ******************************************************************************/
860 DdNode
*base
= DD_ONE(zdd
);
865 if (Cudd_IsConstant(f
)) {
866 (void)fprintf(zdd
->out
, "ID = %d\n", (f
== base
));
869 if (st_is_member(t
, (char *)f
) == 1)
872 if (st_insert(t
, (char *) f
, NULL
) == ST_OUT_OF_MEM
)
875 #if SIZEOF_VOID_P == 8
876 (void) fprintf(zdd
->out
, "ID = 0x%lx\tindex = %u\tr = %u\t",
877 (ptruint
)f
/ (ptruint
) sizeof(DdNode
), f
->index
, f
->ref
);
879 (void) fprintf(zdd
->out
, "ID = 0x%x\tindex = %hu\tr = %hu\t",
880 (ptruint
)f
/ (ptruint
) sizeof(DdNode
), f
->index
, f
->ref
);
884 if (Cudd_IsConstant(n
)) {
885 (void) fprintf(zdd
->out
, "T = %d\t\t", (n
== base
));
888 #if SIZEOF_VOID_P == 8
889 (void) fprintf(zdd
->out
, "T = 0x%lx\t", (ptruint
) n
/
890 (ptruint
) sizeof(DdNode
));
892 (void) fprintf(zdd
->out
, "T = 0x%x\t", (ptruint
) n
/
893 (ptruint
) sizeof(DdNode
));
899 if (Cudd_IsConstant(n
)) {
900 (void) fprintf(zdd
->out
, "E = %d\n", (n
== base
));
903 #if SIZEOF_VOID_P == 8
904 (void) fprintf(zdd
->out
, "E = 0x%lx\n", (ptruint
) n
/
905 (ptruint
) sizeof(DdNode
));
907 (void) fprintf(zdd
->out
, "E = 0x%x\n", (ptruint
) n
/
908 (ptruint
) sizeof(DdNode
));
914 if (zp2(zdd
, cuddE(f
), t
) == 0) return(0);
916 if (zp2(zdd
, cuddT(f
), t
) == 0) return(0);
922 /**Function********************************************************************
924 Synopsis [Performs the recursive step of Cudd_zddPrintMinterm.]
932 ******************************************************************************/
934 zdd_print_minterm_aux(
935 DdManager
* zdd
/* manager */,
936 DdNode
* node
/* current node */,
937 int level
/* depth in the recursion */,
938 int * list
/* current recursion path */)
942 DdNode
*base
= DD_ONE(zdd
);
944 if (Cudd_IsConstant(node
)) {
946 /* Check for missing variable. */
947 if (level
!= zdd
->sizeZ
) {
948 list
[zdd
->invpermZ
[level
]] = 0;
949 zdd_print_minterm_aux(zdd
, node
, level
+ 1, list
);
952 /* Terminal case: Print one cube based on the current recursion
955 for (i
= 0; i
< zdd
->sizeZ
; i
++) {
958 (void) fprintf(zdd
->out
,"0");
960 (void) fprintf(zdd
->out
,"1");
962 (void) fprintf(zdd
->out
,"@"); /* should never happen */
964 (void) fprintf(zdd
->out
,"-");
966 (void) fprintf(zdd
->out
," 1\n");
969 /* Check for missing variable. */
970 if (level
!= cuddIZ(zdd
,node
->index
)) {
971 list
[zdd
->invpermZ
[level
]] = 0;
972 zdd_print_minterm_aux(zdd
, node
, level
+ 1, list
);
979 list
[node
->index
] = 2;
980 zdd_print_minterm_aux(zdd
, Nnv
, level
+ 1, list
);
984 list
[node
->index
] = 1;
985 zdd_print_minterm_aux(zdd
, Nv
, level
+ 1, list
);
986 list
[node
->index
] = 0;
987 zdd_print_minterm_aux(zdd
, Nnv
, level
+ 1, list
);
991 } /* end of zdd_print_minterm_aux */
994 /**Function********************************************************************
996 Synopsis [Performs the recursive step of Cudd_zddPrintCover.]
1004 ******************************************************************************/
1007 DdManager
* zdd
/* manager */,
1008 DdNode
* node
/* current node */,
1009 int level
/* depth in the recursion */,
1010 int * list
/* current recursion path */)
1014 DdNode
*base
= DD_ONE(zdd
);
1016 if (Cudd_IsConstant(node
)) {
1018 /* Check for missing variable. */
1019 if (level
!= zdd
->sizeZ
) {
1020 list
[zdd
->invpermZ
[level
]] = 0;
1021 zddPrintCoverAux(zdd
, node
, level
+ 1, list
);
1024 /* Terminal case: Print one cube based on the current recursion
1027 for (i
= 0; i
< zdd
->sizeZ
; i
+= 2) {
1028 v
= list
[i
] * 4 + list
[i
+1];
1030 (void) putc('-',zdd
->out
);
1032 (void) putc('1',zdd
->out
);
1034 (void) putc('0',zdd
->out
);
1036 (void) putc('@',zdd
->out
); /* should never happen */
1038 (void) fprintf(zdd
->out
," 1\n");
1041 /* Check for missing variable. */
1042 if (level
!= cuddIZ(zdd
,node
->index
)) {
1043 list
[zdd
->invpermZ
[level
]] = 0;
1044 zddPrintCoverAux(zdd
, node
, level
+ 1, list
);
1051 list
[node
->index
] = 2;
1052 zddPrintCoverAux(zdd
, Nnv
, level
+ 1, list
);
1056 list
[node
->index
] = 1;
1057 zddPrintCoverAux(zdd
, Nv
, level
+ 1, list
);
1058 list
[node
->index
] = 0;
1059 zddPrintCoverAux(zdd
, Nnv
, level
+ 1, list
);
1063 } /* end of zddPrintCoverAux */