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.
		
		
		
		
		
			
		
			
				
					
					
						
							931 lines
						
					
					
						
							25 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							931 lines
						
					
					
						
							25 KiB
						
					
					
				| /**CFile********************************************************************** | |
|  | |
|   FileName     [dddmpNodeCnf.c] | |
|  | |
|   PackageName  [dddmp] | |
|  | |
|   Synopsis     [Functions to handle BDD node infos and numbering | |
|     while storing a CNF formula from a BDD or an array of BDDs] | |
|  | |
|   Description  [Functions to handle BDD node infos and numbering | |
|     while storing a CNF formula from a BDD or an array of BDDs. | |
|     ] | |
|  | |
|   Author       [Gianpiero Cabodi and Stefano Quer] | |
|  | |
|   Copyright    [ | |
|     Copyright (c) 2004 by Politecnico di Torino. | |
|     All Rights Reserved. This software is for educational purposes only. | |
|     Permission is given to academic institutions to use, copy, and modify | |
|     this software and its documentation provided that this introductory | |
|     message is not removed, that this software and its documentation is | |
|     used for the institutions' internal research and educational purposes, | |
|     and that no monies are exchanged. No guarantee is expressed or implied | |
|     by the distribution of this code. | |
|     Send bug-reports and/or questions to: | |
|     {gianpiero.cabodi,stefano.quer}@polito.it. | |
|     ] | |
|  | |
| ******************************************************************************/ | |
| 
 | |
| #include "dddmpInt.h" | |
|  | |
| /*---------------------------------------------------------------------------*/ | |
| /* Stucture declarations                                                     */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| /*---------------------------------------------------------------------------*/ | |
| /* Type declarations                                                         */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| /*---------------------------------------------------------------------------*/ | |
| /* Variable declarations                                                     */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| #define DDDMP_DEBUG_CNF 0 | |
|  | |
| /*---------------------------------------------------------------------------*/ | |
| /* Macro declarations                                                        */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| /**AutomaticStart*************************************************************/ | |
| 
 | |
| /*---------------------------------------------------------------------------*/ | |
| /* Static function prototypes                                                */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| static int DddmpWriteNodeIndexCnfWithTerminalCheck(DdNode *f, int *cnfIds, int id); | |
| #if 0 | |
| static int DddmpClearVisitedCnfRecur(DdNode *f); | |
| #endif | |
| static void DddmpClearVisitedCnf(DdNode *f); | |
| static int NumberNodeRecurCnf(DdNode *f, int *cnfIds, int id); | |
| static void DddmpDdNodesCheckIncomingAndScanPath(DdNode *f, int pathLengthCurrent, int edgeInTh, int pathLengthTh); | |
| static int DddmpDdNodesNumberEdgesRecur(DdNode *f, int *cnfIds, int id); | |
| static int DddmpDdNodesResetCountRecur(DdNode *f); | |
| static int DddmpDdNodesCountEdgesRecur(DdNode *f); | |
| static void RemoveFromUniqueRecurCnf(DdManager *ddMgr, DdNode *f); | |
| static void RestoreInUniqueRecurCnf(DdManager *ddMgr, DdNode *f); | |
| static int DddmpPrintBddAndNextRecur(DdManager *ddMgr, DdNode *f); | |
| 
 | |
| /**AutomaticEnd***************************************************************/ | |
| 
 | |
| /*---------------------------------------------------------------------------*/ | |
| /* Definition of exported functions                                          */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| /*---------------------------------------------------------------------------*/ | |
| /* Definition of internal functions                                          */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Removes nodes from unique table and numbers them] | |
|  | |
|   Description [Node numbering is required to convert pointers to integers. | |
|     Since nodes are removed from unique table, no new nodes should  | |
|     be generated before re-inserting nodes in the unique table | |
|     (DddmpUnnumberDdNodesCnf()). | |
|     ] | |
|  | |
|   SideEffects [Nodes are temporarily removed from unique table] | |
|  | |
|   SeeAlso     [RemoveFromUniqueRecurCnf(), NumberNodeRecurCnf(),  | |
|     DddmpUnnumberDdNodesCnf()] | |
|  | |
| ******************************************************************************/ | |
| 
 | |
