📄 cuddzddutil.c
字号:
/**CFile*********************************************************************** FileName [cuddZddUtil.c] PackageName [cudd] Synopsis [Utility functions for ZDDs.] Description [External procedures included in this module: <ul> <li> Cudd_zddPrintMinterm() <li> Cudd_zddPrintCover() <li> Cudd_zddPrintDebug() <li> Cudd_zddDumpDot() </ul> Internal procedures included in this module: <ul> <li> cuddZddP() </ul> Static procedures included in this module: <ul> <li> zp2() <li> zdd_print_minterm_aux() </ul> ] SeeAlso [] Author [Hyong-Kyoon Shin, In-Ho Moon] Copyright [ This file was created at the University of Colorado at Boulder. The University of Colorado at Boulder makes no warranty about the suitability of this software for any purpose. It is presented on an AS IS basis.]******************************************************************************/#include "util.h"#include "cuddInt.h"/*---------------------------------------------------------------------------*//* Constant declarations *//*---------------------------------------------------------------------------*//*---------------------------------------------------------------------------*//* Stucture declarations *//*---------------------------------------------------------------------------*//*---------------------------------------------------------------------------*//* Type declarations *//*---------------------------------------------------------------------------*//*---------------------------------------------------------------------------*//* Variable declarations *//*---------------------------------------------------------------------------*/#ifndef lintstatic char rcsid[] DD_UNUSED = "$Id: cuddZddUtil.c,v 1.1.1.1 2003/02/24 22:23:54 wjiang Exp $";#endif/*---------------------------------------------------------------------------*//* Macro declarations *//*---------------------------------------------------------------------------*//**AutomaticStart*************************************************************//*---------------------------------------------------------------------------*//* Static function prototypes *//*---------------------------------------------------------------------------*/static int zp2 ARGS((DdManager *zdd, DdNode *f, st_table *t));static void zdd_print_minterm_aux ARGS((DdManager *zdd, DdNode *node, int level, int *list));static void zddPrintCoverAux ARGS((DdManager *zdd, DdNode *node, int level, int *list));/**AutomaticEnd***************************************************************//*---------------------------------------------------------------------------*//* Definition of exported functions *//*---------------------------------------------------------------------------*//**Function******************************************************************** Synopsis [Prints a disjoint sum of product form for a ZDD.] Description [Prints a disjoint sum of product form for a ZDD. Returns 1 if successful; 0 otherwise.] SideEffects [None] SeeAlso [Cudd_zddPrintDebug Cudd_zddPrintCover]******************************************************************************/intCudd_zddPrintMinterm( DdManager * zdd, DdNode * node){ int i, size; int *list; size = (int)zdd->sizeZ; list = ALLOC(int, size); if (list == NULL) { zdd->errorCode = CUDD_MEMORY_OUT; return(0); } for (i = 0; i < size; i++) list[i] = 3; /* bogus value should disappear */ zdd_print_minterm_aux(zdd, node, 0, list); FREE(list); return(1);} /* end of Cudd_zddPrintMinterm *//**Function******************************************************************** Synopsis [Prints a sum of products from a ZDD representing a cover.] Description [Prints a sum of products from a ZDD representing a cover. Returns 1 if successful; 0 otherwise.] SideEffects [None] SeeAlso [Cudd_zddPrintMinterm]******************************************************************************/intCudd_zddPrintCover( DdManager * zdd, DdNode * node){ int i, size; int *list; size = (int)zdd->sizeZ; if (size % 2 != 0) return(0); /* number of variables should be even */ list = ALLOC(int, size); if (list == NULL) { zdd->errorCode = CUDD_MEMORY_OUT; return(0); } for (i = 0; i < size; i++) list[i] = 3; /* bogus value should disappear */ zddPrintCoverAux(zdd, node, 0, list); FREE(list); return(1);} /* end of Cudd_zddPrintCover *//**Function******************************************************************** Synopsis [Prints to the standard output a ZDD and its statistics.] Description [Prints to the standard output a DD and its statistics. The statistics include the number of nodes and the number of minterms. (The number of minterms is also the number of combinations in the set.) The statistics are printed if pr > 0. Specifically: <ul> <li> pr = 0 : prints nothing <li> pr = 1 : prints counts of nodes and minterms <li> pr = 2 : prints counts + disjoint sum of products <li> pr = 3 : prints counts + list of nodes <li> pr > 3 : prints counts + disjoint sum of products + list of nodes </ul> Returns 1 if successful; 0 otherwise. ] SideEffects [None] SeeAlso []******************************************************************************/intCudd_zddPrintDebug( DdManager * zdd, DdNode * f, int n, int pr){ DdNode *empty = DD_ZERO(zdd); int nodes; double minterms; int retval = 1; if (f == empty && pr > 0) { (void) fprintf(zdd->out,": is the empty ZDD\n"); (void) fflush(zdd->out); return(1); } if (pr > 0) { nodes = Cudd_zddDagSize(f); if (nodes == CUDD_OUT_OF_MEM) retval = 0; minterms = Cudd_zddCountMinterm(zdd, f, n); if (minterms == (double)CUDD_OUT_OF_MEM) retval = 0; (void) fprintf(zdd->out,": %d nodes %g minterms\n", nodes, minterms); if (pr > 2) if (!cuddZddP(zdd, f)) retval = 0; if (pr == 2 || pr > 3) { if (!Cudd_zddPrintMinterm(zdd, f)) retval = 0; (void) fprintf(zdd->out,"\n"); } (void) fflush(zdd->out); } return(retval);} /* end of Cudd_zddPrintDebug *//**Function******************************************************************** Synopsis [Finds the first path of a ZDD.] Description [Defines an iterator on the paths of a ZDD and finds its first path. Returns a generator that contains the information necessary to continue the enumeration if successful; NULL otherwise.<p> A path is represented as an array of literals, which are integers in {0, 1, 2}; 0 represents an else arc out of a node, 1 represents a then arc out of a node, and 2 stands for the absence of a node. The size of the array equals the number of variables in the manager at the time Cudd_zddFirstCube is called.<p> The paths that end in the empty terminal are not enumerated.] SideEffects [The first path is returned as a side effect.] SeeAlso [Cudd_zddForeachPath Cudd_zddNextPath Cudd_GenFree Cudd_IsGenEmpty]******************************************************************************/DdGen *Cudd_zddFirstPath( DdManager * zdd, DdNode * f, int ** path){ DdGen *gen; DdNode *top, *next, *prev; int i; int nvars; /* Sanity Check. */ if (zdd == NULL || f == NULL) return(NULL); /* Allocate generator an initialize it. */ gen = ALLOC(DdGen,1); if (gen == NULL) { zdd->errorCode = CUDD_MEMORY_OUT; return(NULL); } gen->manager = zdd; gen->type = CUDD_GEN_ZDD_PATHS; gen->status = CUDD_GEN_EMPTY; gen->gen.cubes.cube = NULL; gen->gen.cubes.value = DD_ZERO_VAL; gen->stack.sp = 0; gen->stack.stack = NULL; gen->node = NULL; nvars = zdd->sizeZ; gen->gen.cubes.cube = ALLOC(int,nvars); if (gen->gen.cubes.cube == NULL) { zdd->errorCode = CUDD_MEMORY_OUT; FREE(gen); return(NULL); } for (i = 0; i < nvars; i++) gen->gen.cubes.cube[i] = 2; /* The maximum stack depth is one plus the number of variables. ** because a path may have nodes at all levels, including the ** constant level. */ gen->stack.stack = ALLOC(DdNode *, nvars+1); if (gen->stack.stack == NULL) { zdd->errorCode = CUDD_MEMORY_OUT; FREE(gen->gen.cubes.cube); FREE(gen); return(NULL); } for (i = 0; i <= nvars; i++) gen->stack.stack[i] = NULL; /* Find the first path of the ZDD. */ gen->stack.stack[gen->stack.sp] = f; gen->stack.sp++; while (1) { top = gen->stack.stack[gen->stack.sp-1]; if (!cuddIsConstant(top)) { /* Take the else branch first. */ gen->gen.cubes.cube[top->index] = 0; next = cuddE(top); gen->stack.stack[gen->stack.sp] = next; gen->stack.sp++; } else if (top == DD_ZERO(zdd)) { /* Backtrack. */ while (1) { if (gen->stack.sp == 1) { /* The current node has no predecessor. */ gen->status = CUDD_GEN_EMPTY; gen->stack.sp--; goto done; } prev = gen->stack.stack[gen->stack.sp-2]; next = cuddT(prev); if (next != top) { /* follow the then branch next */ gen->gen.cubes.cube[prev->index] = 1; gen->stack.stack[gen->stack.sp-1] = next; break; } /* Pop the stack and try again. */ gen->gen.cubes.cube[prev->index] = 2; gen->stack.sp--; top = gen->stack.stack[gen->stack.sp-1]; } } else { gen->status = CUDD_GEN_NONEMPTY; gen->gen.cubes.value = cuddV(top); goto done; } }done: *path = gen->gen.cubes.cube; return(gen);} /* end of Cudd_zddFirstPath *//**Function******************************************************************** Synopsis [Generates the next path of a ZDD.] Description [Generates the next path of a ZDD onset, using generator gen. Returns 0 if the enumeration is completed; 1 otherwise.] SideEffects [The path is returned as a side effect. The generator is modified.] SeeAlso [Cudd_zddForeachPath Cudd_zddFirstPath Cudd_GenFree Cudd_IsGenEmpty]******************************************************************************/intCudd_zddNextPath( DdGen * gen, int ** path){ DdNode *top, *next, *prev; DdManager *zdd = gen->manager; /* Backtrack from previously reached terminal node. */ while (1) { if (gen->stack.sp == 1) { /* The current node has no predecessor. */ gen->status = CUDD_GEN_EMPTY; gen->stack.sp--; goto done; } top = gen->stack.stack[gen->stack.sp-1]; prev = gen->stack.stack[gen->stack.sp-2]; next = cuddT(prev); if (next != top) { /* follow the then branch next */ gen->gen.cubes.cube[prev->index] = 1; gen->stack.stack[gen->stack.sp-1] = next; break; } /* Pop the stack and try again. */ gen->gen.cubes.cube[prev->index] = 2; gen->stack.sp--; } while (1) { top = gen->stack.stack[gen->stack.sp-1]; if (!cuddIsConstant(top)) { /* Take the else branch first. */ gen->gen.cubes.cube[top->index] = 0; next = cuddE(top); gen->stack.stack[gen->stack.sp] = next; gen->stack.sp++; } else if (top == DD_ZERO(zdd)) { /* Backtrack. */ while (1) { if (gen->stack.sp == 1) { /* The current node has no predecessor. */ gen->status = CUDD_GEN_EMPTY; gen->stack.sp--; goto done; } prev = gen->stack.stack[gen->stack.sp-2]; next = cuddT(prev); if (next != top) { /* follow the then branch next */ gen->gen.cubes.cube[prev->index] = 1; gen->stack.stack[gen->stack.sp-1] = next; break; } /* Pop the stack and try again. */ gen->gen.cubes.cube[prev->index] = 2; gen->stack.sp--; top = gen->stack.stack[gen->stack.sp-1]; } } else { gen->status = CUDD_GEN_NONEMPTY; gen->gen.cubes.value = cuddV(top); goto done; } }done: if (gen->status == CUDD_GEN_EMPTY) return(0); *path = gen->gen.cubes.cube; return(1);} /* end of Cudd_zddNextPath *//**Function******************************************************************** Synopsis [Converts a path of a ZDD representing a cover to a string.] Description [Converts a path of a ZDD representing a cover to a string. The string represents an implicant of the cover. The path is typically produced by Cudd_zddForeachPath. Returns a pointer to the string if successful; NULL otherwise. If the str input is NULL, it allocates a new string. The string passed to this function must have enough room for all variables and for the terminator.] SideEffects [None] SeeAlso [Cudd_zddForeachPath]******************************************************************************/char *Cudd_zddCoverPathToString( DdManager *zdd /* DD manager */, int *path /* path of ZDD representing a cover */, char *str /* pointer to string to use if != NULL */ ){ int nvars = zdd->sizeZ; int i; char *res; if (nvars & 1) return(NULL); nvars >>= 1; if (str == NULL) { res = ALLOC(char, nvars+1); if (res == NULL) return(NULL); } else { res = str; } for (i = 0; i < nvars; i++) { int v = (path[2*i] << 2) | path[2*i+1]; switch (v) { case 0: case 2: case 8: case 10: res[i] = '-'; break; case 1: case 9: res[i] = '0'; break; case 4: case 6: res[i] = '1'; break; default: res[i] = '?'; } } res[nvars] = 0; return(res);} /* end of Cudd_zddCoverPathToString *//**Function******************************************************************** Synopsis [Writes a dot file representing the argument ZDDs.] Description [Writes a file representing the argument ZDDs in a format suitable for the graph drawing program dot. It returns 1 in case of success; 0 otherwise (e.g., out-of-memory, file system full). Cudd_zddDumpDot does not close the file: This is the caller responsibility. Cudd_zddDumpDot uses a minimal unique subset of the hexadecimal address of a node as name for it. If the argument inames is non-null, it is assumed to hold the pointers to the names of the inputs. Similarly for onames. Cudd_zddDumpDot uses the following convention to draw arcs: <ul> <li> solid line: THEN arcs; <li> dashed line: ELSE arcs. </ul> The dot options are chosen so that the drawing fits on a letter-size sheet. ] SideEffects [None] SeeAlso [Cudd_DumpDot Cudd_zddPrintDebug]
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -