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.
		
		
		
		
		
			
		
			
				
					
					
						
							432 lines
						
					
					
						
							13 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							432 lines
						
					
					
						
							13 KiB
						
					
					
				| /**CFile*********************************************************************** | |
|  | |
|   FileName    [cuddInteract.c] | |
|  | |
|   PackageName [cudd] | |
|  | |
|   Synopsis    [Functions to manipulate the variable interaction matrix.] | |
|  | |
|   Description [Internal procedures included in this file: | |
| 	<ul> | |
| 	<li> cuddSetInteract() | |
| 	<li> cuddTestInteract() | |
| 	<li> cuddInitInteract() | |
| 	</ul> | |
|   Static procedures included in this file: | |
| 	<ul> | |
| 	<li> ddSuppInteract() | |
| 	<li> ddClearLocal() | |
| 	<li> ddUpdateInteract() | |
| 	<li> ddClearGlobal() | |
| 	</ul> | |
|   The interaction matrix tells whether two variables are | |
|   both in the support of some function of the DD. The main use of the | |
|   interaction matrix is in the in-place swapping. Indeed, if two | |
|   variables do not interact, there is no arc connecting the two layers; | |
|   therefore, the swap can be performed in constant time, without | |
|   scanning the subtables. Another use of the interaction matrix is in | |
|   the computation of the lower bounds for sifting. Finally, the | |
|   interaction matrix can be used to speed up aggregation checks in | |
|   symmetric and group sifting.<p> | |
|   The computation of the interaction matrix is done with a series of | |
|   depth-first searches. The searches start from those nodes that have | |
|   only external references. The matrix is stored as a packed array of bits; | |
|   since it is symmetric, only the upper triangle is kept in memory. | |
|   As a final remark, we note that there may be variables that do | |
|   interact, but that for a given variable order have no arc connecting | |
|   their layers when they are adjacent.  For instance, in ite(a,b,c) with | |
|   the order a<b<c, b and c interact, but are not connected.] | |
|  | |
|   SeeAlso     [] | |
|  | |
|   Author      [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                                                     */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| #if SIZEOF_LONG == 8 | |
| #define BPL 64 | |
| #define LOGBPL 6 | |
| #else | |
| #define BPL 32 | |
| #define LOGBPL 5 | |
| #endif | |
|  | |
| /*---------------------------------------------------------------------------*/ | |
| /* Stucture declarations                                                     */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| 
 | |
| /*---------------------------------------------------------------------------*/ | |
| /* Type declarations                                                         */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| 
 | |
| /*---------------------------------------------------------------------------*/ | |
| /* Variable declarations                                                     */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| #ifndef lint | |
| static char rcsid[] DD_UNUSED = "$Id: cuddInteract.c,v 1.14 2012/02/05 01:07:19 fabio Exp $"; | |
| #endif | |
|  | |
| /*---------------------------------------------------------------------------*/ | |
| /* Macro declarations                                                        */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| 
 | |
| /**AutomaticStart*************************************************************/ | |
| 
 | |
| /*---------------------------------------------------------------------------*/ | |
| /* Static function prototypes                                                */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| static void ddSuppInteract (DdNode *f, char *support); | |
| static void ddClearLocal (DdNode *f); | |
| static void ddUpdateInteract (DdManager *table, char *support); | |
| static void ddClearGlobal (DdManager *table); | |
| 
 | |
| /**AutomaticEnd***************************************************************/ | |
| 
 | |
| 
 | |
| /*---------------------------------------------------------------------------*/ | |
| /* Definition of exported functions                                          */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| 
 | |