| int | |
| DddmpNumberDdNodesCnf ( | |
|   DdManager *ddMgr  /*  IN: DD Manager */, | |
|   DdNode **f        /*  IN: array of BDDs */, | |
|   int rootN         /*  IN: number of BDD roots in the array of BDDs */, | |
|   int *cnfIds       /* OUT: CNF identifiers for variables */, | |
|   int id            /* OUT: number of Temporary Variables Introduced */ | |
|   ) | |
| { | |
|   int i; | |
| 
 | |
|   for (i=0; i<rootN; i++) { | |
|     RemoveFromUniqueRecurCnf (ddMgr, f[i]); | |
|   } | |
| 
 | |
|   for (i=0; i<rootN; i++) { | |
|     id = NumberNodeRecurCnf (f[i], cnfIds, id); | |
|   } | |
| 
 | |
|   return (id); | |
| } | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Removes nodes from unique table and numbers each node according | |
|     to the number of its incoming BDD edges. | |
|     ] | |
|  | |
|   Description [Removes nodes from unique table and numbers each node according | |
|     to the number of its incoming BDD edges. | |
|     ] | |
|  | |
|   SideEffects [Nodes are temporarily removed from unique table] | |
|  | |
|   SeeAlso     [RemoveFromUniqueRecurCnf()] | |
|  | |
| ******************************************************************************/ | |
| 
 | |
| int | |
| DddmpDdNodesCountEdgesAndNumber ( | |
|   DdManager *ddMgr    /*  IN: DD Manager */, | |
|   DdNode **f          /*  IN: Array of BDDs */, | |
|   int rootN           /*  IN: Number of BDD roots in the array of BDDs */, | |
|   int edgeInTh        /*  IN: Max # In-Edges, after a Insert Cut Point */, | |
|   int pathLengthTh    /*  IN: Max Path Length (after, Insert a Cut Point) */, | |
|   int *cnfIds         /* OUT: CNF identifiers for variables */, | |
|   int id              /* OUT: Number of Temporary Variables Introduced */ | |
|   ) | |
| { | |
|   int i; | |
| 
 | |
|   /*-------------------------- Remove From Unique ---------------------------*/ | |
| 
 | |
|   for (i=0; i<rootN; i++) { | |
|     RemoveFromUniqueRecurCnf (ddMgr, f[i]); | |
|   } | |
| 
 | |
|   /*-------------------- Reset Counter and Reset Visited --------------------*/ | |
| 
 | |
|   for (i=0; i<rootN; i++) { | |
|     (void) DddmpDdNodesResetCountRecur (f[i]); | |
|   } | |
| 
 | |
|   /*  Here we must have: | |
|    *    cnfIndex = 0 | |
|    *    visitedFlag = 0 | |
|    *  FOR ALL nodes | |
|    */ | |
| 
 | |
| #if DDDMP_DEBUG_CNF | |
|   fprintf (stdout, "###---> BDDs After Count Reset:\n"); | |
|   DddmpPrintBddAndNext (ddMgr, f, rootN); | |
| #endif | |
|  | |
|   /*----------------------- Count Incoming Edges ----------------------------*/ | |
| 
 | |
|   for (i=0; i<rootN; i++) { | |
|     (void) DddmpDdNodesCountEdgesRecur (f[i]); | |
|   } | |
| 
 | |
|   /*  Here we must have: | |
|    *    cnfIndex = incoming edge count | |
|    *    visitedFlag = 0 (AGAIN ... remains untouched) | |
|    *  FOR ALL nodes | |
|    */ | |
| 
 | |
| #if DDDMP_DEBUG_CNF | |
|   fprintf (stdout, "###---> BDDs After Count Recur:\n"); | |
|   DddmpPrintBddAndNext (ddMgr, f, rootN); | |
| #endif | |
|  | |
|   /*------------------------- Count Path Length ----------------------------*/ | |
|       | |
|   for (i=0; i<rootN; i++) { | |
|     DddmpDdNodesCheckIncomingAndScanPath (f[i], 0, edgeInTh, | |
|       pathLengthTh); | |
|   } | |
| 
 | |
|   /* Here we must have: | |
|    *   cnfIndex = 1 if we want to insert there a cut point | |
|    *              0 if we do NOT want to insert there a cut point | |
|    *    visitedFlag = 1 | |
|    *  FOR ALL nodes | |
|    */ | |
| 
 | |
| #if DDDMP_DEBUG_CNF | |
|   fprintf (stdout, "###---> BDDs After Check Incoming And Scan Path:\n"); | |
|   DddmpPrintBddAndNext (ddMgr, f, rootN); | |
| #endif | |
|  | |
|   /*-------------------- Number Nodes and Set Visited -----------------------*/ | |
| 
 | |
|   for (i=0; i<rootN; i++) { | |
|     id = DddmpDdNodesNumberEdgesRecur (f[i], cnfIds, id); | |
|   } | |
| 
 | |
|   /*  Here we must have: | |
|    *    cnfIndex = CNF auxiliary variable enumeration | |
|    *    visitedFlag = 0 | |
|    *  FOR ALL nodes | |
|    */ | |
| 
 | |
| #if DDDMP_DEBUG_CNF | |
|   fprintf (stdout, "###---> BDDs After Count Edges Recur:\n"); | |
|   DddmpPrintBddAndNext (ddMgr, f, rootN); | |
| #endif | |
|  | |
|   return (id); | |
| } | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis     [Restores nodes in unique table, loosing numbering] | |
|  | |
|   Description  [Node indexes are no more needed. Nodes are re-linked in the | |
|     unique table. | |
|     ] | |
|  | |
|   SideEffects  [None] | |
|  | |
|   SeeAlso      [DddmpNumberDdNode()] | |
|  | |
| ******************************************************************************/ | |
| 
 | |
