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.
		
		
		
		
		
			
		
			
				
					
					
						
							1205 lines
						
					
					
						
							34 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							1205 lines
						
					
					
						
							34 KiB
						
					
					
				
								/**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_zddFirstPath()
							 | 
						|
										    <li> Cudd_zddNextPath()
							 | 
						|
										    <li> Cudd_zddCoverPathToString()
							 | 
						|
								                    <li> Cudd_zddSupport()
							 | 
						|
										    <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()
							 | 
						|
										    <li> zddPrintCoverAux()
							 | 
						|
								                    <li> zddSupportStep()
							 | 
						|
								                    <li> zddClearFlag()
							 | 
						|
										    </ul>
							 | 
						|
									      ]
							 | 
						|
								
							 | 
						|
								  SeeAlso     []
							 | 
						|
								
							 | 
						|
								  Author      [Hyong-Kyoon Shin, In-Ho Moon, Fabio Somenzi]
							 | 
						|
								
							 | 
						|
								  Copyright   [Copyright (c) 1995-2012, 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.]
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								
							 | 
						|
								#include "util.h"
							 | 
						|
								#include "cuddInt.h"
							 | 
						|
								
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								/* Constant declarations                                                     */
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								/* Stucture declarations                                                     */
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								/* Type declarations                                                         */
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								/* Variable declarations                                                     */
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								
							 | 
						|
								#ifndef lint
							 | 
						|
								static char rcsid[] DD_UNUSED = "$Id: cuddZddUtil.c,v 1.29 2012/02/05 01:07:19 fabio Exp $";
							 | 
						|
								#endif
							 | 
						|
								
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								/* Macro declarations                                                        */
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**AutomaticStart*************************************************************/
							 | 
						|
								
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								/* Static function prototypes                                                */
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								
							 | 
						|
								static int zp2 (DdManager *zdd, DdNode *f, st_table *t);
							 | 
						|
								static void zdd_print_minterm_aux (DdManager *zdd, DdNode *node, int level, int *list);
							 | 
						|
								static void zddPrintCoverAux (DdManager *zdd, DdNode *node, int level, int *list);
							 | 
						|
								static void zddSupportStep(DdNode * f, int * support);
							 | 
						|
								static void zddClearFlag(DdNode * f);
							 | 
						|
								
							 | 
						|
								/**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]
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								int
							 | 
						|
								Cudd_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]
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								int
							 | 
						|
								Cudd_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     []
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								int
							 | 
						|
								Cudd_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(DdNodePtr, 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(Cudd_Regular(top))) {
							 | 
						|
									    /* Take the else branch first. */
							 | 
						|
									    gen->gen.cubes.cube[Cudd_Regular(top)->index] = 0;
							 | 
						|
									    next = cuddE(Cudd_Regular(top));
							 | 
						|
									    gen->stack.stack[gen->stack.sp] = Cudd_Not(next); gen->stack.sp++;
							 | 
						|
									} else if (Cudd_Regular(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 = Cudd_Regular(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(Cudd_Regular(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]
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								int
							 | 
						|
								Cudd_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 = Cudd_Regular(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(Cudd_Regular(top))) {
							 | 
						|
									    /* Take the else branch first. */
							 | 
						|
									    gen->gen.cubes.cube[Cudd_Regular(top)->index] = 0;
							 | 
						|
									    next = cuddE(Cudd_Regular(top));
							 | 
						|
									    gen->stack.stack[gen->stack.sp] = Cudd_Not(next); gen->stack.sp++;
							 | 
						|
									} else if (Cudd_Regular(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 = Cudd_Regular(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(Cudd_Regular(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    [Finds the variables on which a ZDD depends.]
							 | 
						|
								
							 | 
						|
								  Description [Finds the variables on which a ZDD depends.
							 | 
						|
								  Returns a BDD consisting of the product of the variables if
							 | 
						|
								  successful; NULL otherwise.]
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     [Cudd_Support]
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								DdNode *
							 | 
						|
								Cudd_zddSupport(
							 | 
						|
								  DdManager * dd /* manager */,
							 | 
						|
								  DdNode * f /* ZDD whose support is sought */)
							 | 
						|
								{
							 | 
						|
								    int *support;
							 | 
						|
								    DdNode *res, *tmp, *var;
							 | 
						|
								    int i,j;
							 | 
						|
								    int size;
							 | 
						|
								
							 | 
						|
								    /* Allocate and initialize support array for ddSupportStep. */
							 | 
						|
								    size = ddMax(dd->size, dd->sizeZ);
							 | 
						|
								    support = ALLOC(int,size);
							 | 
						|
								    if (support == NULL) {
							 | 
						|
								        dd->errorCode = CUDD_MEMORY_OUT;
							 | 
						|
								        return(NULL);
							 | 
						|
								    }
							 | 
						|
								    for (i = 0; i < size; i++) {
							 | 
						|
								        support[i] = 0;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    /* Compute support and clean up markers. */
							 | 
						|
								    zddSupportStep(Cudd_Regular(f),support);
							 | 
						|
								    zddClearFlag(Cudd_Regular(f));
							 | 
						|
								
							 | 
						|
								    /* Transform support from array to cube. */
							 | 
						|
								    do {
							 | 
						|
								        dd->reordered = 0;
							 | 
						|
								        res = DD_ONE(dd);
							 | 
						|
								        cuddRef(res);
							 | 
						|
								        for (j = size - 1; j >= 0; j--) { /* for each level bottom-up */
							 | 
						|
								            i = (j >= dd->size) ? j : dd->invperm[j];
							 | 
						|
								            if (support[i] == 1) {
							 | 
						|
								                /* The following call to cuddUniqueInter is guaranteed
							 | 
						|
								                ** not to trigger reordering because the node we look up
							 | 
						|
								                ** already exists. */
							 | 
						|
								                var = cuddUniqueInter(dd,i,dd->one,Cudd_Not(dd->one));
							 | 
						|
								                cuddRef(var);
							 | 
						|
								                tmp = cuddBddAndRecur(dd,res,var);
							 | 
						|
								                if (tmp == NULL) {
							 | 
						|
								                    Cudd_RecursiveDeref(dd,res);
							 | 
						|
								                    Cudd_RecursiveDeref(dd,var);
							 | 
						|
								                    res = NULL;
							 | 
						|
								                    break;
							 | 
						|
								                }
							 | 
						|
								                cuddRef(tmp);
							 | 
						|
								                Cudd_RecursiveDeref(dd,res);
							 | 
						|
								                Cudd_RecursiveDeref(dd,var);
							 | 
						|
								                res = tmp;
							 | 
						|
								            }
							 | 
						|
								        }
							 | 
						|
								    } while (dd->reordered == 1);
							 | 
						|
								
							 | 
						|
								    FREE(support);
							 | 
						|
								    if (res != NULL) cuddDeref(res);
							 | 
						|
								    return(res);
							 | 
						|
								
							 | 
						|
								} /* end of Cudd_zddSupport */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**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]
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								int
							 | 
						|
								Cudd_zddDumpDot(
							 | 
						|
								  DdManager * dd /* manager */,
							 | 
						|
								  int  n /* number of output nodes to be dumped */,
							 | 
						|
								  DdNode ** f /* array of output nodes to be dumped */,
							 | 
						|
								  char ** inames /* array of input names (or NULL) */,
							 | 
						|
								  char ** onames /* array of output names (or NULL) */,
							 | 
						|
								  FILE * fp /* pointer to the dump file */)
							 | 
						|
								{
							 | 
						|
								    DdNode	*support = NULL;
							 | 
						|
								    DdNode	*scan;
							 | 
						|
								    int		*sorted = NULL;
							 | 
						|
								    int		nvars = dd->sizeZ;
							 | 
						|
								    st_table	*visited = NULL;
							 | 
						|
								    st_generator *gen;
							 | 
						|
								    int		retval;
							 | 
						|
								    int		i, j;
							 | 
						|
								    int		slots;
							 | 
						|
								    DdNodePtr	*nodelist;
							 | 
						|
								    long	refAddr, diff, mask;
							 | 
						|
								
							 | 
						|
								    /* Build a bit array with the support of f. */
							 | 
						|
								    sorted = ALLOC(int,nvars);
							 | 
						|
								    if (sorted == NULL) {
							 | 
						|
									dd->errorCode = CUDD_MEMORY_OUT;
							 | 
						|
									goto failure;
							 | 
						|
								    }
							 | 
						|
								    for (i = 0; i < nvars; i++) sorted[i] = 0;
							 | 
						|
								
							 | 
						|
								    /* Take the union of the supports of each output function. */
							 | 
						|
								    for (i = 0; i < n; i++) {
							 | 
						|
									support = Cudd_zddSupport(dd,f[i]);
							 | 
						|
									if (support == NULL) goto failure;
							 | 
						|
									cuddRef(support);
							 | 
						|
									scan = support;
							 | 
						|
									while (!cuddIsConstant(scan)) {
							 | 
						|
									    sorted[scan->index] = 1;
							 | 
						|
									    scan = cuddT(scan);
							 | 
						|
									}
							 | 
						|
									Cudd_RecursiveDeref(dd,support);
							 | 
						|
								    }
							 | 
						|
								    support = NULL; /* so that we do not try to free it in case of failure */
							 | 
						|
								
							 | 
						|
								    /* Initialize symbol table for visited nodes. */
							 | 
						|
								    visited = st_init_table(st_ptrcmp, st_ptrhash);
							 | 
						|
								    if (visited == NULL) goto failure;
							 | 
						|
								
							 | 
						|
								    /* Collect all the nodes of this DD in the symbol table. */
							 | 
						|
								    for (i = 0; i < n; i++) {
							 | 
						|
									retval = cuddCollectNodes(f[i],visited);
							 | 
						|
									if (retval == 0) goto failure;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    /* Find how many most significant hex digits are identical
							 | 
						|
								    ** in the addresses of all the nodes. Build a mask based
							 | 
						|
								    ** on this knowledge, so that digits that carry no information
							 | 
						|
								    ** will not be printed. This is done in two steps.
							 | 
						|
								    **  1. We scan the symbol table to find the bits that differ
							 | 
						|
								    **     in at least 2 addresses.
							 | 
						|
								    **  2. We choose one of the possible masks. There are 8 possible
							 | 
						|
								    **     masks for 32-bit integer, and 16 possible masks for 64-bit
							 | 
						|
								    **     integers.
							 | 
						|
								    */
							 | 
						|
								
							 | 
						|
								    /* Find the bits that are different. */
							 | 
						|
								    refAddr = (long) f[0];
							 | 
						|
								    diff = 0;
							 | 
						|
								    gen = st_init_gen(visited);
							 | 
						|
								    while (st_gen(gen, &scan, NULL)) {
							 | 
						|
									diff |= refAddr ^ (long) scan;
							 | 
						|
								    }
							 | 
						|
								    st_free_gen(gen);
							 | 
						|
								
							 | 
						|
								    /* Choose the mask. */
							 | 
						|
								    for (i = 0; (unsigned) i < 8 * sizeof(long); i += 4) {
							 | 
						|
									mask = (1 << i) - 1;
							 | 
						|
									if (diff <= mask) break;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    /* Write the header and the global attributes. */
							 | 
						|
								    retval = fprintf(fp,"digraph \"ZDD\" {\n");
							 | 
						|
								    if (retval == EOF) return(0);
							 | 
						|
								    retval = fprintf(fp,
							 | 
						|
									"size = \"7.5,10\"\ncenter = true;\nedge [dir = none];\n");
							 | 
						|
								    if (retval == EOF) return(0);
							 | 
						|
								
							 | 
						|
								    /* Write the input name subgraph by scanning the support array. */
							 | 
						|
								    retval = fprintf(fp,"{ node [shape = plaintext];\n");
							 | 
						|
								    if (retval == EOF) goto failure;
							 | 
						|
								    retval = fprintf(fp,"  edge [style = invis];\n");
							 | 
						|
								    if (retval == EOF) goto failure;
							 | 
						|
								    /* We use a name ("CONST NODES") with an embedded blank, because
							 | 
						|
								    ** it is unlikely to appear as an input name.
							 | 
						|
								    */
							 | 
						|
								    retval = fprintf(fp,"  \"CONST NODES\" [style = invis];\n");
							 | 
						|
								    if (retval == EOF) goto failure;
							 | 
						|
								    for (i = 0; i < nvars; i++) {
							 | 
						|
									if (sorted[dd->invpermZ[i]]) {
							 | 
						|
									    if (inames == NULL) {
							 | 
						|
										retval = fprintf(fp,"\" %d \" -> ", dd->invpermZ[i]);
							 | 
						|
									    } else {
							 | 
						|
										retval = fprintf(fp,"\" %s \" -> ", inames[dd->invpermZ[i]]);
							 | 
						|
									    }
							 | 
						|
									    if (retval == EOF) goto failure;
							 | 
						|
									}
							 | 
						|
								    }
							 | 
						|
								    retval = fprintf(fp,"\"CONST NODES\"; \n}\n");
							 | 
						|
								    if (retval == EOF) goto failure;
							 | 
						|
								
							 | 
						|
								    /* Write the output node subgraph. */
							 | 
						|
								    retval = fprintf(fp,"{ rank = same; node [shape = box]; edge [style = invis];\n");
							 | 
						|
								    if (retval == EOF) goto failure;
							 | 
						|
								    for (i = 0; i < n; i++) {
							 | 
						|
									if (onames == NULL) {
							 | 
						|
									    retval = fprintf(fp,"\"F%d\"", i);
							 | 
						|
									} else {
							 | 
						|
									    retval = fprintf(fp,"\"  %s  \"", onames[i]);
							 | 
						|
									}
							 | 
						|
									if (retval == EOF) goto failure;
							 | 
						|
									if (i == n - 1) {
							 | 
						|
									    retval = fprintf(fp,"; }\n");
							 | 
						|
									} else {
							 | 
						|
									    retval = fprintf(fp," -> ");
							 | 
						|
									}
							 | 
						|
									if (retval == EOF) goto failure;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    /* Write rank info: All nodes with the same index have the same rank. */
							 | 
						|
								    for (i = 0; i < nvars; i++) {
							 | 
						|
									if (sorted[dd->invpermZ[i]]) {
							 | 
						|
									    retval = fprintf(fp,"{ rank = same; ");
							 | 
						|
									    if (retval == EOF) goto failure;
							 | 
						|
									    if (inames == NULL) {
							 | 
						|
										retval = fprintf(fp,"\" %d \";\n", dd->invpermZ[i]);
							 | 
						|
									    } else {
							 | 
						|
										retval = fprintf(fp,"\" %s \";\n", inames[dd->invpermZ[i]]);
							 | 
						|
									    }
							 | 
						|
									    if (retval == EOF) goto failure;
							 | 
						|
									    nodelist = dd->subtableZ[i].nodelist;
							 | 
						|
									    slots = dd->subtableZ[i].slots;
							 | 
						|
									    for (j = 0; j < slots; j++) {
							 | 
						|
										scan = nodelist[j];
							 | 
						|
										while (scan != NULL) {
							 | 
						|
										    if (st_is_member(visited,(char *) scan)) {
							 | 
						|
											retval = fprintf(fp,"\"%p\";\n", (void *)
							 | 
						|
													 ((mask & (ptrint) scan) /
							 | 
						|
													  sizeof(DdNode)));
							 | 
						|
											if (retval == EOF) goto failure;
							 | 
						|
										    }
							 | 
						|
										    scan = scan->next;
							 | 
						|
										}
							 | 
						|
									    }
							 | 
						|
									    retval = fprintf(fp,"}\n");
							 | 
						|
									    if (retval == EOF) goto failure;
							 | 
						|
									}
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    /* All constants have the same rank. */
							 | 
						|
								    retval = fprintf(fp,
							 | 
						|
									"{ rank = same; \"CONST NODES\";\n{ node [shape = box]; ");
							 | 
						|
								    if (retval == EOF) goto failure;
							 | 
						|
								    nodelist = dd->constants.nodelist;
							 | 
						|
								    slots = dd->constants.slots;
							 | 
						|
								    for (j = 0; j < slots; j++) {
							 | 
						|
									scan = nodelist[j];
							 | 
						|
									while (scan != NULL) {
							 | 
						|
									    if (st_is_member(visited,(char *) scan)) {
							 | 
						|
										retval = fprintf(fp,"\"%p\";\n", (void *)
							 | 
						|
												 ((mask & (ptrint) scan) / sizeof(DdNode)));
							 | 
						|
										if (retval == EOF) goto failure;
							 | 
						|
									    }
							 | 
						|
									    scan = scan->next;
							 | 
						|
									}
							 | 
						|
								    }
							 | 
						|
								    retval = fprintf(fp,"}\n}\n");
							 | 
						|
								    if (retval == EOF) goto failure;
							 | 
						|
								
							 | 
						|
								    /* Write edge info. */
							 | 
						|
								    /* Edges from the output nodes. */
							 | 
						|
								    for (i = 0; i < n; i++) {
							 | 
						|
									if (onames == NULL) {
							 | 
						|
									    retval = fprintf(fp,"\"F%d\"", i);
							 | 
						|
									} else {
							 | 
						|
									    retval = fprintf(fp,"\"  %s  \"", onames[i]);
							 | 
						|
									}
							 | 
						|
									if (retval == EOF) goto failure;
							 | 
						|
									retval = fprintf(fp," -> \"%p\" [style = solid];\n",
							 | 
						|
											 (void *) ((mask & (ptrint) f[i]) /
							 | 
						|
													  sizeof(DdNode)));
							 | 
						|
									if (retval == EOF) goto failure;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    /* Edges from internal nodes. */
							 | 
						|
								    for (i = 0; i < nvars; i++) {
							 | 
						|
									if (sorted[dd->invpermZ[i]]) {
							 | 
						|
									    nodelist = dd->subtableZ[i].nodelist;
							 | 
						|
									    slots = dd->subtableZ[i].slots;
							 | 
						|
									    for (j = 0; j < slots; j++) {
							 | 
						|
										scan = nodelist[j];
							 | 
						|
										while (scan != NULL) {
							 | 
						|
										    if (st_is_member(visited,(char *) scan)) {
							 | 
						|
											retval = fprintf(fp,
							 | 
						|
											    "\"%p\" -> \"%p\";\n",
							 | 
						|
											    (void *) ((mask & (ptrint) scan) / sizeof(DdNode)),
							 | 
						|
											    (void *) ((mask & (ptrint) cuddT(scan)) /
							 | 
						|
												      sizeof(DdNode)));
							 | 
						|
											if (retval == EOF) goto failure;
							 | 
						|
											retval = fprintf(fp,
							 | 
						|
													 "\"%p\" -> \"%p\" [style = dashed];\n",
							 | 
						|
													 (void *) ((mask & (ptrint) scan)
							 | 
						|
														   / sizeof(DdNode)),
							 | 
						|
													 (void *) ((mask & (ptrint)
							 | 
						|
														    cuddE(scan)) /
							 | 
						|
														   sizeof(DdNode)));
							 | 
						|
											if (retval == EOF) goto failure;
							 | 
						|
										    }
							 | 
						|
										    scan = scan->next;
							 | 
						|
										}
							 | 
						|
									    }
							 | 
						|
									}
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    /* Write constant labels. */
							 | 
						|
								    nodelist = dd->constants.nodelist;
							 | 
						|
								    slots = dd->constants.slots;
							 | 
						|
								    for (j = 0; j < slots; j++) {
							 | 
						|
									scan = nodelist[j];
							 | 
						|
									while (scan != NULL) {
							 | 
						|
									    if (st_is_member(visited,(char *) scan)) {
							 | 
						|
										retval = fprintf(fp,"\"%p\" [label = \"%g\"];\n",
							 | 
						|
												 (void *) ((mask & (ptrint) scan) /
							 | 
						|
													   sizeof(DdNode)),
							 | 
						|
												 cuddV(scan));
							 | 
						|
										if (retval == EOF) goto failure;
							 | 
						|
									    }
							 | 
						|
									    scan = scan->next;
							 | 
						|
									}
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    /* Write trailer and return. */
							 | 
						|
								    retval = fprintf(fp,"}\n");
							 | 
						|
								    if (retval == EOF) goto failure;
							 | 
						|
								
							 | 
						|
								    st_free_table(visited);
							 | 
						|
								    FREE(sorted);
							 | 
						|
								    return(1);
							 | 
						|
								
							 | 
						|
								failure:
							 | 
						|
								    if (sorted != NULL) FREE(sorted);
							 | 
						|
								    if (visited != NULL) st_free_table(visited);
							 | 
						|
								    return(0);
							 | 
						|
								
							 | 
						|
								} /* end of Cudd_zddDumpBlif */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								/* Definition of internal functions                                          */
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis [Prints a ZDD to the standard output. One line per node is
							 | 
						|
								  printed.]
							 | 
						|
								
							 | 
						|
								  Description [Prints a ZDD to the standard output. One line per node is
							 | 
						|
								  printed. Returns 1 if successful; 0 otherwise.]
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     [Cudd_zddPrintDebug]
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								int
							 | 
						|
								cuddZddP(
							 | 
						|
								  DdManager * zdd,
							 | 
						|
								  DdNode * f)
							 | 
						|
								{
							 | 
						|
								    int retval;
							 | 
						|
								    st_table *table = st_init_table(st_ptrcmp, st_ptrhash);
							 | 
						|
								
							 | 
						|
								    if (table == NULL) return(0);
							 | 
						|
								
							 | 
						|
								    retval = zp2(zdd, f, table);
							 | 
						|
								    st_free_table(table);
							 | 
						|
								    (void) fputc('\n', zdd->out);
							 | 
						|
								    return(retval);
							 | 
						|
								
							 | 
						|
								} /* end of cuddZddP */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								/* Definition of static functions                                            */
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis [Performs the recursive step of cuddZddP.]
							 | 
						|
								
							 | 
						|
								  Description [Performs the recursive step of cuddZddP. Returns 1 in
							 | 
						|
								  case of success; 0 otherwise.]
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     []
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								static int
							 | 
						|
								zp2(
							 | 
						|
								  DdManager * zdd,
							 | 
						|
								  DdNode * f,
							 | 
						|
								  st_table * t)
							 | 
						|
								{
							 | 
						|
								    DdNode	*n;
							 | 
						|
								    int		T, E;
							 | 
						|
								    DdNode	*base = DD_ONE(zdd);
							 | 
						|
								
							 | 
						|
								    if (f == NULL)
							 | 
						|
									return(0);
							 | 
						|
								
							 | 
						|
								    if (Cudd_IsConstant(f)) {
							 | 
						|
									(void)fprintf(zdd->out, "ID = %d\n", (f == base));
							 | 
						|
									return(1);
							 | 
						|
								    }
							 | 
						|
								    if (st_is_member(t, (char *)f) == 1)
							 | 
						|
									return(1);
							 | 
						|
								
							 | 
						|
								    if (st_insert(t, (char *) f, NULL) == ST_OUT_OF_MEM)
							 | 
						|
									return(0);
							 | 
						|
								
							 | 
						|
								#if SIZEOF_VOID_P == 8
							 | 
						|
								    (void) fprintf(zdd->out, "ID = 0x%lx\tindex = %u\tr = %u\t",
							 | 
						|
									(ptruint)f / (ptruint) sizeof(DdNode), f->index, f->ref);
							 | 
						|
								#else
							 | 
						|
								    (void) fprintf(zdd->out, "ID = 0x%x\tindex = %hu\tr = %hu\t",
							 | 
						|
									(ptruint)f / (ptruint) sizeof(DdNode), f->index, f->ref);
							 | 
						|
								#endif
							 | 
						|
								
							 | 
						|
								    n = cuddT(f);
							 | 
						|
								    if (Cudd_IsConstant(n)) {
							 | 
						|
									(void) fprintf(zdd->out, "T = %d\t\t", (n == base));
							 | 
						|
									T = 1;
							 | 
						|
								    } else {
							 | 
						|
								#if SIZEOF_VOID_P == 8
							 | 
						|
									(void) fprintf(zdd->out, "T = 0x%lx\t", (ptruint) n /
							 | 
						|
										       (ptruint) sizeof(DdNode));
							 | 
						|
								#else
							 | 
						|
									(void) fprintf(zdd->out, "T = 0x%x\t", (ptruint) n /
							 | 
						|
										       (ptruint) sizeof(DdNode));
							 | 
						|
								#endif
							 | 
						|
									T = 0;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    n = cuddE(f);
							 | 
						|
								    if (Cudd_IsConstant(n)) {
							 | 
						|
									(void) fprintf(zdd->out, "E = %d\n", (n == base));
							 | 
						|
									E = 1;
							 | 
						|
								    } else {
							 | 
						|
								#if SIZEOF_VOID_P == 8
							 | 
						|
									(void) fprintf(zdd->out, "E = 0x%lx\n", (ptruint) n /
							 | 
						|
										      (ptruint) sizeof(DdNode));
							 | 
						|
								#else
							 | 
						|
									(void) fprintf(zdd->out, "E = 0x%x\n", (ptruint) n /
							 | 
						|
										       (ptruint) sizeof(DdNode));
							 | 
						|
								#endif
							 | 
						|
									E = 0;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    if (E == 0)
							 | 
						|
									if (zp2(zdd, cuddE(f), t) == 0) return(0);
							 | 
						|
								    if (T == 0)
							 | 
						|
									if (zp2(zdd, cuddT(f), t) == 0) return(0);
							 | 
						|
								    return(1);
							 | 
						|
								
							 | 
						|
								} /* end of zp2 */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis    [Performs the recursive step of Cudd_zddPrintMinterm.]
							 | 
						|
								
							 | 
						|
								  Description []
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     []
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								static void
							 | 
						|
								zdd_print_minterm_aux(
							 | 
						|
								  DdManager * zdd /* manager */,
							 | 
						|
								  DdNode * node /* current node */,
							 | 
						|
								  int  level /* depth in the recursion */,
							 | 
						|
								  int * list /* current recursion path */)
							 | 
						|
								{
							 | 
						|
								    DdNode	*Nv, *Nnv;
							 | 
						|
								    int		i, v;
							 | 
						|
								    DdNode	*base = DD_ONE(zdd);
							 | 
						|
								
							 | 
						|
								    if (Cudd_IsConstant(node)) {
							 | 
						|
									if (node == base) {
							 | 
						|
									    /* Check for missing variable. */
							 | 
						|
									    if (level != zdd->sizeZ) {
							 | 
						|
										list[zdd->invpermZ[level]] = 0;
							 | 
						|
										zdd_print_minterm_aux(zdd, node, level + 1, list);
							 | 
						|
										return;
							 | 
						|
									    }
							 | 
						|
									    /* Terminal case: Print one cube based on the current recursion
							 | 
						|
									    ** path.
							 | 
						|
									    */
							 | 
						|
									    for (i = 0; i < zdd->sizeZ; i++) {
							 | 
						|
										v = list[i];
							 | 
						|
										if (v == 0)
							 | 
						|
										    (void) fprintf(zdd->out,"0");
							 | 
						|
										else if (v == 1)
							 | 
						|
										    (void) fprintf(zdd->out,"1");
							 | 
						|
										else if (v == 3)
							 | 
						|
										    (void) fprintf(zdd->out,"@");	/* should never happen */
							 | 
						|
										else
							 | 
						|
										    (void) fprintf(zdd->out,"-");
							 | 
						|
									    }
							 | 
						|
									    (void) fprintf(zdd->out," 1\n");
							 | 
						|
									}
							 | 
						|
								    } else {
							 | 
						|
									/* Check for missing variable. */
							 | 
						|
									if (level != cuddIZ(zdd,node->index)) {
							 | 
						|
									    list[zdd->invpermZ[level]] = 0;
							 | 
						|
									    zdd_print_minterm_aux(zdd, node, level + 1, list);
							 | 
						|
									    return;
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									Nnv = cuddE(node);
							 | 
						|
									Nv = cuddT(node);
							 | 
						|
									if (Nv == Nnv) {
							 | 
						|
									    list[node->index] = 2;
							 | 
						|
									    zdd_print_minterm_aux(zdd, Nnv, level + 1, list);
							 | 
						|
									    return;
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									list[node->index] = 1;
							 | 
						|
									zdd_print_minterm_aux(zdd, Nv, level + 1, list);
							 | 
						|
									list[node->index] = 0;
							 | 
						|
									zdd_print_minterm_aux(zdd, Nnv, level + 1, list);
							 | 
						|
								    }
							 | 
						|
								    return;
							 | 
						|
								
							 | 
						|
								} /* end of zdd_print_minterm_aux */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis    [Performs the recursive step of Cudd_zddPrintCover.]
							 | 
						|
								
							 | 
						|
								  Description []
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     []
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								static void
							 | 
						|
								zddPrintCoverAux(
							 | 
						|
								  DdManager * zdd /* manager */,
							 | 
						|
								  DdNode * node /* current node */,
							 | 
						|
								  int  level /* depth in the recursion */,
							 | 
						|
								  int * list /* current recursion path */)
							 | 
						|
								{
							 | 
						|
								    DdNode	*Nv, *Nnv;
							 | 
						|
								    int		i, v;
							 | 
						|
								    DdNode	*base = DD_ONE(zdd);
							 | 
						|
								
							 | 
						|
								    if (Cudd_IsConstant(node)) {
							 | 
						|
									if (node == base) {
							 | 
						|
									    /* Check for missing variable. */
							 | 
						|
									    if (level != zdd->sizeZ) {
							 | 
						|
										list[zdd->invpermZ[level]] = 0;
							 | 
						|
										zddPrintCoverAux(zdd, node, level + 1, list);
							 | 
						|
										return;
							 | 
						|
									    }
							 | 
						|
									    /* Terminal case: Print one cube based on the current recursion
							 | 
						|
									    ** path.
							 | 
						|
									    */
							 | 
						|
									    for (i = 0; i < zdd->sizeZ; i += 2) {
							 | 
						|
										v = list[i] * 4 + list[i+1];
							 | 
						|
										if (v == 0)
							 | 
						|
										    (void) putc('-',zdd->out);
							 | 
						|
										else if (v == 4)
							 | 
						|
										    (void) putc('1',zdd->out);
							 | 
						|
										else if (v == 1)
							 | 
						|
										    (void) putc('0',zdd->out);
							 | 
						|
										else
							 | 
						|
										    (void) putc('@',zdd->out); /* should never happen */
							 | 
						|
									    }
							 | 
						|
									    (void) fprintf(zdd->out," 1\n");
							 | 
						|
									}
							 | 
						|
								    } else {
							 | 
						|
									/* Check for missing variable. */
							 | 
						|
									if (level != cuddIZ(zdd,node->index)) {
							 | 
						|
									    list[zdd->invpermZ[level]] = 0;
							 | 
						|
									    zddPrintCoverAux(zdd, node, level + 1, list);
							 | 
						|
									    return;
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									Nnv = cuddE(node);
							 | 
						|
									Nv = cuddT(node);
							 | 
						|
									if (Nv == Nnv) {
							 | 
						|
									    list[node->index] = 2;
							 | 
						|
									    zddPrintCoverAux(zdd, Nnv, level + 1, list);
							 | 
						|
									    return;
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									list[node->index] = 1;
							 | 
						|
									zddPrintCoverAux(zdd, Nv, level + 1, list);
							 | 
						|
									list[node->index] = 0;
							 | 
						|
									zddPrintCoverAux(zdd, Nnv, level + 1, list);
							 | 
						|
								    }
							 | 
						|
								    return;
							 | 
						|
								
							 | 
						|
								} /* end of zddPrintCoverAux */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis    [Performs the recursive step of Cudd_zddSupport.]
							 | 
						|
								
							 | 
						|
								  Description [Performs the recursive step of Cudd_zddSupport. Performs a
							 | 
						|
								  DFS from f. The support is accumulated in supp as a side effect. Uses
							 | 
						|
								  the LSB of the then pointer as visited flag.]
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     [zddClearFlag]
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								static void
							 | 
						|
								zddSupportStep(
							 | 
						|
								  DdNode * f,
							 | 
						|
								  int * support)
							 | 
						|
								{
							 | 
						|
								    if (cuddIsConstant(f) || Cudd_IsComplement(f->next)) {
							 | 
						|
								        return;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    support[f->index] = 1;
							 | 
						|
								    zddSupportStep(cuddT(f),support);
							 | 
						|
								    zddSupportStep(Cudd_Regular(cuddE(f)),support);
							 | 
						|
								    /* Mark as visited. */
							 | 
						|
								    f->next = Cudd_Not(f->next);
							 | 
						|
								    return;
							 | 
						|
								
							 | 
						|
								} /* end of zddSupportStep */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis    [Performs a DFS from f, clearing the LSB of the next
							 | 
						|
								  pointers.]
							 | 
						|
								
							 | 
						|
								  Description []
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     [zddSupportStep]
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								static void
							 | 
						|
								zddClearFlag(
							 | 
						|
								  DdNode * f)
							 | 
						|
								{
							 | 
						|
								    if (!Cudd_IsComplement(f->next)) {
							 | 
						|
								        return;
							 | 
						|
								    }
							 | 
						|
								    /* Clear visited flag. */
							 | 
						|
								    f->next = Cudd_Regular(f->next);
							 | 
						|
								    if (cuddIsConstant(f)) {
							 | 
						|
								        return;
							 | 
						|
								    }
							 | 
						|
								    zddClearFlag(cuddT(f));
							 | 
						|
								    zddClearFlag(Cudd_Regular(cuddE(f)));
							 | 
						|
								    return;
							 | 
						|
								
							 | 
						|
								} /* end of zddClearFlag */
							 | 
						|
								
							 |