| /*---------------------------------------------------------------------------*/ | |
| /* Definition of internal functions                                          */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Set interaction matrix entries.] | |
|  | |
|   Description [Given a pair of variables 0 <= x < y < table->size, | |
|   sets the corresponding bit of the interaction matrix to 1.] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [] | |
|  | |
| ******************************************************************************/ | |
| void | |
| cuddSetInteract( | |
|   DdManager * table, | |
|   int  x, | |
|   int  y) | |
| { | |
|     int posn, word, bit; | |
| 
 | |
| #ifdef DD_DEBUG | |
|     assert(x < y); | |
|     assert(y < table->size); | |
|     assert(x >= 0); | |
| #endif | |
|  | |
|     posn = ((((table->size << 1) - x - 3) * x) >> 1) + y - 1; | |
|     word = posn >> LOGBPL; | |
|     bit = posn & (BPL-1); | |
|     table->interact[word] |= 1L << bit; | |
| 
 | |
| } /* end of cuddSetInteract */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Test interaction matrix entries.] | |
|  | |
|   Description [Given a pair of variables 0 <= x < y < table->size, | |
|   tests whether the corresponding bit of the interaction matrix is 1. | |
|   Returns the value of the bit.] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [] | |
|  | |
| ******************************************************************************/ | |
| int | |
| cuddTestInteract( | |
|   DdManager * table, | |
|   int  x, | |
|   int  y) | |
| { | |
|     int posn, word, bit, result; | |
| 
 | |
|     if (x > y) { | |
| 	int tmp = x; | |
| 	x = y; | |
| 	y = tmp; | |
|     } | |
| #ifdef DD_DEBUG | |
|     assert(x < y); | |
|     assert(y < table->size); | |
|     assert(x >= 0); | |
| #endif | |
|  | |
|     posn = ((((table->size << 1) - x - 3) * x) >> 1) + y - 1; | |
|     word = posn >> LOGBPL; | |
|     bit = posn & (BPL-1); | |
|     result = (table->interact[word] >> bit) & 1L; | |
|     return(result); | |
| 
 | |
| } /* end of cuddTestInteract */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Initializes the interaction matrix.] | |
|  | |
|   Description [Initializes the interaction matrix. The interaction | |
|   matrix is implemented as a bit vector storing the upper triangle of | |
|   the symmetric interaction matrix. The bit vector is kept in an array | |
|   of long integers. The computation is based on a series of depth-first | |
|   searches, one for each root of the DAG. Two flags are needed: The | |
|   local visited flag uses the LSB of the then pointer. The global | |
|   visited flag uses the LSB of the next pointer. | |
|   Returns 1 if successful; 0 otherwise.] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [] | |
|  | |
| ******************************************************************************/ | |
| int | |
| cuddInitInteract( | |
|   DdManager * table) | |
| { | |
|     int i,j; | |
|     unsigned long words; | |
|     long *interact; | |
|     char *support; | |
|     DdNode *f; | |
|     DdNode *sentinel = &(table->sentinel); | |
|     DdNodePtr *nodelist; | |
|     int slots; | |
|     unsigned long n = (unsigned long) table->size; | |
| 
 | |
|     words = ((n * (n-1)) >> (1 + LOGBPL)) + 1; | |
|     table->interact = interact = ALLOC(long,words); | |
|     if (interact == NULL) { | |
| 	table->errorCode = CUDD_MEMORY_OUT; | |
| 	return(0); | |
|     } | |
|     for (i = 0; i < words; i++) { | |
| 	interact[i] = 0; | |
|     } | |
| 
 | |
|     support = ALLOC(char,n); | |
|     if (support == NULL) { | |
| 	table->errorCode = CUDD_MEMORY_OUT; | |
| 	FREE(interact); | |
| 	return(0); | |
|     } | |
|     for (i = 0; i < n; i++) { | |
|         support[i] = 0; | |
|     } | |
| 
 | |
|     for (i = 0; i < n; i++) { | |
| 	nodelist = table->subtables[i].nodelist; | |
| 	slots = table->subtables[i].slots; | |
| 	for (j = 0; j < slots; j++) { | |
| 	    f = nodelist[j]; | |
| 	    while (f != sentinel) { | |
| 		/* A node is a root of the DAG if it cannot be | |
| 		** reached by nodes above it. If a node was never | |
| 		** reached during the previous depth-first searches, | |
| 		** then it is a root, and we start a new depth-first | |
| 		** search from it. | |
| 		*/ | |
| 		if (!Cudd_IsComplement(f->next)) { | |
| 		    ddSuppInteract(f,support); | |
| 		    ddClearLocal(f); | |
| 		    ddUpdateInteract(table,support); | |
| 		} | |
| 		f = Cudd_Regular(f->next); | |
| 	    } | |
| 	} | |
|     } | |
|     ddClearGlobal(table); | |
| 
 | |
|     FREE(support); | |
|     return(1); | |
| 
 | |
| } /* end of cuddInitInteract */ | |
| 
 | |