| void | |
| DddmpUnnumberDdNodesCnf( | |
|   DdManager *ddMgr   /* IN: DD Manager */, | |
|   DdNode **f         /* IN: array of BDDs */, | |
|   int rootN           /* IN: number of BDD roots in the array of BDDs */ | |
|   ) | |
| { | |
|   int i; | |
| 
 | |
|   for (i=0; i<rootN; i++) { | |
|     RestoreInUniqueRecurCnf (ddMgr, f[i]); | |
|   } | |
| 
 | |
|   return; | |
| } | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis     [Prints debug information] | |
|  | |
|   Description  [Prints debug information for an array of BDDs on the screen] | |
|  | |
|   SideEffects  [None] | |
|  | |
|   SeeAlso      [] | |
|  | |
| ******************************************************************************/ | |
| 
 | |
| int | |
| DddmpPrintBddAndNext ( | |
|   DdManager *ddMgr   /* IN: DD Manager */, | |
|   DdNode **f         /* IN: Array of BDDs to be displayed */, | |
|   int rootN          /* IN: Number of BDD roots in the array of BDDs */ | |
|   ) | |
| { | |
|   int i; | |
| 
 | |
|   for (i=0; i<rootN; i++) { | |
|     fprintf (stdout, "---> Bdd %d:\n", i); | |
|     fflush (stdout); | |
|     DddmpPrintBddAndNextRecur (ddMgr, f[i]); | |
|   } | |
| 
 | |
|   return (DDDMP_SUCCESS); | |
| } | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis     [Write index to node] | |
|  | |
|   Description  [The index of the node is written in the "next" field of | |
|     a DdNode struct. LSB is not used (set to 0). It is used as  | |
|     "visited" flag in DD traversals. | |
|     ] | |
|  | |
|   SideEffects  [None] | |
|  | |
|   SeeAlso      [DddmpReadNodeIndexCnf(), DddmpSetVisitedCnf (), | |
|     DddmpVisitedCnf () | |
|     ] | |
|  | |
| ******************************************************************************/ | |
| 
 | |
| int | |
| DddmpWriteNodeIndexCnf ( | |
|   DdNode *f   /* IN: BDD node */, | |
|   int id      /* IN: index to be written */ | |
|   ) | |
| { | |
|   if (!Cudd_IsConstant (f)) { | |
|     f->next = (struct DdNode *)((ptruint)id<<1); | |
|   } | |
| 
 | |
|   return (DDDMP_SUCCESS); | |
| } | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis     [Returns true if node is visited] | |
|  | |
|   Description  [Returns true if node is visited] | |
|  | |
|   SideEffects  [None] | |
|  | |
|   SeeAlso      [DddmpSetVisitedCnf (), DddmpClearVisitedCnf ()] | |
|  | |
| ******************************************************************************/ | |
| 
 | |
| int | |
| DddmpVisitedCnf ( | |
|   DdNode *f      /* IN: BDD node to be tested */ | |
|   ) | |
| { | |
|   f = Cudd_Regular(f); | |
| 
 | |
|   return ((int)((ptruint)(f->next)) & (01)); | |
| } | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis     [Marks a node as visited] | |
|   | |
|   Description  [Marks a node as visited] | |
|  | |
|   SideEffects  [None] | |
|  | |
|   SeeAlso      [DddmpVisitedCnf (), DddmpClearVisitedCnf ()] | |
|  | |
| ******************************************************************************/ | |
| 
 | |
| void | |
| DddmpSetVisitedCnf ( | |
|   DdNode *f     /* IN: BDD node to be marked (as visited) */ | |
|   ) | |
| { | |
|   f = Cudd_Regular(f); | |
| 
 | |
|   f->next = (DdNode *)(ptruint)((int)((ptruint)(f->next))|01); | |
| 
 | |
|   return; | |
| } | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis     [Reads the index of a node] | |
|  | |
|   Description  [Reads the index of a node. LSB is skipped (used as visited | |
|     flag). | |
|     ] | |
|  | |
|   SideEffects  [None] | |
|  | |
|   SeeAlso      [DddmpWriteNodeIndexCnf(), DddmpSetVisitedCnf (), | |
|     DddmpVisitedCnf ()] | |
|  | |
| ******************************************************************************/ | |
| 
 | |
| int | |
| DddmpReadNodeIndexCnf ( | |
|   DdNode *f     /* IN: BDD node */ | |
|   ) | |
| { | |
|   if (!Cudd_IsConstant (f)) { | |
|     return ((int)(((ptruint)(f->next))>>1)); | |
|   } else { | |
|     return (1); | |
|   } | |
| } | |
| 
 | |
| /*---------------------------------------------------------------------------*/ | |
| /* Definition of static functions                                            */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis     [Write index to node] | |
|  | |
|   Description  [The index of the node is written in the "next" field of | |
|     a DdNode struct. LSB is not used (set to 0). It is used as  | |
|     "visited" flag in DD traversals. The index corresponds to  | |
|     the BDD node variable if both the node's children are a  | |
|     constant node, otherwise a new CNF variable is used.  | |
|     ] | |
|  | |
|   SideEffects  [None] | |
|  | |
|   SeeAlso      [DddmpReadNodeIndexCnf(), DddmpSetVisitedCnf (), | |
|     DddmpVisitedCnf ()] | |
|  | |
| *****************************************************************************/ | |
| 
 | |
| static int | |
| DddmpWriteNodeIndexCnfWithTerminalCheck ( | |
|   DdNode *f    /* IN: BDD node */, | |
|   int *cnfIds  /* IN: possible source for the index to be written */, | |
|   int id       /* IN: possible source for the index to be written */ | |
|   ) | |
| { | |
|   if (!Cudd_IsConstant (f)) { | |
|     if (Cudd_IsConstant (cuddT (f)) && Cudd_IsConstant (cuddE (f))) { | |
|       /* If Variable SET ID as Variable ID */ | |
|       f->next = (struct DdNode *)((ptruint)cnfIds[f->index]<<1); | |
|     } else { | |
|       f->next = (struct DdNode *)((ptruint)id<<1); | |
|       id++; | |
|     } | |
|   } | |
| 
 | |
|   return(id); | |
| } | |
| 
 | |
| #if 0 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis     [Mark ALL nodes as not visited] | |
|  | |
|   Description  [Mark ALL nodes as not visited (it recurs on the node children)] | |
|  | |
|   SideEffects  [None] | |
|  | |
|   SeeAlso      [DddmpVisitedCnf (), DddmpSetVisitedCnf ()] | |
|  | |
| ******************************************************************************/ | |
|  | |
| static int | |
| DddmpClearVisitedCnfRecur ( | |
|   DdNode *f     /* IN: root of the BDD to be marked */ | |
|   ) | |
| { | |
|   f = Cudd_Regular(f); | |
|  | |
|   if (cuddIsConstant (f)) { | |
|     return (DDDMP_SUCCESS); | |
|   } | |
|  | |
|   if (!DddmpVisitedCnf (f)) { | |
|     return (DDDMP_SUCCESS); | |
|   } | |
|  | |
|   (void) DddmpClearVisitedCnfRecur (cuddT (f)); | |
|   (void) DddmpClearVisitedCnfRecur (cuddE (f)); | |
|  | |
|   DddmpClearVisitedCnf (f); | |
|  | |
|   return (DDDMP_SUCCESS); | |
| } | |
| #endif | |
|  | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis     [Marks a node as not visited] | |
|  | |
|   Description  [Marks a node as not visited] | |
|  | |
|   SideEffects  [None] | |
|  | |
|   SeeAlso      [DddmpVisitedCnf (), DddmpSetVisitedCnf ()] | |
|  | |
| ******************************************************************************/ | |
| 
 | |