| 
 | |
| /*---------------------------------------------------------------------------*/ | |
| /* Definition of static functions                                            */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Find the support of f.] | |
|  | |
|   Description [Performs a DFS from f. Uses the LSB of the then pointer | |
|   as visited flag.] | |
|  | |
|   SideEffects [Accumulates in support the variables on which f depends.] | |
|  | |
|   SeeAlso     [] | |
|  | |
| ******************************************************************************/ | |
| static void | |
| ddSuppInteract( | |
|   DdNode * f, | |
|   char * support) | |
| { | |
|     if (cuddIsConstant(f) || Cudd_IsComplement(cuddT(f))) { | |
| 	return; | |
|     } | |
| 
 | |
|     support[f->index] = 1; | |
|     ddSuppInteract(cuddT(f),support); | |
|     ddSuppInteract(Cudd_Regular(cuddE(f)),support); | |
|     /* mark as visited */ | |
|     cuddT(f) = Cudd_Complement(cuddT(f)); | |
|     f->next = Cudd_Complement(f->next); | |
|     return; | |
| 
 | |
| } /* end of ddSuppInteract */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Performs a DFS from f, clearing the LSB of the then pointers.] | |
|  | |
|   Description [] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [] | |
|  | |
| ******************************************************************************/ | |
| static void | |
| ddClearLocal( | |
|   DdNode * f) | |
| { | |
|     if (cuddIsConstant(f) || !Cudd_IsComplement(cuddT(f))) { | |
| 	return; | |
|     } | |
|     /* clear visited flag */ | |
|     cuddT(f) = Cudd_Regular(cuddT(f)); | |
|     ddClearLocal(cuddT(f)); | |
|     ddClearLocal(Cudd_Regular(cuddE(f))); | |
|     return; | |
| 
 | |
| } /* end of ddClearLocal */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis [Marks as interacting all pairs of variables that appear in | |
|   support.] | |
|  | |
|   Description [If support[i] == support[j] == 1, sets the (i,j) entry | |
|   of the interaction matrix to 1.] | |
|  | |
|   SideEffects [Clears support.] | |
|  | |
|   SeeAlso     [] | |
|  | |
| ******************************************************************************/ | |
| static void | |
| ddUpdateInteract( | |
|   DdManager * table, | |
|   char * support) | |
| { | |
|     int i,j; | |
|     int n = table->size; | |
| 
 | |
|     for (i = 0; i < n-1; i++) { | |
| 	if (support[i] == 1) { | |
|             support[i] = 0; | |
| 	    for (j = i+1; j < n; j++) { | |
| 		if (support[j] == 1) { | |
| 		    cuddSetInteract(table,i,j); | |
| 		} | |
| 	    } | |
| 	} | |
|     } | |
|     support[n-1] = 0; | |
| 
 | |
| } /* end of ddUpdateInteract */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Scans the DD and clears the LSB of the next pointers.] | |
|  | |
|   Description [The LSB of the next pointers are used as markers to tell | |
|   whether a node was reached by at least one DFS. Once the interaction | |
|   matrix is built, these flags are reset.] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [] | |
|  | |
| ******************************************************************************/ | |
| static void | |
| ddClearGlobal( | |
|   DdManager * table) | |
| { | |
|     int i,j; | |
|     DdNode *f; | |
|     DdNode *sentinel = &(table->sentinel); | |
|     DdNodePtr *nodelist; | |
|     int slots; | |
| 
 | |
|     for (i = 0; i < table->size; i++) { | |
| 	nodelist = table->subtables[i].nodelist; | |
| 	slots = table->subtables[i].slots; | |
| 	for (j = 0; j < slots; j++) { | |
| 	    f = nodelist[j]; | |
| 	    while (f != sentinel) { | |
| 		f->next = Cudd_Regular(f->next); | |
| 		f = f->next; | |
| 	    } | |
| 	} | |
|     } | |
| 
 | |
| } /* end of ddClearGlobal */ | |
| 
 |