| static void | |
| DddmpClearVisitedCnf ( | |
|   DdNode *f     /* IN: BDD node to be marked (as not visited) */ | |
|   ) | |
| { | |
|   f = Cudd_Regular (f); | |
| 
 | |
|   f->next = (DdNode *)(ptruint)((int)((ptruint)(f->next)) & (~01)); | |
| 
 | |
|   return; | |
| } | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis     [Number nodes recursively in post-order] | |
|  | |
|   Description  [Number nodes recursively in post-order. | |
|     The "visited" flag is used with inverse polarity, because all nodes | |
|     were set "visited" when removing them from unique.  | |
|     ] | |
|  | |
|   SideEffects  ["visited" flags are reset.] | |
|  | |
|   SeeAlso      [] | |
|  | |
| ******************************************************************************/ | |
| 
 | |
| static int | |
| NumberNodeRecurCnf( | |
|   DdNode *f        /*  IN: root of the BDD to be numbered */, | |
|   int *cnfIds      /*  IN: possible source for numbering */, | |
|   int id        /* IN/OUT: possible source for numbering */ | |
|   ) | |
| { | |
|   f = Cudd_Regular(f); | |
| 
 | |
|   if (!DddmpVisitedCnf (f)) { | |
|     return (id); | |
|   } | |
| 
 | |
|   if (!cuddIsConstant (f)) { | |
|     id = NumberNodeRecurCnf (cuddT (f), cnfIds, id); | |
|     id = NumberNodeRecurCnf (cuddE (f), cnfIds, id); | |
|   } | |
| 
 | |
|   id = DddmpWriteNodeIndexCnfWithTerminalCheck (f, cnfIds, id); | |
|   DddmpClearVisitedCnf (f); | |
| 
 | |
|   return (id); | |
| } | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis     [Number nodes recursively in post-order] | |
|  | |
|   Description  [Number nodes recursively in post-order. | |
|     The "visited" flag is used with the right polarity. | |
|     The node is assigned to a new CNF variable only if it is a "shared" | |
|     node (i.e. the number of its incoming edges is greater than 1).  | |
|     ] | |
|  | |
|   SideEffects  ["visited" flags are set.] | |
|  | |
|   SeeAlso      [] | |
|  | |
| ******************************************************************************/ | |
| 
 | |
| static void | |
| DddmpDdNodesCheckIncomingAndScanPath ( | |
|   DdNode *f             /* IN: BDD node to be numbered */, | |
|   int pathLengthCurrent /* IN: Current Path Length */, | |
|   int edgeInTh          /* IN: Max # In-Edges, after a Insert Cut Point */, | |
|   int pathLengthTh      /* IN: Max Path Length (after, Insert a Cut Point) */ | |
|   ) | |
| { | |
|   int retValue; | |
| 
 | |
|   f = Cudd_Regular(f); | |
| 
 | |
|   if (DddmpVisitedCnf (f)) { | |
|     return; | |
|   } | |
| 
 | |
|   if (cuddIsConstant (f)) { | |
|     return; | |
|   } | |
| 
 | |
|   pathLengthCurrent++; | |
|   retValue = DddmpReadNodeIndexCnf (f); | |
| 
 | |
|   if ( ((edgeInTh >= 0) && (retValue > edgeInTh)) || | |
|        ((pathLengthTh >= 0) && (pathLengthCurrent > pathLengthTh)) | |
|      ) { | |
|     DddmpWriteNodeIndexCnf (f, 1); | |
|     pathLengthCurrent = 0; | |
|   } else { | |
|     DddmpWriteNodeIndexCnf (f, 0); | |
|   } | |
| 
 | |
|   DddmpDdNodesCheckIncomingAndScanPath (cuddT (f), pathLengthCurrent, | |
|     edgeInTh, pathLengthTh); | |
|   DddmpDdNodesCheckIncomingAndScanPath (cuddE (f), pathLengthCurrent, | |
|     edgeInTh, pathLengthTh); | |
| 
 | |
|   DddmpSetVisitedCnf (f); | |
| 
 | |
|   return; | |
| } | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis     [Number nodes recursively in post-order] | |
|  | |
|   Description  [Number nodes recursively in post-order. | |
|     The "visited" flag is used with the inverse polarity. | |
|     Numbering follows the subsequent strategy: | |
|     * if the index = 0 it remains so | |
|     * if the index >= 1 it gets enumerated. | |
|       This implies that the node is assigned to a new CNF variable only if | |
|       it is not a terminal node otherwise it is assigned the index of | |
|       the BDD variable. | |
|     ] | |
|  | |
|   SideEffects  ["visited" flags are reset.] | |
|  | |
|   SeeAlso      [] | |
|  | |
| ******************************************************************************/ | |
| 
 | |
| static int | |
| DddmpDdNodesNumberEdgesRecur ( | |
|   DdNode *f      /*  IN: BDD node to be numbered */, | |
|   int *cnfIds    /*  IN: possible source for numbering */, | |
|   int id      /* IN/OUT: possible source for numbering */ | |
|   ) | |
| { | |
|   int retValue; | |
| 
 | |
|   f = Cudd_Regular(f); | |
| 
 | |
|   if (!DddmpVisitedCnf (f)) { | |
|     return (id); | |
|   } | |
| 
 | |
|   if (cuddIsConstant (f)) { | |
|     return (id); | |
|   } | |
| 
 | |
|   id = DddmpDdNodesNumberEdgesRecur (cuddT (f), cnfIds, id); | |
|   id = DddmpDdNodesNumberEdgesRecur (cuddE (f), cnfIds, id); | |
| 
 | |
|   retValue = DddmpReadNodeIndexCnf (f); | |
|   if (retValue >= 1) { | |
|     id = DddmpWriteNodeIndexCnfWithTerminalCheck (f, cnfIds, id); | |
|   } else { | |
|     DddmpWriteNodeIndexCnf (f, 0); | |
|   } | |
| 
 | |
|   DddmpClearVisitedCnf (f); | |
| 
 | |
|   return (id); | |
| } | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis     [Resets counter and visited flag for ALL nodes of a BDD] | |
|  | |
|   Description  [Resets counter and visited flag for ALL nodes of a BDD (it  | |
|     recurs on the node children). The index field of the node is  | |
|     used as counter. | |
|     ] | |
|  | |
|   SideEffects  [] | |
|  | |
|   SeeAlso      [] | |
|  | |
| ******************************************************************************/ | |
| 
 | |
| static int | |
| DddmpDdNodesResetCountRecur ( | |
|   DdNode *f  /*  IN: root of the BDD whose counters are reset */ | |
|   ) | |
| { | |
|   f = Cudd_Regular (f); | |
| 
 | |
|   if (!DddmpVisitedCnf (f)) { | |
|     return (DDDMP_SUCCESS); | |
|   } | |
| 
 | |
|   if (!cuddIsConstant (f)) { | |
|     (void) DddmpDdNodesResetCountRecur (cuddT (f)); | |
|     (void) DddmpDdNodesResetCountRecur (cuddE (f)); | |
|   } | |
| 
 | |
|   DddmpWriteNodeIndexCnf (f, 0); | |
|   DddmpClearVisitedCnf (f); | |
| 
 | |
|   return (DDDMP_SUCCESS); | |
| } | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis     [Counts the number of incoming edges for each node of a BDD] | |
|  | |
|   Description  [Counts (recursively) the number of incoming edges for each  | |
|     node of a BDD. This number is stored in the index field. | |
|     ] | |
|  | |
|   SideEffects  ["visited" flags remain untouched.] | |
|  | |
|   SeeAlso      [] | |
|  | |
| ******************************************************************************/ | |
| 
 | |
| static int | |
| DddmpDdNodesCountEdgesRecur ( | |
|   DdNode *f    /* IN: root of the BDD */ | |
|   ) | |
| { | |
|   int indexValue; | |
| 
 | |
|   f = Cudd_Regular (f); | |
| 
 | |
|   if (cuddIsConstant (f)) { | |
|     return (DDDMP_SUCCESS); | |
|   } | |
| 
 | |
|   if (Cudd_IsConstant (cuddT (f)) && Cudd_IsConstant (cuddE (f))) { | |
|     return (DDDMP_SUCCESS); | |
|   } | |
| 
 | |
|   indexValue = DddmpReadNodeIndexCnf (f); | |
| 
 | |
|   /* IF (first time) THEN recur */ | |
|   if (indexValue == 0) { | |
|     (void) DddmpDdNodesCountEdgesRecur (cuddT (f)); | |
|     (void) DddmpDdNodesCountEdgesRecur (cuddE (f)); | |
|   } | |
| 
 | |
|   /* Increment Incoming-Edge Count Flag */ | |
|   indexValue++; | |
|   DddmpWriteNodeIndexCnf (f, indexValue); | |
| 
 | |
|   return (DDDMP_SUCCESS); | |
| } | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Removes a node from unique table] | |
|  | |
|   Description [Removes a node from the unique table by locating the proper | |
|     subtable and unlinking the node from it. It recurs on  on the  | |
|     children of the node. Constants remain untouched. | |
|     ] | |
|  | |
|   SideEffects [Nodes are left with the "visited" flag true.] | |
|  | |
|   SeeAlso     [RestoreInUniqueRecurCnf()] | |
|  | |
| ******************************************************************************/ | |
| 
 | |
| static void | |
| RemoveFromUniqueRecurCnf ( | |
|   DdManager *ddMgr  /*  IN: DD Manager */, | |
|   DdNode *f         /*  IN: root of the BDD to be extracted */ | |
|   ) | |
| { | |
|   DdNode *node, *last, *next; | |
|   DdNode *sentinel = &(ddMgr->sentinel); | |
|   DdNodePtr *nodelist; | |
|   DdSubtable *subtable; | |
|   int pos, level; | |
| 
 | |
|   f = Cudd_Regular (f); | |
| 
 | |
|   if (DddmpVisitedCnf (f)) { | |
|     return; | |
|   } | |
| 
 | |
|   if (!cuddIsConstant (f)) { | |
| 
 | |
|     RemoveFromUniqueRecurCnf (ddMgr, cuddT (f)); | |
|     RemoveFromUniqueRecurCnf (ddMgr, cuddE (f)); | |
| 
 | |
|     level = ddMgr->perm[f->index]; | |
|     subtable = &(ddMgr->subtables[level]); | |
| 
 | |
|     nodelist = subtable->nodelist; | |
| 
 | |
|     pos = ddHash (cuddT (f), cuddE (f), subtable->shift); | |
|     node = nodelist[pos]; | |
|     last = NULL; | |
|     while (node != sentinel) { | |
|       next = node->next; | |
|       if (node == f) { | |
|         if (last != NULL)   | |
|   	  last->next = next; | |
|         else  | |
|           nodelist[pos] = next; | |
|         break; | |
|       } else { | |
|         last = node; | |
|         node = next; | |
|       } | |
|     } | |
| 
 | |
|     f->next = NULL; | |
| 
 | |
|   } | |
| 
 | |
|   DddmpSetVisitedCnf (f); | |
| 
 | |
|   return; | |
| } | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis     [Restores a node in unique table] | |
|  | |
|   Description  [Restores a node in unique table (recursive)] | |
|  | |
|   SideEffects  [Nodes are not restored in the same order as before removal] | |
|  | |
|   SeeAlso      [RemoveFromUnique()] | |
|  | |
| ******************************************************************************/ | |
| 
 | |
| static void | |
| RestoreInUniqueRecurCnf ( | |
|   DdManager *ddMgr  /*  IN: DD Manager */, | |
|   DdNode *f         /*  IN: root of the BDD to be restored */ | |
|   ) | |
| { | |
|   DdNodePtr *nodelist; | |
|   DdNode *T, *E, *looking; | |
|   DdNodePtr *previousP; | |
|   DdSubtable *subtable; | |
|   int pos, level; | |
| #ifdef DDDMP_DEBUG | |
|   DdNode *node; | |
|   DdNode *sentinel = &(ddMgr->sentinel); | |
| #endif | |
|  | |
|   f = Cudd_Regular(f); | |
| 
 | |
|   if (!Cudd_IsComplement (f->next)) { | |
|     return; | |
|   } | |
| 
 | |
|   if (cuddIsConstant (f)) { | |
|     /* StQ 11.02.2004: | |
|        Bug fixed --> restore NULL within the next field */ | |
|     /*DddmpClearVisitedCnf (f);*/ | |
|     f->next = NULL; | |
| 
 | |
|     return; | |
|   } | |
| 
 | |
|   RestoreInUniqueRecurCnf (ddMgr, cuddT (f)); | |
|   RestoreInUniqueRecurCnf (ddMgr, cuddE (f)); | |
| 
 | |
|   level = ddMgr->perm[f->index]; | |
|   subtable = &(ddMgr->subtables[level]); | |
| 
 | |
|   nodelist = subtable->nodelist; | |
| 
 | |
|   pos = ddHash (cuddT (f), cuddE (f), subtable->shift); | |
| 
 | |
| #ifdef DDDMP_DEBUG | |
|   /* verify uniqueness to avoid duplicate nodes in unique table */ | |
|   for (node=nodelist[pos]; node != sentinel; node=node->next) | |
|     assert(node!=f); | |
| #endif | |
|  | |
|   T = cuddT (f); | |
|   E = cuddE (f); | |
|   previousP = &(nodelist[pos]); | |
|   looking = *previousP; | |
| 
 | |
|   while (T < cuddT (looking)) { | |
|     previousP = &(looking->next); | |
|     looking = *previousP; | |
|   } | |
| 
 | |
|   while (T == cuddT (looking) && E < cuddE (looking)) { | |
|     previousP = &(looking->next); | |
|     looking = *previousP; | |
|   } | |
|   f->next = *previousP; | |
|   *previousP = f; | |
| 
 | |
|   return; | |
| } | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis     [Prints debug info] | |
|  | |
|   Description  [Prints debug info for a BDD on the screen. It recurs on  | |
|     node's children. | |
|     ] | |
|  | |
|   SideEffects  [] | |
|  | |
|   SeeAlso      [] | |
|  | |
| ******************************************************************************/ | |
| 
 | |
| static int | |
| DddmpPrintBddAndNextRecur ( | |
|   DdManager *ddMgr   /* IN: DD Manager */, | |
|   DdNode *f          /* IN: root of the BDD to be displayed */ | |
|   ) | |
| { | |
|   DdNode *fPtr, *tPtr, *ePtr; | |
| 
 | |
|   fPtr = Cudd_Regular (f); | |
| 
 | |
|   if (Cudd_IsComplement (f)) { | |
|     fprintf (stdout, "sign=- ptr=%" PRIiPTR " ", ((ptrint) fPtr)); | |
|   } else { | |
|     fprintf (stdout, "sign=+ ptr=%" PRIiPTR " ", ((ptrint) fPtr)); | |
|   } | |
| 
 | |
|   if (cuddIsConstant (fPtr)) { | |
|     fprintf (stdout, "one\n"); | |
|     fflush (stdout); | |
|     return (DDDMP_SUCCESS); | |
|   } | |
| 
 | |
|   fprintf (stdout, | |
|     "thenPtr=%" PRIiPTR " elsePtr=%" PRIiPTR " BddId=%d CnfId=%d Visited=%d\n", | |
|     ((ptrint) cuddT (fPtr)), ((ptrint) cuddE (fPtr)), | |
|     fPtr->index, DddmpReadNodeIndexCnf (fPtr), | |
|     DddmpVisitedCnf (fPtr)); | |
|    | |
|   tPtr  = cuddT (fPtr); | |
|   ePtr = cuddE (fPtr); | |
|   if (Cudd_IsComplement (f)) { | |
|     tPtr  = Cudd_Not (tPtr); | |
|     ePtr = Cudd_Not (ePtr); | |
|   } | |
| 
 | |
|   (void) DddmpPrintBddAndNextRecur (ddMgr, tPtr); | |
|   (void) DddmpPrintBddAndNextRecur (ddMgr, ePtr); | |
| 
 | |
|   return (DDDMP_SUCCESS); | |
| } | |
| 
 | |
| 
 |